Upgrading Game Mechanics in Unity: Shield Durability and Dynamic Color Changes
Adding nuanced features to a game’s mechanics can improve the User’s experience. My challenge:
- Modify an game object’s behavior so that it could handle multiple collisions before deactivating.
- The game object also needed to give the User visual feedback about it’s state by changing its color.
To apply these features in Unity, the Player (Script) will need to track the number of collisions and update the Shield’s color as it takes damage.
Upgrading Attributes
The Player (Script) already contains a reference to the GameObject, _shield
, which will receive the upgrade to it’s game mechanics. One upgrade for this mechanic is for it to withstand three collisions.
Attributes and Statements of Shield Durability
A variable that will store the number of collisions can be defined at the top of the class as private int _shieldsRemaining;
.
The addition of the [SerializedField]
to the private variable, makes the integer value visible in the Inspector and on runtime will update to the number of collisions assigned to the variable, which will be 3.
Currently, the Damage()
method first checks to see if the Shield state is active (i.e., collected), then deactivates the _shield
behavior and visual representation based on one collision with Enemy or Enemy Lasers, and finally return
resets the Damage()
method. The Player returns to an unprotected state.
Using pseudocode comments, think through the logic of the new behavior. Add pseudocode comments back into the existing block of code to clarify the existing sequence and add new attributes into the behavior.
When the _shield
is activated is must allow three collisions. The ShieldActive()
method activates Shield behavior and Shield sprite when the Shield Power Up is collected. Within the context of this method, a local variable can be added and set to the number of collisions stored in _shieldsRemaining
.
Now that the number of collisions allowed is assigned in the ShieldActive()
method, where will the deduction of collisions take place? The same place that subtracts _lives
, which is the Damage()
method.
When the Damage()
method is called by the Enemy that collides with the Player, if
the Shield is active, one collision will need to be subtracted from the integer stored in _shieldsRemaining
. if
the _shieldsRemaining
is less than or equal to 0
, then Shield behavior should be deactivated and it’s sprite should also be deactivated.
Developing Shield Durability Pseudocode
- To develop the pseudocode, (1) the private integer defining the number of
_shieldsRemaining
, can be set to 3 as a local variable within theShieldActive()
method. NOTE: This value can be changed in the Inspector of the Player (Script) in the Unity editor later.
Now that the value has been set to the number of collisions permitted when ShieldActive()
is active, developing the logic of “losing” a layer of _shield
for each collision can be developed. The concept of “losing” implies a statement using subtraction within the Damage()
method.
- After the
Damage()
method checks to see if the Shield Power Up has been collected, the variable which contains the assigned number collisions,_shieldsRemaining
, should subtract collisions in increments of 1 each time damage occurs using the--
operator. - A second check will be used to check how many collisions have occurred and
if
the value stored in_shieldsRemaining
is less than or equal to0
. If the number of_shieldsRemaining
is0
, then the boolean value_isShieldActive
and the_shield.SetActive
will be deactivated using the keywordfalse
.
Once again the Player will be vulnerable to losing lives and the visual representation of the shield will disappear.
Test the Feature
- Go back into the Unity editor. Press play. Collect the Shield power up and deliberately collide with Enemy or Enemies Lasers and watch the durability of the shield take 3 collisions before resetting to a Players unprotected state.
Visual Feedback of Shield Durability
In addition to the behavior of Shield durability, some visual indication helps Players understand the gameplay circumstances and the state of the game mechanic, i.e., durability to the shield.
The SpriteRenderer component attached to the Player (Script) holds the Shield sprite, i.e., visual representation, in the slot labeled Sprite. It also contains the Color, i.e., property of visual representation.
To give the User visual feedback of the Player’s state, the _shield can change color, but how to access the Color property of the SpriteRenderer component?
To understand this process and many others, research is a necessity. Google Search “change SpriteRenderer color Unity”. Google Search results return Unity Scripting API: SpriteRenderer.color.
SpriteRenderer.color in Unity documentation is described as “rendering the color for the Sprite graphic.” To find out more, search for the most relevant keyword within the SpriteRenderer.color documentation. Left-click on the word Color.
According to Unity documentation on the Color , “each color component is a floating point value with a range from 0 to 1.”
Scrolling down, more detailed information about the Constructor, Color is described as “Constructs a new Color…”
For more on a basic understanding of Constructors, watch this tutorial from GamedevHQ.
The Color Constructor has 4 parameters that set the color’s value.
Within the Unity documentation of the Color Constructor, the Description states that the constructor is used to “construct a new Color”. In the script example, the GameObject Color is a variable named “newColor” then it is set using the keyword new and then the Color()
constructor followed by the float RGBA values.
Back in the Player (Script), developing the logic for the change in color of the _shield
will be a part of the Damage()
method and the ShieldsActive()
method. Why? The _shield
SpriteRenderer’s color property must be accessed when the Player collects the Shield Power Up.
Once the color constructor is accessed and assigned to a color, the change in color must coincide with the collisions. Each time a collision occurs, an integer of 1 is being subtracted from _shieldsRemaining
.
Currently the logic is: turn off _shield
if
less than or equal to 0
or return to top of the method. Before returning to the top of the method what else
does the method need to do? // change _shield color based on _shieldsRemaining
then // get the color of the _shield sprite and set it to a new Color.
In the Player (Script), there is already an existing reference to the GameObject _shield
. To access the GameObjects SpriteRenderer component and it’s color property from within the ShieldActive()
method, the variable referring to the GameObject begins the statement, followed by GetComponent<>()
method and it’s property .color
.
_shield.GetComponent<SpriteRenderer>().color
For the _shield
sprite to be seen in it’s original color, the color property of the SpriteRenderer component must be set to white
using the Color
Constructor.
Once the color property of the SpriteRenderer is accessed and set, it can be changed and that change will occur in the Damage()
method.
Calculating Smooth Changes in the State of the Variable
The change of color needs to be smooth so it must be divided into equal parts. 3 collisions equals three parts. The total number of collisions (3f
) can be divided by the number of collisions remaining (_shieldsRemaining
). The resulting decimal value will be stored in a new variable identifying the color value.
To change the RGBA floating values, the decimal value or the variable representing a decimal value must be set in the parameter of the Color constructor. As stated in the documentation, 1f
is the maximum value of the color. After the first collision, there will only be 2 _shieldsRemaining
. 2f / 3f = a color value of 0.67f. After the second collision, there will be only 1 _shieldsRemaining
. 1f / 3f = a color value of 0.33f. One more collision will result in 0 resulting in the color value being set to 0, which is no color and at that point the Shield will be deactivated/set to false
.
To store the remainders of division as floating values, a variable is created that identifies exactly what it represents, colorValue
. In the Damage()
method, the variable float colorValue
will be assigned to the equation _shieldsRemaining / 3f;
that divides the color value into 3 equal parts.
GetComponent’s color property & Construct the New colorValue
Next, the _shield.GetComponent<SpriteRenderer>().color
will need accessed again to set a new
color using the Color
constructor and apply the floating point value stored in the colorValue
variable.
The decrease in color will coincide with the decrease in floating values. While the decrease in value could be applied to all color properties, here they will only be applied to Green and Blue. Red will remain at full strength (1f
)because the color red is associated with damage.
- Set the new
Color()
the RGBA parameters will be(1f, colorValue, colorValue, 1f)
.
Test the Feature
Save the Script. Return to the Unity editor. Run the game. Collect the Shield Power Up and watch the Shield sprite provide the visual feedback after each collision.
Mission Accomplished
These upgrades to the Game Object, Shield Power Up, improves User experience during gameplay through visual feedback and more dynamic game mechanics. As I continue exploring creative possibilities and experimenting with techniques to further refine my game development skills, join me, please follow/subscribe or clap and comment.