A Lofty Introduction

Grasped in my hand is an idea for a blog post, in the other a freshly brewed coffee. Sunrise is still a few hours off and the morning air is cold, still and peaceful. I sit down with my idea and try to parse it out into an elegant and concise work of literary mastery. But just as the sun comes marching defiantly through the window, I find not one word is written. Instead I have no less than a dozen web-pages open and a page of notes illegible to even myself.  This seems to be how the writing process goes. Each week finding myself down an endless rabbit hole that I never knew existed.  

This posting was initially a simple idea, intended for the very beginners of unity; what are access modifiers and which one to use and when.

Now I find myself with pages of notes on how Unity complies code, the process of converting the managed C# code into the native C++ and how reflection is done with the Mono virtual machine. Needless to say, I'm beyond confused and still in need of a blog posting. Which is my long-winded way of  explaining to you the reader, we will be discussing something very simple, but underneath are very complex ideas. These ideas I hope to understand and explain in the not too distant future.

 

What are Access Modifiers?

Access modifiers define the scope of the variable or method that you are declaring. The three modifiers that you will regularly use in your games are; Public, Private and Protected. For the sake of brevity (perhaps too late for that?) I will ignore the Internal modifier as there is seldom a need for it when developing small games in Unity.

 

 

Lets Start With Public

 

It might not be a surprise to learn that a Public variable or method is one that can be accessed by other classes in your game. Your intention when declaring something to be public is that it will be needed beyond the specific class you are coding. Take the example given below of a player health class. Naturally you need a script to keep track of your player's health, but on its own, is not particularly useful. Various other game elements will need to both read and modify the player's health at different times. For instance the UI will need to read the health in order to display it. Meanwhile an enemy needs a way to reduce the health, just as a health pack needs to increase the health.

With all the time in the universe I couldn't possibly exhaust all of the ways you may want to access variables from another script. But suffice it to say that the public access modifier is how you do it. 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerHealth : MonoBehaviour
{
    public float maxHealth;
    public float currentHealth;

    /// 
    /// This method will reduce the player's health by specified amount. 
    /// 
    ///
    public void DamagePlayer(float damage)
    {
        currentHealth -= damage;
    }

    /// 
    /// This method will inccrease the player's health by the specified amount up to max.
    /// 
    ///
    public void HealPlayer(float health)
    {
        currentHealth = Mathf.Clamp(currentHealth + health, 0f, maxHealth);
    }   

  

Keep it Private

But what if the script is self-contained and has no need to be accessed outside of itself? This is where the private modifier comes in. Using the keyword private limits the scope of the method or variable to within the class it is defined. Now I can hear you asking; But why would I bother to do that? Where is the harm in just making everything public? The truth is, if you are solo developer, making a small indie game; odds are good that won't run into any problems. Your game will compile and run just fine.

But by doing so you put your game at risk of failing in the future. You will struggle to update or understand your scripts long after the initial purposes of your code has faded from your memory. C# is a Object-Orientated Language, in which the primary objective is to create scalable code that requires little explanation to implement. By making everything public you muddle the purpose of your scripts and make them susceptible to been later misused. As a rule of thumb, keep everything private until needed otherwise.

Now on to an example! Below is an example of a simple player controller that moves the player each frame by a force. In order for this script to work efficiently a reference to the Rigidbody component is necessary (as opposed to using get component each frame). However, there is no need for any other class to access this particular reference to the Rigidbody. If a reference to the Rigidbody is needed in another class, it is more efficient and cleaner for that class to reference it directly. Thus the Rigidbody in this example should be kept private.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MovePlayer : MonoBehaviour
{
    [SerializeField]
    private float force; //vale of force to move player
    private Rigidbody playerRB; //rididbody attached to player


    // Start is called before the first frame update
    void Start()
    {
        playerRB = GetComponent();
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        playerRB.AddForce(transform.forward * force);
    }
}

 

Despite been specified as private. The value of force can be altered in the inspector thanks to the SerializeField tag.

In this example I also decided to keep the value of force private. But this may lead you to a dilemma that results from not been able to see private variables in the Unity inspector.

Naturally you need to specific a value for the force, but you have no intuitive way of knowing exactly what that value might be.  I'm certainly not suggesting that you should hard-code it and change it within in the script after every test. Instead what we can take advantage of is the [SerializeField] tag. This will keep the field private but make it visible in the Unity inspector for tweaking during playmode. 

 

  

Don’t Worry I’m Protected 

Inheritance is a completely underutilised by new developers, especially those without a background in programming. This was certainty true of me, MonoBehaviour was all I ever needed and all I ever wanted, so I thought anyway. I will expand on the idea of inheritance in a future blog, for now it will suffice to say that when working with inheritance; protected variables are vital to you. 

Below is an example of an enemy class.  It has variables for speed and damage that are in this example defined in the start method. But in this example which is common in many games, there are different types of enemies. Each enemy might exhibit slightly different behaviour but still have the same type of variables.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour
{   
    protected float speed;
    protected float damage;

    private void Start()
    {
        speed = 10f;
        damage = 20f;
    }
}

//Inherit values from enemy. 
public class Zombie : Enemy
{
    private void Update()
    {
        transform.Translate(transform.forward * speed);    
    }

    private void OnCollisionEnter(Collision collision)
    {
        speed *= 2f;
        if (collision.collider.CompareTag("Player"))
        {
            collision.collider.GetComponent().DamagePlayer(damage);
        }
    }
}

 

In this example the protected floats of the Enemy are been inherited and thus accessible by the Zombie class. Because the protected fields act essentially as public fields in the zombie class, they can be used such as in a collision event (notice we are using the public damage player method from before).

This is just a rudimentary example of how protected fields can be used and as discussed with the private modifier the goal is to future proof your code limiting the way it can be implemented beyond the initial intention.