2D Mobile Game: Enemy Class Shared Behavior
In this article, we exam the shared behaviors of the enemies and see what can be added to the Enemy Class to optimize our code.
Looking at our two current enemy scripts, we are looking for shared behaviors and properties. At first glance, the variables in each individual script are the same — an Animator & Sprite Renderer.
This is a great place to start, but before adding these variable to our Enemy Class we want to take a closer look at how these variables are being used to see if there is any commonality.
We have shared properties between the two enemies, but lets go through each script and look at any common methods to see if those properties being utilized in the same way.
Both Enemy scripts use an On Start to initialize those shared variables and they are caching those same components (Animator & SpriteRenderer) in the same way; The components are both in the child. Also, the targetID is being initialized inn the same way. This On Start can be moved from the individual scripts to the Enemy Class script.
Between both scripts, an Update is used and in both Updates the same logic is being used where the Animator is being checked to see if the Idle animation is being played and if it is not the Movement method is called. I already peeked ahead at the Movement method and the logic is the same between both, meaning this Update can be moved to the Enemy Class script.
The Movement method is also similar, where the waypoint is checked to determined if the sprite needs to be flipped, the position of the enemy is checked to see if it is the same as the target waypoint and if it is, we cycle to the next waypoint and trigger the Idle animation, and lastly we have the enemy moving towards the target waypoint. This method can be moved to the Enemy Class script.
Revising Enemy Class Script
We identified the shared properties and behaviors of our individual enemy scripts and now lets merge those commonalities into the Enemy Class script.
We create the Animator & SpriteRenderer variables and make them protected to ensure they are private and can be accessed only by inherited classes. Next, we are going to create an Initialization method (Init). This is where we are grabbing the Animator & Sprite Renderer and assigning to our variable. We also, set the Target ID for the waypoints. Lastly, we use an On Start and call this Init method, so these variables are initialized for all the Enemy Class scripts that will use them. It is important to note, the Init method is virtual, meaning it can be override if an individual enemy script needs something different than the parent class.
A public virtual Update is added that will check for the Idle animation through the new protected parent class anim (Animator) and call the Movement method. This Movement method is another public virtual method and we continue to swap put the out individual script variables for the new protected parent class versions.
Enemy Inheritance Scripts
We have moved all of the common properties and shared behaviors to the parent class script, so we can go back into those inherited scripts and remove the code that we refactored back in the parent class script.
Since these behaviors are passed from the Enemy Class script to the individual scripts of Spider and Moss Giant they are performing the same as they were before, but now we can easily setup 50 enemies with the same behavior without rewrite the same code over and over again.
The last thing we will do is in the individual enemy scripts we will override the Init method of the parent class but still call the Init from the parent class (base).
This will allow use to initialize unique properties of those different enemies along with still being able to use those common properties from the parent class.