If I have an object in a script and I want other scripts to access it, I always wonder what is the best way to do it :
Public :
My favorite, but also disliked by most programmers. I can give a value directly in the editor and when the game load it should be faster then doing a getcomponent on start/awake (form what I have read). I also can access it just by typing the name. The issue most people have with public variable is that anyone can modify it without validation. it,s bad practice.
Public property :
With this, you don’t have the issue of lack of validation. In your get/set of property, you can add code to validate your data. Sadly, it won’t shup up in the editor, and you will have to getcomponent on start.
I know everyone will tell me to no use Public variable. But then should I initiate every property on the awake/start component of my object? Won’t it be a bit slower then public variable?
Also is there another way to add a variable that can be used by another script and still show up in the editor?
P.S : If anything I say in my post is wrong, feel free to correct it.
There’s a reason that public variables and public properties both exist in the C# language, and that is because sometimes you want one, and sometimes you want the other. If you have any sort of validation or reaction to a change of a variable, it should be a property. If you find yourself checking a variable in Update and then doing something if it changed, it should probably be a property. If neither outside scripts nor the inspector need write access to a particular thing, consider making it a property.
And is it a non-issue that I can’t assign my property in the editor and have to do it via getcomponent?
As I have a script manager that manage other scripts, and he need to be linked to every other script so I use public variable and set to value in the Editor.
There are ways to make it possible to assign properties from the editor. Either you create a custom editor from scratch or you use an existing asset to mostly automate the process. The Vexe Framework can handle properties and it’s open source.
You can also consider you can create public variables of the script itself. So a gameManager that has
public PlayerScript player; Could have a player gameobject that has the script dragged and dropped in there, thus removing the need to use getComponent and you could then just access your properties through that.
If it’s a Public GameObject player and you dragged and dropped, you’d still have to create a reference to the script using getComponent.
Custom Editors are pretty amazing. You can make it access whatever you want, property (get/set) or the backer field (bypass). They have a bit of a learning curve and serialization caveats and maintenance to consider.
You could just expose the backer field as public if you really wanted to get it in the inspector. As long as you assume you’re always going to communicate with it through the property at runtime…
I wish there was a [SerializeAutomaticProperty] that would do the same as serialize field, but without me having to manually write out the private backing fields.
That’s what you are doing anyway. The auto properties just hide it within syntactic sugar.
There really is no explicit need to use properties. A field works fine. If you need validation, you can always change it later.
This is best practice. For clarity, let’s go over a bunch of them:
[SerialiseField] - Used whenever a variable needs to be exposed to the inspector.
public - Used whenever another script needs to access a variable.
Auto properties - Used whenever you need different access modifies on the set or get properties.
Explicit properties - Used whenever you need to get clever. For example data validation, triggering on change events, complex setting or getting behaviour.
Method - Used whenever there are additional side effects above and beyond setting and getting a variable.
And there are a couple of bad practices you should stomp out mercilessly:
Using a public variable just to expose it to the inspector.
Using auto properties on everything, regardless of need.
Changing a field to a property is a breaking change. For example a field is a variable and can be passed by reference (ref or out keyword), while a property is a pair of accessors and cannot be passed by reference, thus changing a field that is passed by ref or out into a property will cause you code to break. So while you can change it later it might force some refactoring while changing a property to a field (or adding a backing field) will never be a breaking change.