- Home /
Using [SerializeField] vs public
Hi Unity community.
I just have a quick question regarding the use of [SerializeField]. I have been using this a lot on private variables (c#), but have noticed a lot of other people seem to just make all their fields public when they want the inspector to display them.
I would have thought this was less than ideal practice, since often you're exposing something only so you can edit it in the editor, not so that any other object could technically alter its state.
Even the Unity manual suggests "you will almost never need this".
So am I missing something here - is there some other reason to make all your properties public when they ordinarily wouldn't be? Is there a reason that [SerlializeField] isn't considered the norm for exposing fields in the editor?
Thanks for your time.
Answer by Jamora · Oct 06, 2013 at 12:56 PM
There is no other reason to make your variables public than to make them visible in the inspector (aside from making them serializable... but SerializeField does that).
I suppose the reason [SerializeField] isn't the norm in exposing variables is because Unity doesn't want to be only a tool for programmers so people who don't know programming (artists or modellers etc.) could make their own games.
I personally think it's lazy of Unity to not have made a property drawer for public properties. (Ironic, isn't it?)
Thank Jamora, I think this mostly answers my question, I just don't personally like using public fields out of convenience in the inspector, as it seems very non OOP regarding encapsulation.
Also, cheers re the link to drawers, never had stumbled across these - seems like a great middle ground between custom editor classes for small $$anonymous$$ms which don't need super pretty front end inspector panels
Note that if you just want to "see" a field (not edit it in inspector) it's much more practical to use the debug inspector than to make them public.
@Jamora So how do you reference an object if the field is just private?
Should I use the GameObject.Find or varName = GetComponent()?
With the GetComponent methods I'm ok since you can access to the other components in the same GameObject, but what about GameObject.Find?
As far as I know these are expensive.
Had to split the post ^^.
There are several "things" you can do to a variable declaration that changes one or multiple of the three mentioned things:
/*
| available from other classes | serialized | visible |
------------------------------------------------------------------------------
[HideInInspector] | - | - | No |
------------------------------------------------------------------------------
[NonSerialized] | - | No | No |
------------------------------------------------------------------------------
[SerializeField] | - | Yes | Yes |
------------------------------------------------------------------------------
public modifier | Yes | Yes | Yes |
------------------------------------------------------------------------------
private,protected | No | No | No |
internal modifier | | | |
------------------------------------------------------------------------------
*/
I ordered the first column by precedence. So if multiple apply to the same variable, the top most overwrites lower things.
Of course there are a few combinations that doesn't make any sense or are mutual exclusive. Like for example:
public / private / protected / internal are mutual exclusive
private + HideInInspector --> does not change anything
public + SerializeField --> does not change anything
NonSerialized + SerializeField --> NonSerialized do$$anonymous$$ates, SerializeField has no effect
Note: Things can only be visible in the inspector if they are serialized. If something is not serialized it will never show up in the inspector.
Though there is one special combination that involves 3 of the above that does actually make sense:
private + SerializeField + HideInInspector
This will make the variable encapsulated in the OOP sense. It also prevents the user from seeing / modifying the value in the inspector but the value is still serialized in the editor. However it can only be modified through methods / properties of that class.
You should break this comment into it's own answer to this question. It's more accurate and informative than the accepted answer.
I truly do not understand why they would when basing this in c# not adhere to well established c# coding conversions. People program$$anonymous$$g outside of games will no doubt be annoyed and frustrated but those trying to take their skills elsewhere will likewise find it difficult. Why not just $$anonymous$$ch things properly from the get-go?
I'm not sure what you mean. First of all Unity is not "based" on C# or .NET / mono but is written in C++. $$anonymous$$ono and C# are just used as managed scripting environment. So certain engine mechanics are based on C++ and have to adapted in order to be used from the scripting environment. That includes the ability to "destroy" objects which doesn't exist in the managed world.
$$anonymous$$ost other rather unusual practises are mainly used for performance. Unity's object system is component based. That means it encourages flat class hierarchies. Unity also doesn't use the normal virtual / override mechanics mainly for performance benefits. The kind of C# that is used is just plain C#. It can even be compiled by any other C# compiler (as long as the C# version isn't too high).
What exactly do you see in Unity that does not "adhere to well established c# coding conversions"? Again, the serialization system in Unity is C++ based, not .NET / mono. The system need to serialize things which are not based in the .NET / mono world.
Answer by Bunny83 · Nov 27, 2016 at 03:55 PM
Jamora's answer might be a bit misleading. What he wanted to say is that the only thing that the SerializeField attribute and the "public" access modifier have in common is that they will make a variable "visible in the inspector" and serialized.
There are different things you have to decide which have almost nothing to do with each other in the first place:
Should this variable be serialized?
Should a serialized variable be editable in the inspector?
Should other classes be able to access this variable from outside
The first question is only about if the value of the variable should be serialized or not. The second question belongs to the last last one. A value should only be visible in the inspector when the user should be able to set a value in the inspector. The last question is a pure OOP question. You might want to read up on Encapsulation.
There are several "things" you can do to a variable declaration that changes one or multiple of the three mentioned things:
/*
| available from other classes | serialized | visible |
------------------------------------------------------------------------------
[HideInInspector] | - | - | No |
------------------------------------------------------------------------------
[NonSerialized] | - | No | No |
------------------------------------------------------------------------------
[SerializeField] | - | Yes | Yes |
------------------------------------------------------------------------------
public modifier | Yes | Yes | Yes |
------------------------------------------------------------------------------
private,protected | No | No | No |
internal modifier | | | |
------------------------------------------------------------------------------
*/
I ordered the first column by precedence. So if multiple apply to the same variable, the top most overwrites lower things.
Of course there are a few combinations that doesn't make any sense or are mutual exclusive. Like for example:
public / private / protected / internal are mutual exclusive
private + HideInInspector --> does not change anything
public + SerializeField --> does not change anything
NonSerialized + SerializeField --> NonSerialized dominates, SerializeField has no effect
Note: Things can only be visible in the inspector if they are serialized. If something is not serialized it will never show up in the inspector.
Though there is one special combination that involves 3 of the above that does actually make sense:
private + SerializeField + HideInInspector
This will make the variable encapsulated in the OOP sense. It also prevents the user from seeing / modifying the value in the inspector but the value is still serialized in the editor. However it can only be modified through methods / properties of that class.
Thanks for mentioning this combo: "private + SerializeField + HideInInspector". I never thought about it.
A minor mistake in your table : internal allows access from other classes (of same assembly).