Search Unity

Encapsulation and using [SerializeField]

Discussion in 'Scripting' started by liortal, Dec 21, 2014.

  1. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    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:

    Code (CSharp):
    1. public class MyBehaviour : MonoBehaviour
    2. {
    3.     [SerializeField]
    4.     private int mySpeed;
    5.  
    6.     public int Speed
    7.     { get { return mySpeed; } }
    8.     { private set { mySpeed = value; } }
    9. }
    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.
     
    Last edited: Dec 21, 2014
  2. toreau

    toreau

    Joined:
    Feb 8, 2014
    Posts:
    204
    Well. Unity is a bit weird when it comes to this. :)

    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.
     
  3. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    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.
     
  4. toreau

    toreau

    Joined:
    Feb 8, 2014
    Posts:
    204
    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: http://docs.unity3d.com/Manual/ExtendingTheEditor.html
     
  5. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    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.
     
  6. cmcpasserby

    cmcpasserby

    Joined:
    Jul 18, 2014
    Posts:
    315
    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
     
  7. SpiralConDave

    SpiralConDave

    Joined:
    Dec 29, 2014
    Posts:
    37
    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).