Preparing the scene and the game objects
First, we need to create a new Unity project. Call it Collisions and Deleting Objects and select the 2D option. Download all the following graphics or you can create your own but be sure to use the same file names. Note that the four wall graphics are significantly scaled-down (shrunk) in their appearance, for the purposes of display on the Web page. When you download them you will see they are actually quite large (1000 pixels wide/high). Also note that the bumpy-bat.png graphic is blue but the screen-shots from the projects it is white. This just makes it easier for you to see and download.
You can download the files by right-clicking on each in turn and selecting Save image as…
In Unity, add each of the graphics to the project by right-clicking in the Project window and selecting Import New Asset… Do this to each of the graphics. Your project window should now look like this next image.
One at a time, drag each of the assets from the Project window to the Hierarchy window in order to create the necessary game objects.
Tip: It might be worth reading ahead the next two paragraphs and two images to see the intended result. It might be slightly simpler to arrange the Scene window as and when you add each object. The Hierarchy window should now look like this.
Rearrange the objects in the Scene window so they look like this next image. To do so, select move mode by pressing W, then select and move each object in turn by dragging them using their horizontal and vertical arrows. Your scene does not need to look exactly the same but fairly similar and with an enclosed area so nothing can “escape” the four walls.
At this point you could run the game and see our scene just sitting there, motionless. Let’s bring it all to life.
Adding RidgidBody2D components
As we have seen in previous projects, if we want a game object to interact with the Unity physics system then it needs a RigidBody2D component. In this project we want all of our objects to interact so we will add a RigidBody2D component to each one in turn.
Identify the first of the objects that we added in the Hierarchy window. This is bottom-wall. Left-click it to select it and then in the Inspector window click Add Component and choose Physics 2D | RigidBody2D.
Now do exactly the same for bumpy-bat, destroyer, left-wall, particle, right-wall and top-wall. All our added objects now have a RigidBody2d component.
Run the game and the entire scene should slide away as the Unity engine applies gravity.
Now we will configure all the objects to stay where they are. You might remember from previous tutorials that we can check the Is Kinematic check box, like we did to stop our spaceship from falling into oblivion in the Adding a controllable player object in Unity 2D. We will do this for all the objects except for particle, because we want particles to fall and bounce. Go ahead and check the Is Kinematic checkbox for all the objects except for particle. Select the objects one at a time and check the box as shown in the next image.
Tip: Later in the tutorial we will need to change one of these settings. I will explain why when we get to it. For now, making them all Kinematic except for particle achieves what we need.
Now, if you run the game, only particle will fall. The issue we have now is that the particle falls straight through the bat and the walls. Let’s fix that by adding Collider components
Making Unity objects bump with Colliders
There are several different types of colliders for 2D objects and we will see three of them next. The quickest and easiest collider to add for any game object, that is shaped like a square or rectangle, is a Box Collider 2D. It just so happens that each of the four walls and the destroyer object are nicely shaped rectangles. We will add a Box Collider 2D to each.
Select the bottom-wall object then click the Add Component button in the Inspector Window. Choose Physics 2d | Box Collider 2D. Do the same for each of the other three walls and the destroyer object.
If you ran the game at this point, you might be disappointed to see the particle object still falls through the wall at the bottom. We can fix this by adding a Collider component to the particle. We will add a Circle Collider 2d.
Select the particle object then click Add Component. Now choose Physics 2D | Circle Collider 2D. Now you can run the game and see the particle object come to rest on the bottom-wall object. This is shown in the next image.
We want our particles to be much more erratic and bouncy. We can do this by adding a Physics2D 2D material to particle.
Creating and adding a Physics2D Material to an object
First, we can create the material. Right-click in the Project window and choose Create | Physics2D Material. Now in the Inspector window set the properties of our new Physics2D Material to these values:
Friction = 0
Bounciness = 1.1
Here is an image so you can see exactly what is happening in the previous step.
What we have done is create a new material with physical attributes, however, we are not actually using that material anywhere. What we need to do is tell Unity that our particle object is made from this material. The particle object will then have its properties of friction(none) and bounciness(loads).
In the Hierarchy window left-click particle to make sure it is selected and you can see its details in the Inspector window. Now, drag New Physics2D Material from the Project window to the Material field of the Circle Collider 2D component of the particle object and drop it. This next image shows (as clearly as possible) this step in progress.
Now you can run the game and see the particle bouncing up and down with increasing power. This is because each bounce reverses and multiplies the velocity by 1.1 and as friction is zero, nothing can stop it. Eventually, it will seem to “phase” through a wall because it is too fast to be detected by the physics system.
Let’s make our bumpy-bat object bouncy too. Then the particle can be made to bounce more interestingly, by the player.
Using Polygon Collider 2D
Left-click bumpy-bat in the Hierarchy window and then click the Add Component button in the Inspector window. Select Physics 2D | Polygon Collider 2D. Observe how the irregular shape of the bumpy-bat object is neatly wrapped in a collider. This means Unity will accurately detect collisions based on the shape of the object not just a simple rectangle wrapping the object. Note that the polygon-based collider will use more system resources than a rectangle or circle-based collider. With a project this small the extra resources are totally irrelevant but it is worth being aware of because one day your games might have dozens, hundreds, or perhaps thousands of objects. This is what bumpy-bat looks like with the Polygon Collider 2D component.
Now run the game again and see the particle bouncing at much more interesting angles. Depending upon the exact positioning of bumpy-bat, relative to particle, it might still bounce straight up and down. If this happens, position bumpy-bat in the Scene window with one of its sloping edges, directly below particle.
Let’s make destroyer and bumpy-bat controllable.
Adding player controls
This will be quite a quick section because we have seen this code before in the Adding a controllable player object in Unity 2D project. Select the bumpy-bat object in the Hierarchy window. Click Add Component in the Inspector and choose New Script. Name the script Controller and click Create and Add.
In the Inspector window, on the component we just added, click the gear icon and choose Edit Script. MonoDevelop will open and we can add some code.
Edit the code in the Controller script so it looks exactly like this next code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
using UnityEngine; using System.Collections; public class Controller : MonoBehaviour { float speed = 10f; // Use this for initialization void Start () { } // Update is called once per frame void Update () { // What is the player doing with the controls? Vector3 move = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0); // Update the bat position each frame transform.position += move * speed * Time.deltaTime; } } |
I am not going to go through the code line by line because it is exactly the same as the code we wrote in the Adding a controllable player object in Unity 2D project. A full explanation can be found there. Run the game and try moving bumpy-bat around with the cursor keys.
Reusing the Controller script
We want the destroyer object to move simultaneously with the bumpy-bat object. We can actually add the exact same code to the destroyer object. I don’t mean we can copy & paste the same code to a new script, I mean we can use the exact same script.
Select the destroyer object in the Hierarchy window. Now click Add Component in the Inspector window. Choose Scripts | Controller. That’s it! Run the game and you will see that the destroyer object mirrors the movement of the bumpy-bat object.
There are two things left to do.
- Spawn a particle object for every mouse click
- Destroy a particle object each time one bumps into the destroyer object
Spawning particles on mouse clicks
As with the last script, I will not go into great detail about the code in this section. This is because we have seen the near-identical code in the Spawning new objects in Unity project. There is, however, something subtly but significantly different between this project and the previous project. Let’s talk about Unity prefabs.
Unity Prefabs
All the objects in the Hierarchy window are real, instantiated objects, that are part of our game. If this sounds odd go and familiarize yourself with the Object oriented programming with C# tutorial.
In the Spawning new objects in Unity project, every time we clicked the mouse we spawned another bob object. We had a public bob that was connected to the bob object in the Hierarchy window. The spawning code only worked because the bob object already existed! As we will be destroying particles we cannot rely on the particle object existing whenever we need it to be there. We need another way, another blueprint for a particle, that does not rely on the existence of the original particle object, that we placed in the scene, via the Hierarchy window.
This makes sense if you think about it. What if we need 100 zombies to come rushing out of the forest? Using the techniques we have deployed so far, we would already have to have a zombie in the scene. What if we have multiple different types of zombies? We would then need one of each type, already in the scene, in order to spawn the rest.
We can create an object, just like we have the particle, and then from that object, create a prefab that can be used as a blueprint, to make as many objects as we need. We can use the blueprint/prefab whenever we like, regardless of whether there are existing objects of that type already in the scene/game/Hierarchy window. This is how we make a prefab.
Identify the particle object in the Hierarchy window. Drag and drop the particle object into the Project window. Congratulations! You now have a prefab, a blueprint we can use to create as many particle objects as we like. This image shows the particle prefab in the Project window.
Left-click it and check the Inspector window to confirm to yourself that it has all the exact same components and materials that our particle object(in the Hierarchy window) has.
Delete the particle object in the Hierarchy window because we don’t need it anymore. You can do this by right-clicking and choosing Delete.
Run the game and as expected, the particle object is gone. We can now see how to spawn particle objects from the particle prefab. This process and code is almost identical to how we spawned bob objects in the Spawning new objects in Unity project.
Spawning objects from prefabs
Just as we did in the previous project, we want an empty game object to detect mouse clicks and take action. You might remember that for the script to work it needs to be attached to a game object. Right-click in the Hierarchy window and select Create Empty… Rename the new game object to ClickHandler.
Tip: You might need to un-check the checkbox next to the new object’s name in order to rename it and then re-check it afterward. Actually, it doesn’t matter what this empty object is called, it will still work. Don’t sweat what it is called too much as long as you attach the script we are about to write, all will be well!
Next, we will write the script. Make sure ClickHandler is selected in the Hierarchy window then click Add Component in the Inspector window. Choose Script | New Script and name it ClickHandler, then click Create and Add. Open the script to edit it and change the code to look exactly like this next code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
using UnityEngine; using System.Collections; public class ClickHandler : MonoBehaviour { public GameObject particle; // Update is called once per frame void Update () { if (Input.GetMouseButtonDown (0)) SpawnParticle (); } void SpawnParticle(){ // Where should we spawn Bob? Vector3 clickPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition); clickPosition.z = 0; // Now we can actually spawn a bob object Instantiate(particle, clickPosition, Quaternion.identity); } } |
This code is nearly identical to the code in the Spawning new objects in Unity project. Please refer back if you want a refresher on how it works.
At this point, you should have a new game object called ClickHandler with a component, which is a script also called ClickHandler.
Now identify the particle prefab in the Project window (Not the particle sprite which is just above it). Drag and drop the particle prefab onto the Particle field of the ClickHandler script component in the Inspector window. This image shows exactly where to do this.
You can now run the game and go crazy spawning particles by left-clicking. Move the bat around to influence and “stir-up” the particles.
All we need to do now is see how to destroy those objects when they hit the destroyer object.
Destroying game objects
It is likely at this point, that you have worked out for yourself, that we need to write a script for the destroyer object. This is absolutely correct. We need to find out the following:
- Has something touched the destroyer?
- Is that something a particle?
- If so, destroy it
The first thing to do is to let Unity know that if something touches the destroyer WE want to decide what happens. Normally Unity will merrily continue applying the laws of physics and things keep on bouncing.
The way we take control of this is to make the Box Collider 2D on the destroyer object a Trigger. Select the destroyer object in the Hierarchy window. Now identify the Is Trigger checkbox on the Box Collider 2D component in the Inspector window. Check the Is Trigger checkbox.
Now we can add a script to destroyer. Make sure destroyer is selected in the Hierarchy window then click Add Component in the Inspector window. Choose Script | New Script and name it CollisionHandler, then click Create and Add. Open the script to edit it and change the code to look exactly like this next code.
void OnTriggerEnter2D(Collider2D o){ if (o.tag == "particle") { Destroy (o.gameObject); } }
As this code is new, let’s talk about it. As you can see we have deleted the default methods that Unity adds for us and added one of our own. The OnTriggerEnter2D method is called by the game engine every time a collider (that is also a trigger) collides with ANY other object. The object collided with is passed into the method and can be referred to/used using o, as detailed in the method’s one and only parameter.
The line if (o.tag == "particle") checks to see whether the current object has a tag that is equal to “particle”. If it does the line of code inside the if statement deletes the object with the code Destroy (o.gameObject).
The only other thing to explain is, where did this tag thing suddenly appear? Every game object in Unity can be tagged. It is a way we can use to identify different types of object. So what we need to do now is add a tag to the particle prefab and then every particle that collides with destroyer will get destroyed.
Tip: Actually there is one small detail to take care of after adding a tag ;-).
Adding a tag to a prefab
Select the particle prefab in the Project window. Now click the Untagged button in the Tag field, right at the top of the Inspector window. This next image will help identify where to do this.
Now follow these steps carefully:
- Select Add Tag
- Click the + icon
- Type particle in the New Tag field
- Select the particle prefab in the Project window
- Click the Untagged button at the top of the Inspector window
- Click particle
That’s it. All our particle objects will now have a “particle” tag and be identified and destroyed by the CollisionHandler script.
Kinematic objects do not respond to triggers
You can run the game now…. and notice that it doesn’t work. Sigh! The final issue is quick and easily explained. Remember at the start of the project we set everything to Is Kinematic, including the destroyer object. This might at first seem like a problem. If we remove the Is Kinematic setting from the object it will fall in to oblivion. We can control the gravity applied to the destroyer object another way.
Make sure the destroyer object is selected in the Hierarchy window and then un-check Is Kinematic and set Gravity Scale to zero. This image should help.
By setting Gravity Scale to zero we prevent the destroyer object from falling, allowing us to un-check Is Kinematic and complete the project. You can run the project and create bazillions of particle objects, bounce them around with bumpy-bat, and destroy them with destroyer.
Watch the Hierarchy window as particle instances are added and removed from the game.
In the previous image, you can see that Unity refers to the particle instances as clones. Clones of the particle prefab.
Our next project will be looking at GUIs and persisting player data to handle things like high scores and more. I hope you enjoyed the project. Keep coding!
Why does the bumpy-bat1 go through the walls? And is there any way to stop the particles going through walls?
The bumpy bat goes through the wall because it is kinematic. The particles will go through the walls eventually because they get faster and faster until eventually, they teleport straight past the colliders. It is possible to increase the sensitivity of detection by changing the collision detection on the colliders to continuous instead of discrete but a better solution would be to control/limit the speed and force applied to the particles. In the Asteroids game, we see a different way than we used in this tutorial.