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. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

State Machine OnEnter technique

Discussion in 'Scripting' started by Zebbi, Apr 3, 2021.

  1. Zebbi

    Zebbi

    Joined:
    Jan 17, 2017
    Posts:
    521
    I've been working on my own switch case state machine, but I needed an OnEnter type of trigger that happens once if the state is entered:

    So, I'm using a top-level state for Alive/Dead:
    Code (CSharp):
    1.     public enum MonsterExist {
    2.         Alive,
    3.         Dead,
    4.     }
    5.    
    6.     public MonsterExist monsterexist;
    This runs my second-level logic:
    Code (CSharp):
    1.     void MonsterExistLoop()
    2.     {
    3.         switch (monsterexist)
    4.         {
    5.         case MonsterExist.Alive:
    6.             MonsterStateLoop();
    7.             break;
    8.         case MonsterExist.Dead:
    9.        
    10.             break;
    11.         }
    12.     }
    And the second-level machine for all of the actual logic:
    Code (CSharp):
    1.     public enum MonsterState {
    2.         Asleep,
    3.         Chase,
    4.         ChangeDir,
    5.     }
    6.    
    7.     public MonsterState monsterstate;
    Code (CSharp):
    1.     void Update()
    2.     {
    3.         MonsterExistLoop();
    4.     }
    Then, I have a second enum and bool that I use to keep track of the state before it changes:
    Code (CSharp):
    1.     public MonsterState monsterstateOld;
    Code (CSharp):
    1.     bool monsterstateOnce()
    2.     {
    3.         if (monsterstateOld != monsterstate)
    4.         {
    5.             monsterstateOld = monsterstate;
    6.             return (true);
    7.         }
    8.         else return (false);
    9.     }
    Here's the second-level mail state loop, you can see during the Chase state:
    Code (CSharp):
    1.             if (monsterstateOnce())
    2.             {
    3.                 Debug.Log("once on enter");
    4.             }
    We enter the state and it checks if the bool is true, which it is because we have just changed to this state, then the bool sets itself as false:

    Code (CSharp):
    1.     void MonsterStateLoop()
    2.     {
    3.         switch (monsterstate)
    4.         {
    5.         case MonsterState.Asleep:
    6.             // asleep code
    7.             break;
    8.         case MonsterState.Chase:
    9.             if (monsterstateOnce())
    10.             {
    11.                 Debug.Log("once on enter");
    12.             }
    13.            
    14.             break;
    15.         }
    16.        
    17.     }
    Anyways, I don't know if this is the standard way of doing this or if it could be improved because I just kinda freestyled this based on my own needs. If it could be improved in any way, please let me know!
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    29,654
    It's hard to offer commentary on code unless you're using it.

    State machines can be done ten zillion different ways, but I find it is almost always best to specifically make the state machine you need each time, rather than trying to come up with some global generic way that ALL your projects will forever use into the future.
     
  3. Zebbi

    Zebbi

    Joined:
    Jan 17, 2017
    Posts:
    521
    Yeah, that’s why I’m doing this the way I need it. It pretty much gives me everything I need for now and is reasonably easy to follow, I was just interested if anyone else had used this kinda technique or might find it useful.