Upgrading Game Mechanics in Unity: Shield Durability and Dynamic Color Changes

Brian David
8 min readAug 24, 2024

--

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.

Shield Upgrade — created in collaboration with DALL.E3

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;.

private integer

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.

private int _shieldsRemaining visible in Inspector

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.

logic for the activation of shield behavior in pseudo code

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.

logic of shield behavior in pseudo code

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 the ShieldActive() method. NOTE: This value can be changed in the Inspector of the Player (Script) in the Unity editor later.
setting the number of collisions available within the local variable

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 to 0. If the number of _shieldsRemaining is 0 , then the boolean value _isShieldActive and the _shield.SetActive will be deactivated using the keyword false.

Once again the Player will be vulnerable to losing lives and the visual representation of the shield will disappear.

subtraction the number of collisions allowed then deactivate shield when less than or equal to 0

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.
3 consecutive collisions with Shield Active
collection of power up activates 3 shields

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.

examining the GameObject Shield’s SpriteRenderer Color property

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.

Understanding Constructors

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.

else statement with pseudocode logic to change color and set 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.

Setting the Sprite’s color to white

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.

dividing the color property into equal parts and storing it in a variable

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.

_shield collides with Enemy, color intensity fades

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.

--

--

Brian David

an exploration of creativity and software development