Objective: create a state machine for boss behavior, which is organized into classes.
Today we’ll start creating the behavior for the boss enemy of Galaxy Shooter. We want it to have the following set of attacks:
- Move while shooting multiple lasers, fanning out in different directions
- Stop and fire multiple beams at once, targeting the player
- Move while some lasers are shot straight ahead, and others track the player
- Fire missiles that seek the player, and must be destroyed by shooting them
We will use a finite state machine again. However, there’s a lot of complicated behaviors here, and most of them will require variables that have nothing to do with other states. It’s time we create a state machine that is organized a little bit better, by using nested classes. We can create classes inside of BossBehavior and use these smaller classes to keep track of the states of our finite state machine. We declare BossState as an abstract class inside of BossBehavior.
BossState will be inherited by every state used to define the boss’ behavior. Each one will have their own Act and Setup methods. Setup is called once whenever we switch to that state, while Act is called every frame when that state is active. Each state will also have their own class variables that they specifically require.
Note that we can declare each class as System.Serializable, so that they and all their serialized fields will show up in the inspector. They will even be automatically categorized into their various state classes to make it easy to find and assign the variables we are looking for.
Now we just create variables for every type of state that we want, and one variable that contains the current state that is active. Our behavior’s Act method will just call Act from the current state, and switching state will change the active state and ensure that it is set up properly.
Now we can get started creating the first few states. We want the boss to move onto the screen slowly and dramatically, so we create the MoveOnScreen state in order to place it in the right position just off screen, and then move it slowly on screen.
After fiddling with the speed and positions in the inspector for a bit, we end up with this.
Once it’s finished moving to the proper position, we switch to our first attack, the LaserFanAttack. The boss should then move slowly down the screen and periodically shoot volleys of lasers as it goes. We keep track of when to fire the next volley using the _nextVolleyTime variable. To make it more interesting, the boss will alternate the number of lasers it fires out, which will make it harder to figure out the pattern and dodge correctly.
The boss fires lasers out in a “fan” pattern, where each laser has the same angle spread between them. No matter how many lasers we ultimately decide on using, we can keep fire them in the correct direction by using this for loop. The first laser is fired at the top of the arc, and the last is fired at the bottom.
Now it’s really starting to feel like a boss! Next time we’ll add more kinds of attacks to keep the player on their toes when facing this deadly foe.