Plants vs Zombies in Unity using Bolt (Part 1)
Bolt is an Unity Asset that allows you to create logic in Unity visually. Without writing any line of code you can “make stuff happen“. Some of you might know that I love visual tools having covered in the past FlowCanvas. Ever since Bolt came out I wanted to test it but I decided to wait a bit because at the time of writing this Bolt is only 4 months old and there were a couple of features that were not implemented yet. I was mostly waiting for the drag & drop feature, which I do have to say that as of version 1.2 is implemented 🙂
I’m simply amazed on how fast the development of Bolt is happening so I decided to split my tutorial in multiple parts as I am also learning how Bolt works. So don’t that what you see here is “the way to do it”, take it more like a start point. Also because things are evolving fast some things might be a bit different so make sure you will also check my latest tutorials.
The installation of Bolt is pretty easy and it’s also explained in the manual. I do have to mention one thing. I love the fact that you can pick up a Naming Scheme for the Bolt nodes. You have this “Human & Programmer” naming. Since I’m a guy that wants to learn the exact API & programming terms I chose the Programmer Naming. However if you are only interested in Bold and how to use Bolt or maybe you are not “that technical” you can chose the Human Naming. This is really really great!
read more below
This is how the “game” looks right now:
We have the grass tiles and 2 UI buttons with the flowers that we can build.
The GrassTiles are actual game objects that I organized and placed myself. On them I set up a 2D Box Collider and I made sure to check the “Trigger” box. We want the collider to be a trigger so we can see when we clicked on it. As you can see the “On Mouse Down” is an Event that will trigger when the “Mouse will be down” 😀 When that happens we will do a “Custom Event Trigger” and we will send 1 Argument. It says 25551 there but that’s because that when I want to take a screenshot I have to press the “shift” key and when I do that Bolt is putting that number there. No idea why.
One thing that is important here is that “FindGameObjectWithTag”. The reason why we are doing this and the reason why we are not just referencing our Game_Manager from the Scene is because our Flow Machine is of type MACRO. That means it’s an actual Asset file that we can use on multiple scenes. Asset files in Unity can’t have references to the scenes.
So we set up our Game_Manager to have the tag “GameManager”. It will be the only GameObject that will have that Tag.
So we trigger the event “grassTileClicked” in the Game_Manager and we send the Argument that is actually … “Self”. The Grass Tile is sending HIMSELF over to the Game_Manager in form of a GameObject. We will use this GameObject later. Basically we need to know which Grass Tile we clicked so this is why we are doing this.
Flower UI Buttons
Both of the UI Buttons have this Flow Machine. Of course that is of type “Macro” because we want to use the same Flow on both of the button. What happens here is that when the button get’s clicked we do a “Custom Trigger Event”. We send this event “flowerUIClicked” to our Game_Manager. We trigger that event and we send 1 argument.
The argument itself is … the name of the GameObject. We don’t want to send the GameObject itself, because that will mean that we send the button itself. We only want to know the name of the button that you clicked. Sunflower or Firingplant.
This is the flowerUIClicked custom event that we have in our Game_Manager. This is what it’s being called when we click on either of the plant buttons. There is a small bug here that I still have to fix. I actually found it while I was recording the tutorial 😀 If you click a plant, that flow from above will happen. If you click another button again, we have a small problem as the first plant that we clicked will still be instantiated so we have to destroy it. Probably I will have to do a small check to see if the variable “plantToBuild” has already been set up, if it was, I will need to clear it first then I will let you click the button again.
Anyway, let’s see what the above code is doing exactly. Well, we are doing a DebugLog. This DebugLog is a “Super Unit” meaning that it’s actually a “Flow within a Flow”. A Macro!! It looks like this:
The graph itself is kind of simple. And it is actually very simple. The reason why I choose to screenshot more is so you can see the Graph Inspector, that thing on the right. Since this is a macro, it can accept an INPUT and an OUTPUT. Those get setup in that Graph Inspector you see there on the right. On the input we have a “Log” and the value Input is called “Message” and is of type STRING. The Output is just a key, we don’t output anything because what we want to do we actually do right in this graph.
So we INPUT a string, then we do a Debug.Log and we display that String. And that’s all actually.
It was a small way for me to only have one node in my main Game_Manager. Normally the Debug Log requires me to input a String there if I want to write my own message, so I would need to have two nodes, the one for the DebugLog and the one for the String. Now my String Message is actually on the DebugLog. You can’t see it in the screenshot above because my string is being supplied by the argument we receive when we do “flowerUIClicked”. As you might have guessed, we will DebugLog the plant that we just clicked 🙂
After this we have another “Super Unity” called findPlant which also has an input of a String.
This one was a little bit challenging for me even that it looks easy 😀
So this is what we want to accomplish. We know what plant we want to build because we have that String that we got when we clicked the button. It will be either a Sunflower or a Firingplant (for now). I need a way to associate those two strings with the prefab of the plants that I already created. Right now those prefabs are just a simple sprite, but later they will have their own logic.
So how do I do it? Well, in the video from above I went into full details about the adventures I had with this but I will try to keep the written tutorial simple. We are going to use a Select on String. This is a “Control” flow. That node accepts multiple strings inputs. That Select on String will check the string that we just receive than it will do all the nodes from the left of it and it will send that to our Output. Ah, we are going to output a GameObject.
Let me explain again. You click a plant, we know that you clicked on the “Sunflower” plant. We will “findPlant” and take that string (Sunflower) and we will INSTANTIATE the “Sunflower” Prefab and we are going to pass it in our Output.
Now look back at the whole graph from above. The one from the GameManager.
After we found our plant, we set up the variable “plantToBuild” to that GameObject then we set the variable “plantUIClicked” to True. Why? Well… see below:
Late Update – Plant Follow Cursor
Late Update runs all the time. We don’t want that code from the right to run all the time because sometimes the “plantToBuild” is null and this will generate errors. So that’s why we have that Branch that checks if the “platUIClicked” is true. What happens here pretty simple. We have the “followTheCursor” Super Unity … that requires an Input of type GameObject. In our case we actually input our “plantToBuild”.
Now let’s look at the “followTheCursor” and see what this does:
Don’t worry, it’s not really that complicated. What we want to accomplish here is to get our plant that we just clicked from the UI button, and make that plant follow our cursor. The key thing in this flow is of course, the GameObject (The Plant) that we just instantiated in the “findPlant” Flow and the Input.mousePosition node.
We do all those by using the Transform.Position node. That one requires a Vector3. But there are some small problems that we have to fix. We can’t just take the Input.mousePosition and pass it along. We need to convert that Vector3 to Camera.ScreenToWorldPoint.
In that node we also have to specify which Camera. Since this is a Macro we can’t drag & drop our camera into the flow, so we use a Unity function called Camera.main. That function takes our Main Camera.
So we go that and it was all good… except that I coudn’t see my Plant. I saw in the Hierarchy that the plant instantiated but I coudn’t see the plant. When I moved the cursor to click the plant in the hierarchy my plant appeared on the Scene window. I loled a bit. It was clear that the plant was instantiated and it was following my cursor, but it wasn’t in the right spot. And then it hit me. All my objects are at 0 on the Z axis. However the camera is sitting at -10 on the Z axis…so my Sprite was moving on the -10 on the Z axis. So I decided to see how can I “explode” that Vector3. In FlowCanvas we have a node called Extract Vector3 … where that is called Expose Vector3 and as you can see in that big node, you can target all those Vector3 options.
So I created a new Vector3. I left the Z at 0 then I took the X & Y from the Expoded Vector3. Then I passed that new Vector3 into our Transfor.Position. And guess what?