Encapsulation and using [SerializeField]

Hey,

Most of the Unity code I’ve seen in scripts (MonoBehaviours) exposes public fields to be manipulated by the inspector.

This is nice as it allows quick iteration, changing values during gameplay, while on the other hand makes all of the behaviour’s internals visible to… well, all other classes, breaking proper encapsulation.

I was wondering what are the downsides of setting fields to be private, and marking them with the [SerializeField] attribute. Properties can then be setup to provide controlled access to these members:

public class MyBehaviour : MonoBehaviour
{
    [SerializeField]
    private int mySpeed;

    public int Speed
    { get { return mySpeed; } }
    { private set { mySpeed = value; } }
}

Aside from the slightly extra typing involved, why aren’t code examples showing this style of coding ?

I realize some code samples are aimed towards beginners, but I’ve never seen anyone mentioning this as a good practice in Unity.

Well. Unity is a bit weird when it comes to this. :slight_smile:

AFAIK, Unity serializes all public variables (which can be serialized). This data does add some extra overhead to the instantiated classes (i.e. objects), but normally it shouldn’t be a problem. Thus, [SerializeField] just gives you the opportunity to do the same for private variables.

This makes it difficult to have encapsulation done right, of course, but I guess the Unity team thinks that this is a OK trade-off for new users.

If you really-really need encapsulation, you could create editor-scripts which you attach to your game objects, which in turn communicates with your classes properly with properties.

Can you elaborate on that suggestion?
Also, are there any downsides to what i suggested (e.g: private fields marked with SerializeField, exposing public properties if needed).

The whole debate is around encapsulation, I ignore the extra serialization overhead as you mentioned for the sake of this argument.

If you ignore the serialization overhead, you can just set your variables to be private and include the [SerializeField] for them if you want to tweak them in-game.

If you want to extend the editor, look at the documentation: Unity - Manual: Extending the Editor with IMGUI

I think most Unity programmers are just lazy and leave everything public to expose it to the editor. I do find it a constant juggle of exposing fields just for debugging, but I can’t see any good reason why Unity scripts tend to ignore the principles of encapsulation. Lack of encapsulation has definitely created difficult to track bugs for me in Unity programming, so I think proper encapsulatiom is still important.

Chances are if I expose something to the inspector, I also want to be able to interact with that same property from code.

This isn’t the case always which is when I will start using hideininspector and searlizefield

It’s quite annoying when you need to change some values via script. Take the Unity 5 FirstPersonController. Please! I’d like to change things like ‘use head bob’ but it’s effectively hidden to code. I can sub-class it to gain access, but unless I do a lot of extra code (which I’m not even sure is possible in this case) to expose those variable, they become hidden in the Inspector again! Which I suppose would be fine if I didn’t want to leave the FirstPersonController code as-is (Unity may update it, I don’t want to re-code it).