Adventures in GameDev with GameDevHQ, Day 11: Instantiating and destroying GameObjects in Unity.
So we have our ‘Spaceship’ and we can move it around the screen, now we need to shoot some lasers! As with the spaceship, we’re going to keep things simple and use Unitys own basic shapes. A capsule works well so let’s create one.
Whoa! That’s huge! That won’t do, fortunately as you recall, the transform holds information on position, rotation, and scaling. We’re going to want to scale this object down, let’s say to .2 on each axis.
That’s much better and actually looks more lasery! remember to rename it to Laser in the heirarchy panel.
PREFABS:
Unitys prefab system allows you to create clones of an object. For something like lasers, it’s perfect to just have one master laser, and then spawn a clone of one whenever the player presses the fire button instead of creating a new one on the fly which would take up way more resources than necessary. Why do the work of building up a new lasercapsule every time you need it when one’s already available and you can just pull it out of the box? So let’s make our laser a prefab!
Make a directory in your project menu and call it Prefabs
And then drag the Laser object from the heirarchy panel into it.
The Laser object turns blue letting you know you’re now working on an instance of an original prefab and the original is safely stored in the project menu.
We can verify this by deleting the laser and then pulling a new one out!
Ok, so now that we’ve got a laser prefab safe in our project, go ahead and delete the one on screen. We’ll get back to the prefab soon.
Doing a bit of research on how to spawn an object in unity, we learn there’s a command called Instantiate and it clones the original and returns the clone back to Unity.
So where will we be instantiating from? Well, it makes sense to instantiate from the player script since it’s the player where we will be doing the ‘firing’ from. We’ll be creating a reference to the prefab inside of our player script with a variable called laser_prefab:
As you recall, when a variable is public, you can access it via Unitys editor and if we take a look at it, it’s empty. That’s because we just created a box for us to put the laser prefab into, so let’s do that.
Now there’s an actual reference to the laser our Player script can access! Just a quick tip, there’s no reason for the laser_prefab to be a public variable since only the player will be working with it, so let’s change it to a private variable. If we still need to change the laser prefab with maybe a new appropriate model later, we can make it accessible in the editor using the [SerializeField] attribute.
Now we can use instantiate to spawn the laser, let’s take a quick look at the unity page about it.
Ok, so if we want to instantiate an object, we’ll just need to type Instantiate and (_laser_prefab) to get it on the screen but since we want the player to press space to do it, we’ll need to check our Input Key of space. We went over this in simple player movement, but in this case, we’re going to be checking space.
Since we’ll want this to be in our gameloop that’s running constantly, let’s work directly under Update for now. Everything is looking good, let’s give it a try!
Well, it’s kind of working. The laser prefabs ARE being instantiating, but they’re just being spawned at origin 0,0,0. We want them to spawn by our player. Looking back at the instantiate page, it looks like the 4th option where we give it the object, the vector3 location and Quaternion location is what we need, so let’s try that. (By the way, we use Quaternion.identity as its rotation. Quaternion Identity is just the Euler angle of the object, or the default rotation x,y,z of your object.)
Looks good! Let’s see it in action!
PERFECT!
Now to get the lasers moving! And if you recall from player movement the other day, it’s easy! But this time, we’ll be doing this from a script running in laser. It wouldn’t really make sense to put the script anywhere else. Every object should have its own controller script, or as Jonathan Weinberger puts it, “Every Object will be a behavior of some sort”.
But our lasers a prefab! Don’t worry, we can still make changes in a variety of ways. We can use ‘override’ or go directly into the prefab by double clicking it and going into LookDev view. Let’s do the former. Create a script in the scripts directory called Laser. drag a prefab of the laser onto the scene and then drag the script onto it, then select the laser and in the upper right of the inspector panel, you’ll see an option called override. select it
Great! Now to get those lasers moving! I’ll just post the code, if you want to know more about movement, just head on over to day 8 for a more detailed look. But as you recall, we’ll want to use our transform.position command on the y axis and just keep adding to it. We’ll use a speed variable set to 8 to get our laser moving somewhat quickly.
looks good! Now let’s see it in action!
AW YEAH! WE GOT A GAME NOW!
Well, not really but it’s pretty exciting that we’ve come this far!
There’s just one more issue we need to address. If you notice that every time we shoot and instantiate a laser, it’s staying and it will stay forever moving up for as long as the game is running. As you can guess, we’re going to be shooting a lot of lasers and Unity is keeping track of each and every one of them. Eventually, this is going to lag our game down probably to the point of unplayability! We can help Unity by telling it to go ahead and destroy the laser GameObject once it’s off the screen. There’s a variety of ways we can do this, but the most direct method is dragging a laser prefab out into the scene, dragging it up to the top of the game area, and looking at the y position number.
In my case, 6.11 seems to be the top of the screen where the laser reaches the top. Since I want the laser destroyed off the screen, i’ll just add one more unit and make the number 7.11
doing a search on how to destroy game objects gives us the Destroy() command. Simple enough, we can use an if/then statement in the lasers script to check once the laser reaches that point or beyond, it gets destroyed.
you don’t really need the ‘this’ in this.gameObject, but it helps us understand that it’s going to be this particular laser that gets destroyed and not say the player or any other GameObject.
Ok, let’s see if it works!
Excellent! the lasers are being destroyed once they’re off the screen!
Just one more minor thing, the lasers are coming out of the player and we want it to come out in front of the player.
We know that the laser is being instantiated as part of the player so let’s drag a laser out and make it a child of the player and set it at 0,0,0
This gives us a perfect reference of how much we’ll need to add to the y axis so let’s move the laser up and make a note of the y axis position.
The y is .79 so we can round it up to .8 that we’ll need to add in the instantiate command.
So we take our transform position and add a new Vector3(x,y,z) where the y is .8f so it adds .8 to the instantiate position which is 0,0,0.
Why do we need to use new before the Vector3? Vector3 seems to be a built in structure of unity so when we use it, we kind of need to instantiate a Vector3 to use for ourselves! It’s the great circle of programming life!
So let’s see if it actually works…
Yes it does! And with this, we conclude todays lesson! Tomorrow we’ll go over giving our firing a ‘cooldown’ period since we don’t want our player to abuse our laser cannon and control how many times they can actually fire.