Bullet Hell Using Object Pooling
In the previous article, I covered how to Create a Boss Fight with Multiple Phases, and demonstrated phase 3 as an example. Today’s article will discuss the first two scripts for Phase 1 and 2 of the Boss Fight.
Objective: Create an attack that fires projectiles in multiple directions at once by using object pooling.
Note: If you’re following along to create a Boss Fight with multiple phases, check out this article!
Projectile Script
The First Script we’ll be creating is the Projectile Script. This will be attached to your projectile object and will be responsible for its movement, invoke, and destroy.
Note: Make sure your projectile object is all set with a Rigidbody component and a collider box or circle.
- Add global variables for the movement.
2. Set the movement speed in the Start function.
3. In the Update, we’ll be adding de transform’s/objects movement. The direction is calculated from the script object but the direction will be coded later when the projectile is being fired.
4. Create a method to “Destroy” the object.
The way the destruction of this object works is by deactivating it and setting it active whenever it is needed. Kind of like a switch turning on and off. You can see this in the image below if you look at the Hierarchy.
This is made possible through Object Pooling.
Object Pooling pre-instantiates all the objects you’ll need at any specific moment before gameplay. This removes the need to create new objects or destroy old ones while the game is running. It works by creating a set amount of GameObjects before the game’s runtime and inactivates or activates the GameObjects required, effectively just recycling the GameObject and never destroying it.
5. Next, we are going to set an OnEnable function, and an OnDisable function. These functions, like the Update and the Start, will automatically execute per their name: When the object is set to active or inactive(disabled).
- The OnEnable function counts down to 3 seconds and then destroys our object.
- Invoke calls the methods within the given time. The method is called by writing its name as a string. This Destroy method is the same one we created in step 4.
6. Now, we create the aforementioned OnDesable function. When the object has been disabled, we cancel the invoke to avoid issues in which an inactive object cannot be accessed for invocation.
7. Lastly, we set the movement direction. This is made public because we’ll use script communication to access this from the Bulle Hell Attack Script. You'll see this logic later.
Note: Since this is the script attached to the projectile object, I also added the damaged logic for this attack to hurt the Player. This is optional but I wanted to share it as it plays a role in my script.
The Projectile Pool Script
This next script will be added to an empty game object. Its purpose is to add more projectiles when necessary.
- Add global variables
Note: OmniShot is the name of my projectile object and OmniShotPool is the empty game object to which this script is attached to.
- The first variable is a static type, which is the type of variable often used for object pooling. Unlike a Game Object prefab, a static variable cannot be instantiated. Instead, we use instances of the variable.
- The pooledOmnishot represents the projectile object being pooled. It has a SerializeField so that we can assign the object in the Inspector.
- Whenever we need more projectiles in the scene, the needProjectile bool variable can be tweaked to true.
- The projectile list will keep track of all the projectile objects in the scene.
2. in an Awake function, set the instance of the object pool. Awake is called when an instance of a script is being loaded.
3. In the Start function, we assign our projectiles to our list.
Note: To get a better view of how the projectile object is getting listed, I temporarily gave the list variable a SerializeField property so that you can view this in the Inspector. This step is not necessary, only for demonstration.
4. Create a method to get more projectiles into your scene.
- First, we check if there are any projectiles within the pool.
- If there are any, the for-loop will search for any inactive projectiles in the hierarchy and return those values.
- needProjectiles is our bool variable from earlier, this refers to when there are not enough projectiles in the scene and we need to get more.
- This happens in two situations: When the scene has just started and there are no projectiles, or when there are not enough inactive projectiles in the Hierarchy. Inactive projectiles are essentially our reserve to make the continuous attack, without anything in our reserve, we need to be able to produce more.
Note: For needProjectiles we don’t need to directly ask if it’s true or false because we already stated that this variable is true by default in its global declaration.
- If we need to get more projectiles, we instantiate a new pooled object(which is our Game Object variable)
- This new object is deactivated and added to our pool list.
- This method will return a null value when there is no need to add more projectiles.
That’s it for the Object Pool Script! Now all that’s left is making the Bullet Hell Attack script. Since that script will be quite complex and a little math-heavy, it will be covered in the next article!
This has been part of a series of Core Programming Challenges from GameDevHQ. In the next article, I will continue discussing the Boss Fight Code by going through the Bullet Hell Attack Script! The Final Script in this series of challenges!
Special thanks to Alexander Zotov for helping me figure out the kind of logic I should use for this type of script.