Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Refactoring Classes That Use Inspector Fields

Discussion in 'Scripting' started by Scalisco, Dec 31, 2021.

  1. Scalisco

    Scalisco

    Joined:
    Feb 2, 2014
    Posts:
    16
    Hi! One of my biggest wonders about Unity is how people refactor classes when they use the Inspector to set many variables.

    For example, say I have a MonoBehaviour that has ten serialized members. It's used on several game objects. Sometime later, I realize that I need only part of the behaviour for a new object. I want to split the behaviour into two to make more single-responsibility classes to use half of the behaviour on a new object. (Concrete example: the original was an enemy class, but now I'm making NPCs that need similar parts of enemies but not all of it like movement ai. Or if a scriptable object has several properties defining abilities, but now I realize that could be split into multiple SOs.)

    The issue is all of the original instances of the MonoBehaviour have properties edited in the Inspector. If I were to split it, all those values would be lost.

    What do people do to counter this? I think the advice on making fast iterations is not to overengineer early on and instead refactor only when you need to, but the Inspector in Unity makes it hard to refactor later.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
  3. Scalisco

    Scalisco

    Joined:
    Feb 2, 2014
    Posts:
    16
    I believe FormerlySerializedAs only helps with renaming serialized fields. I don't think it works if I want to move fields into a different class.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    You're right... but it is something.

    Fundamentally every inspector connection you make in a MonoBehaviour is this weird outside-the-compiler future thing to fail.

    The problem is, if one breaks in the future,

    a) you have no automated way of knowing
    b) it may be VERY hard to reason about what goes in there, especially if you named the fields poorly

    Personally I really try to limit how many connections I make, or have them try to locate reasonable fallbacks if I fail to set them. This isn't really the Unity Way (tm) where you have huge monstrosities of objects with 27 different dragged-in fields.

    One way to keep yourself sane is to a) name those fields very explicitly, and b) rename GameObjects in the scene to match the field name, to give your future self a helpful clue.

    Dunno if you know about partial classes, but they are an awesome midway step between having a giant class file after a furious day of fast iterations, and actually breaking it into separate classes.

    At least it keeps the editor file smaller. For instance, my SpaceFlight controller on Jetpack Kurt got so incredibly hairy that I didn't ever get around to tearing it apart, and since the game is long-ago-shipped and only gets minor updates, partial classes have done me quite well, each file containing related functionality in one spot, like a so:

    Screen Shot 2021-12-31 at 11.31.32 AM.png

    In fact, everything about the player lives in that SpaceFlightTest1 scene, which gets additively loaded with whatever content scene I want to play on. Works awesomely. The last two files appeared when I ported the game to Android TV, as they have special television-controller shims in there. That's all one giant MonoBehaviour called SpaceFlightTest1 and it only has a few public fields, everything else is lazily located via other resource locator scripts. Your ship doesn't appear until all is kosher and ready to go.

    Partial classes in Unity3D:

    https://forum.unity.com/threads/partial-class-and-unity.1114747/#post-7170964