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.

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.

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?)