As a programmer of sometimes complex systems, you may find that it is valuable to keep your code as simple as possible in order to reduce the potential for error or madness as a codebase grows. One of my favorite “comfort” mechanisms for maintaining clean and understandable code is encapsulation. In a nutshell, encapsulation attempts to reduce code complexity by keeping the majority of a class’s inner workings concealed from other classes. There are a number of reasons that this is quite effective:
- If you are debugging an error in a class, you will have the comfort and luxury of knowing that outside classes are not unintentionally affecting the class you are debugging. Let’s say you have a bug where a particular variable is sometimes giving the wrong value. In a badly encapsulated class, maybe that variable is public, so it is possible that any other class in your code base is changing that value. In a well encapsulated class, that variable is private, which means that the variables value is only being changed internally. The possible sources of error are greatly reduced.
- Similarly, exposing only needed functions to outside classes means that you stop other classes from changing the state of your class in unexpected ways.
- The fewer paths available to classes to communicate, the easier it will be to do refactoring in the future without having to make changes everywhere in the system.
- Only mark methods and variables as “public” if they ought to be visible for outside classes to access. If it is unclear whether a method needs to be public or private, make it private until a compelling reason appears for it to be public. It is easier to change from private to public than the other way around.
- Make the collection of functions and variables that you expose to the public (the “interface”) as coherent, easy to understand, and consistent as possible (relates to abstraction mainly).
- It is best to use accessor methods for variables as opposed to exposing the variables themselves publicly. If you want to change the type or behavior of a variable, this makes it much easier. Also, what if you want other behavior to occur every time you change a variables value? It isn’t possible unless you have accessors.
This post is mainly about that thirdbullet point. In Unity, the public and private keywords implicitly define whether a variable appears in the inspector or not, which at times, can go against the encapsulation goals of the class. For example, you may want to expose a variable so a designer can tweak the initial value, but that doesn’t necessarily mean you want other parts of the code to be able to mess with it! Luckily, there are some mechanisms built into Unity that allows you to have more control over this.
Using Private Variables in the Inspector
Generally, if you want to show a variable in the inspector, it’s as easy as this:
public float someValue = 10.0f;
You can easily expose the field for designers but maintain encapsulation with a minor change:
[SerializeField] private float someValue = 10.0f;
The “SerializeField” attribute will force Unity to serialize the private field and show it in the inspector. According to the Unity documentation, “you will almost never need this.” However, I think it can be extremely helpful to code your fields in this way when you are in a production environment with (potentially) many people working on the same code base. During development, it can be convenient to just access and change a public field to do what you want to do, but this can lead to hard-to-find bugs and tightly coupled code. If you are disciplined about your usage of public and private variables, it can simplify your job in the long run.
Removing Public Variables from the Inspector
On the flip side, you may have a public variable that you don’t want designers to see in the inspector. There is another easy solution using attributes:
[HideInInspector] public float someValue = 10.0f;
The variable will not appear in the inspector. Another way to achieve this (AND improve your encapsulation) is to use a C# property, which is also not serialized by Unity.