Our first step is to get some graphics so we can have something to interact with. All we need to start is something to represent an enemy, so I opened paint.net, created a new image that was 64×64 pixels, used the circle tool to draw a circle and filled it in with a color
You don’t need to use paint.net, any editing tool will suffice, but make sure to export to a format that supports transparency. I chose .png
Once you have your png file ready create a new folder under assets called Art and drop your png into it. Rename it to “Enemy”. If we had set the project up as a 3d project the image would be imported as a texture, but because we selected 2d it’s imported as a sprite.
The image type can be changed at any time by clicking the Enemy image in the project view and changing the settings via the inspector window.
In the first part we were working with the canvas tools and the unity GUI system to create our controls. We won’t be using it for the next few steps. This might get confusing, so bear with me for a bit. What we had before was our canvas view, which if you remember, we enabled by selecting the canvas in the transform toolbar.
Now we want to switch out of canvas mode and back to something like the pan icon. In the hierarchy view there is an object called the Main Camera that we’ve ignored up until now. Double click that. You’ll see that we have just been zoomed into the very bottom left corner of our canvas where we see another square with a camera icon inside it.
Everything inside this square is what is being drawn on the screen at runtime. The canvas exists in a special design time space where we can edit it without relation to what our camera is actually looking at and It will get rendered in a way that fits in to the view of the camera when we run the game. There are more advanced ways you can combine the camera and uGui canvas to create some really cool effects, but that’s outside the scope of this project.
If you need to visualize what I’m talking about, you can drag your enemy image into one of the quadrants displayed, and run the game. You’ll see your image drawn in the corresponding location on the screen.
You can see in the camera preview where the image will show up when we run, and when we run we see this
Having 1 image on the screen doesn’t really do anything for us though. We need to be able to create many images over time while the game is running. To do that we need to create what’s called a prefab. A prefab is essentially a template representing a game object we want to create in the scene. To create a prefab we just need to drag the enemy image we added to the Hierarchy view back into the project view.
You’ll notice that prefabs are represented by a blue cube, and game objects that are tied to a prefab are denoted by the blue text.
Any changes made to a prefab will affect all game objects in the scene that are linked to the prefab, and alternatively you can make changes to an instance of a prefab in the scene and use the apply button in the inspector window to apply those changes back to the prefab, which will then apply them to other instances of the prefab.
You can also use the revert button to restore the game object back to the same state as the prefab.
Now that we have a prefab, we can instantiate a prefab on the fly. We’re going to write some code that we’ll later throw away in order to test this and the next features that we’ll add to make this image into an actual enemy. I only say throw away in the sense that we’re going to spawn our enemies manually via mouse clicks, but in the final game we want the enemies to appear on their own.
First we’ll add a new script and add it to our System game object. Right click inside our scripts folder and create a new C# script called EnemySpawner and double click it to open in the editor.
Unity comes with two commonly used methods for us to use. There are many other methods that come from inheriting MonoBehaviour that can be seen by reading the documentation.
For our purposes we only need update. We’re going to add a public GameObject variable that will be the prefab that we want to instantiate, and in the update method we’ll check to see if the player has clicked the mouse. If they have then we’ll instantiate the prefab at the location they clicked.
What’s happening here is that we’ve declared the prefab that we’re going to instantiate, then in the Update method which is called once per frame of animation we check to see if the right mouse button has been pressed. If it has, then we instantiate the prefab at the where we clicked based on the perspective of the camera. We override the z value, since this is a 2d game and our perspective is flat we have no use for depth. A value of 2 puts the object just a little bit in front of the camera so it will be seen.
All that’s left is to add it to the System object and assign the enemy prefab to the variable on the script component
When you run the game, you’ll see that everywhere you click the enemy prefab is added to the scene. That’s what the GameObject.Instantiate method does for us.
For the next part we’ll do something simple and make each enemy move down the screen.
To do this we’ll be creating a new script called EnemyMovement which will have 1 public member, speed, and each frame will update the position of the game objects transform component.
Your script should look like this
The public value should be self-explanatory by this point. The code in the update function takes the increments the transform.position, which is a Vector3 representing the x, y, z position in 3d space. Since we’re making a 2d game the z value doesn’t change. We’re adding Vector3.down, which is a vector where x = 0, y = -1, and z = 0. multiply by the speed, so if our speed is 2 the value is now (0, -2, 0). Multiply time.delta, which is a value representing the time since the last frame update. The update function gets called once per frame, and we want our speed to represent a units per second value that moves smoothly regardless of our frame rate. Using the Time.deltaTime modifier allows us to maintain that smoothness.
Select the prefab and add our new script as a component of the prefab and set the speed to 2.
When you run the game now your enemies should be falling down the screen.
Now we need to be able to destroy the enemies. Since this is a mobile game we want to operate on Touch input unity provides the Input.Touch mechanism for this.
We’ll add a new script to the System object called EnemyHitDetection. It’s going to detect if we are touching the screen, or in the case of our tests here, pressing the left mouse button.
It uses the SendMessage construct to call a method on the object that we’ve hit. Physics2D.OverlapCircle takes a point and radius and returns a Collider that was found intersecting with that point. Colliders are a type of game component that are used in unity’s physics calculations and checks. We’ll be adding one to our Enemy prefab as well as the following script EnemyHitHandler which will hold the OnHit message we’re calling here.
In the unity editor, select the Enemy prefab that we’ve been working with and add the EnemyHitHandler script, as well as a BoxCollider2D component.
The box collider enable us to detect that we’ve touched / clicked the enemy. It’s important for our use to make sure that Is Trigger is set to on. When a collider is a trigger it doesn’t react to any responsive physics such as bouncing off objects. Since we’re handling the movement ourselves without any kind of gravity or force affecting the enemies we want the collision to only exist in a non-interactive way.
Add the EnemyHitDetection script to the System object and we’ll be good to go with our next test.
Now when we launch the game and spawn some enemies, if we’re holding the left mouse button down and swiping across the enemies they should be getting destroyed.
Now that we’ve got that the only thing left is for the enemy to deal damage to the player. This will be done by detecting when the enemy goes back off the screen, and both destroying the enemy and decrementing a health counter that we’ll track for the duration of the game.
First we’ll add a simple bit of code to the EnemyMovement script to detect if the enemy is still visible or not. If it’s not visible we’re going to destroy the enemy and send a message to system that this particular enemy has gotten past the player.
If you’ll look at your enemy prefab you’ll see that there’s a component called a Sprite Renderer
Anything that’s visible has a Renderer component which is accessible in code via the renderer available that we get for being a MonoBehaviour component in unity. Using GameObject.Find to get the object in our scene named System we then use SendMessage to call DamagePlayer. Alternatively we could have called GetComponent on the system gameobject to get the GameInfo component and called the method directly.
We’ll add a new script called GameInfo and add it to the System. This will track the player’s health and handle the DamagePlayer message being broadcast. Later we’ll use this to track the score as well.
For now we’ll quit but later on we need to come back here after we add a game over screen. For now add this to System and set the player health to 5 in the editor then let’s run the game to make sure that the health decrements correctly after each enemy reaches the bottom and that the game closes once we’re dead.