So, you start up your brand new copy of Unity, and start tapping away, and MAGIC! Public variables show up in the editor.
Fast forward a few months, or even years, and you’re probably still using public variables everywhere, or at least to get them to show up in the inspector.
Now, you may be wondering why this is a bad idea; Unity is being magical after all, filling in your variables for you!
Now think about this: something, somewhere in your code starts changing your variable at runtime, and you have no idea where. Do you go through the entire codebase, searching for it? Use your code editor to find all references of it being used, and hope to get lucky?
Or this: you’re changing a variable, but no matter what you set it to, it’s always doing the same thing. *facepalm* It was a public variable, and unity was setting it for you.
Securing your code from silliness like that is actually fairly easy, and definitely something I would recommend for anyone who has outgrown being a Unity beginner.
First off, make all of your variables private. All of them. Even that one, yes.
This stops other code from being able to manipulate the variables (without resorting to dynamically setting them, but that’s another story entirely). Now, your variables don’t show up in the inspector! Well let’s fix that:
//C# [SerializeField] private Transform myTransform;
//UnityScript @SerializeField private var myTransform : Transform;
Yay! They’re back!
And now you can immediately see which variables should be shown in the inspector and which shouldn’t without having to think twice. You could even put the attribute on the same line as the private variable to make it doubly obvious.
Anyway, other code can’t access the variables now, so let’s get on with the real meat of this post: Properties and/or methods
Methods are the old-school way of giving access to data in a controlled way – you can make a function to set the variable, and a function to get the variable. The benefits of using this over public variables are numerous – you can specify different levels of access for getting and setting (e.g. public get, private set), the ability to add more code into the get/set (e.g. Debug.Log(“Variable accessed!”); to figure out where the code is being got and set from), and many other reasons.
A quick example (For brevity, C# only):
[SerializeField] private Transform myTransform; protected void SetTransform(Transform newTransform) { Debug.Log("Setting myTransform to " + newTransform.name); myTransform = newTransform; } public Transform GetTransform() { Debug.Log("myTransform accessed!"); return myTransform; }
It’s a little bit more code than a single public variable, but much less prone to random bugs, and much easier to debug and add functionality to.
Now, Properties!
Properties have been in .NET since the very beginning, and they’re a pleasure to use. They give you all the benefits of methods, while seemingly acting like variables. Unity makes great use of them, nearly all of Unity’s “variables” are actually properties.
They work in both C# and UnityScript, though much more easily in C#. Here’s an example of declaring one in both languages:
[SerializeField] private Transform myTransform; public Transform MyTransform { get { Debug.Log("Accessing myTransform"); return myTransform; } protected set { Debug.Log("Setting myTransform to " + value.name); myTransform = value; } } public int Test { get; set; }
class MyClass { @SerializeField private var myTransform : Transform; public function get MyTransform() : Transform { Debug.Log("Accessing myTransform"); return myTransform; } protected function set MyTransform(value : Transform) { Debug.Log("Setting myTransform to " + value.name); myTransform = value; } }
Now, you may be wondering why I declared a class explicitly in my UnityScript snippet, and rightly so; You cannot (As of writing this post) use properties in UnityScript with implicitly created classes (i.e. script files without an explicit class definition).
Onto the syntax. The C# one is probably new if you’ve never seen a property before. You declare what looks like a variable, then add in a block after, with get and/or set accessors. The accessors contain the code to get or set the value however you like, and have an implicit variable called value for the set accessor to let you assign to your internal variable. I also added in a second property called Test, which uses the C# 3.0 auto-implemented (or automatic) property syntax. This let’s you quickly make properties which completely hide the backing field (the variable it assigns to), stopping you from doing anything silly with the variable itself, and making code shorter.
For UnityScript, the syntax looks familiar up until the get and set keywords. These tell the compiler to use the functions as accessors to a property.
To use them, in both languages, you simply treat them like they were variables:
MyTransform = transform; //set var theTransform = MyTransform; //get
For C#, using properties is a no-brainer. They’re generally the standard for giving access to your variables, and fairly easy to implement. For UnityScript, less easy to implement, the implicit class issue being the main reason to think about using methods instead.
So, in conclusion – public variables bad, public methods and properties good.
Pingback: Make it Serializable! Pt 2 « Quick Fingers
I was just browsing here and there and got to read this post. I must say that my luck is favoring me today otherwise getting such an excellent post to read was never achievable for me, at least. Really appreciate your content.
It’s really a nice and helpful piece of information. I’m glad that you shared this helpful info with us. Please keep us informed like this. Thanks for sharing.
mike_mac, nice blog, keep it up!
Cheers
Alex