Search Unity

FSM and multiple entities

Discussion in 'Scripting' started by Bonfi_96, May 15, 2018.

  1. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    35
    Hi guys, I'm studying a bit FSM and trying to figure out how to use them correctly
    My current implementation has an interface to implement states, so each state is a class on its own.
    The problem comes when I want to have multiple entities using FSM.
    Let's say I have a player with some states and an enemy with some completely different states. What's the best way to differentiate between them?
    Would it make sense to have inherit the state interface? Like having an IState, and IPlayerState, IPotatoCannonState,...

    Thanks!
     
  2. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    I found this tutorial to be pretty useful, which explains how to build a fairly simple, but flexible, FSM in Unity using ScriptableObjects:

    https://unity3d.com/learn/tutorials/topics/navigation/intro-and-session-goals?playlist=17105

    The basic idea is that States aren't really anything special; they're just collections of Actions and Transtions that you can build out however you want. Here's an example of how I've used this approach recently to create an AI in my game:

    upload_2018-5-15_10-58-32.png

    This is an instance of a state which the AI enters when they are chasing after a target. It defines the actions to be performed while chasing (basically, set NavMeshAgent's destination), and Transitions, which are conditions that might cause the AI to transition into a different state. In this case, it keeps checking whether it's in Combat range (in which case it transitions to the Combat state), and it keeps checking whether the target is visible (if not, it starts looking around).
     

    Attached Files:

  3. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    35
    That's a really interesting way of using scriptable objects!
    Though in this case the StateController acts as a player controller, so there is a requirement for a reference to a State controller object in a State. My question is more like, If I had multiple State Controllers (different player kind, enemy or something else) they would need to operate on different data and have different info in them. How can I handle this in an elegant way?

    By the way I'm having a good read here but they are reffering here too to a single "state controller" which in this case is the player class too
     
    Last edited: May 15, 2018
  4. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    The states don't have a reference to a State Controller, but the methods performed (Decide, Act, etc) accept the State Controller as a parameter. So you should always have access to the state controller. I subclass a base State Controller for different AIs, because different actions and decisions might operate on different data.
     
  5. HeaDiii

    HeaDiii

    Joined:
    May 18, 2015
    Posts:
    61
    For this kind of mechanic I used to work with Interfaces as well, but it turned out to be quite an overkill for most of my cases. It really depends on the size of your unit-behaviours.

    Currently I'm working on an RTS Game where the player basically just places buildings and commands warriors. There are tons of peasants and workers of different kinds (lumberjack, ironsmith, builder, miners and so on) and every single kind of worker needs his own kind of behaviour. I'm using an FSM there as well, but this basically consists of something like this:

    Code (CSharp):
    1. private enum WorkerStates
    2. {
    3.     GoToHouse,
    4.     GoToResource,
    5.     ChopTree,
    6.     DeliverLumber,
    7.     Chill
    8. }
    9.  
    10. private WorkerStates _CurrentState;
    11.  
    12. private WorkerStates CurrentState
    13. {
    14.      set {
    15.          _CurrentState = value;
    16.          switch (_CurrentState)
    17.         {
    18.             case WorkerStates.GoToHouse:
    19.                 Debug.Log("Going to house");
    20.                 break;
    21.             case WorkerStates.GoToResource:
    22.                 Debug.Log("Going to resource");
    23.                 break;
    24.         }
    25.     }
    26.     get { return _CurrentState; }
    27. }
    In my actual code I'm using coroutines instead of Debug-Statements, which change the CurrentState as their last step.

    This works perfectly fine for my case, but there isn't actually much going on. I'm just not using the overhead I would've created when using interfaces and writing every state-behaviour in its own class. The basic stuff every entity needs to know (for example pathfinding, current location and some other information) are stored in a BaseClass every WorkerClass inherits from. This way, I can concentrate on creating only the appropiate behavior for every single worker.

    Some guy called N3K made a tutorial-Series on a Tower-Defense game in which he's using some kind of state-driven behaviour where every behaviour has its own class. You can take a look here, maybe this helps you too: