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