Search code examples
c#performanceunity-game-enginereadability

Best way to notify game objects of change? (Unity Script Organization / Delegation)


Currently I have a game with two modes, a build mode and a play mode.

Objects act differently in build mode than in play mode.

What is the easiest way to handle these objects? Should I use a Toggle? How is my current set up on performance, and code readability considering what I have in OnUpdate?

Here is an example of what I have that checks if the GameController I made is in build mode or Play mode. It also gets when these modes start, and runs the functions once by manipulating bools. I am looking for answers that can help me make better decisions when optimizing my game, code readability and just overall format of my code. I know there must be an easier way, either with listeners or events / triggers.

There can be about a hundred of these items in the game at one time, so I want to make sure I'm not going to ruin the game with too many Update calls. Right now, performance doesn't really run down while I have a lot of these items, but that's no reason to not optimize my game.

   public class GameItem: MonoBehaviour 
{
    //....

         private void Update()
        {
         CheckMode();
        }
    
        // Checks Current Mode, And If StartingMode
        private void CheckMode()
        {
            // check to see if starting build mode, 
            if (!gameController.inPlayMode) 
            { 
               if (!startingBuildMode) 
              { 
                WhenStartingBuildMode(); 
                startingPlayMode = false; 
                startingBuildMode = true; 
               } 
        WhileInBuildMode();
        return; 
      }
    
            // check to see if starting play mode, 
            if (!startingPlayMode) 
           { 
             startingPlayMode = true;
             WhenStartingPlayMode(); 
             startingBuildMode = false; 
           }
    
    
            // what to do while in play mode
            WhileInPlayMode();
    
    
        }
    }

Solution

  • This would represent the pattern I use (with a bonus feature of being able to toggle modes in editor, not sure if you need it)

    public class GameItem: MonoBehaviour 
    {
         [SerializeField] //see it in edior
         private bool _isBuildMode;
         public bool isBuildMode
               { get { return _isBuildMode;}
                 set {
                     // if you want to make sure code only runs when value changes:
                     //   if (_isBuildMode==value)   return;
                      _isBuildMode=value; 
                      // do stuff related to mode change, like
                       if (isBuildMode) WhenStartingPlayMode(); 
                     }
               }
          void OnValidate()
          {
           if (Application.isPlaying) isBuildMode=isInBuildMode; // enable editor change
          }
         private void Update()
           {
            if (isBuildMode)
           {
              WhileInBuildMode();
           }
           else 
           {
              WhileInPlayMode();
            }
         }
       }
    

    If you want to place the boolean mechanism in the gameController you might want to consider doing something like

          public System.Action<bool> OnModeChanged;
          private bool _isBuildMode;
          public bool isBuildMode
               { get { return _isBuildMode;}
                 set {
                      _isBuildMode=value; 
                      if (OnModeChanged!=null) OnModeChanged(value); 
    
                     }
               }
    

    You can then subscribe in your sub components

    void Start()
    {
      var gameController=GetComponentInParent<GameController>();
      if (gameController!=null) gameController.OnModeChanged+=(x)=>
        {
          isBuildMode=x;
        };
    }