Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Official State Machine

Discussion in 'Open Projects' started by Dustin_00, Sep 29, 2020.

  1. cirocontinisio

    cirocontinisio

    Joined:
    Jun 20, 2016
    Posts:
    884
    Animator controller is really made for animation, with concepts that don't match too well the traditional idea of a state machine. To give you an example: FSM generally don't blend between states. This means that in some way you have to remove functionality from the Animator Controller while adding the one that is "missing". This can feel like a hack to some, even though some people did build games using the Animator Controller as a generic state machine.
     
  2. cirocontinisio

    cirocontinisio

    Joined:
    Jun 20, 2016
    Posts:
    884
    Still thinking about this thread. Unfortunately the size of all the PRs proposed here makes this decision A BIG decision now, which is delaying it. That's why I specified in the card and in the thread to go for a "v1". Will come back to you soon-ish.
     
    kcastagnini likes this.
  3. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    271
    For Character we can go with Animator for now.

    I've made my PR only for review, not to actually push it in project right away.
    Generic State Machine is a complex topic, and foundation is most important there, we don't need to rush it.

    Currently I want to rewrite my implementation to Graph nodes, as I found working in a single node inspector quite limiting, even for simple state machines
     
    Walter_Hulsebos likes this.
  4. TomateSalat

    TomateSalat

    Joined:
    Apr 13, 2018
    Posts:
    16
    Imho you are too much focused on "reinventing the wheel". Where is the value of writting a new FSM-System? And if you're honest to yourself: nearly nobody would use it outside of the project. Don't get me wrong: what you've written looks nice (haven't tried it out). But if I would have to make a decission for private project: yours or a battle tested solution like Bolt. Then Bolt would win instantly.

    And where do you stop? You could use the same arguments for rewritting the cinematic package. And the CharacterController - well even the RenderPipeline.

    Existing solution have the benefit that there is existing knowledge. There are communities which can be asked in case of problems. Another big advantage is: Unity is the owner of bolt and it would be a great opportunity to try out their own tool.

    In the end that project is about creating a game. Therefor we should focus on that and not on creating new libraries (at least that is my opinion).
     
  5. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    271
    Did you forgot what Open Source is?

    Bolt was not made from ground up to solve FSM or AI problems, and it has a lot of flaws in it's own visual coding area, so that many people would not want to use it in their projects (especially medium ones).

    Yes, and I'm using this knowledge to try to improve these workflows, avoiding mistakes made in other solutions.
    It's all about research and implementing best ideas.

    It's not only about the game, writing custom tools is a big chunk of real game development.
    There's already multiple small teams of contributors that are working independently from each other, many on the game itself, others on Systems, and someones on Editor experience / QoL.

    It's not their own tool, they've just brought it from Ludiq. Unity's unified visual scripting tool is under heavy development, and will likely be released only in 2021~2022.
     
    Last edited: Oct 13, 2020
    Walter_Hulsebos and dotsquid like this.
  6. invadererik

    invadererik

    Joined:
    Oct 31, 2010
    Posts:
    148
    If the major negative of: Bolt / any visual coding system / custom drag and drop FSM system
    is that we cant just look at PR diffs in github and know easily what changed;

    Then we should probably just go with something simple and straight forward like @Proryanator 's approach of all code FSM ... There could be ways like the visual tool outputs code, where you could have both worlds, but I think its beyond the scope of this project.

    On the other hand if we decide that we don't care about diffs and we are going to go with some type of visual logic system, then I do feel like @TomateSalat has a point, maybe lets just use Bolt. Otherwise we are going to run constantly into bugs, missing features, issues with ux, possible breaking serialization changes, while building something that already exists, is battle tested and for free with many extra features.

    @Neonage About that priority queue approach, its interesting, but I think the devil is in the details, I can quickly see with that approach having some issue with the order, where moving one thing forward or backwards creates bugs and also some cases where there is a clash with the ordering, you might need to create some silly thing like: crouch-highpriority, crouch-lowpriority (basically same state but at different priorities) . Also I feel like that idea is similar but less well thought out than using a more widely known approach like a Behavior Tree.
     
    Walter_Hulsebos, MagdielM and Neonage like this.
  7. islesofurth

    islesofurth

    Joined:
    Oct 10, 2018
    Posts:
    6
    I think it would be best to use an enum & hard code the FSM with a task list.

    - Its easy to setup
    - If you don't know how animation trees work, you can rely on the enum
    - It is very easy to expand on
     
  8. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    271
    Yes, we do care about PR code diffs, but the negative is not only about it.

    With custom FSM we have only logic flow as data, and with Bolt we have whole code architecture inside State Machine.

    For me Bolt is so unintuitive, it's much harder to learn and scale than normal code.

    I honestly feel that what is missing in the core engine is not another Blueprints, but a well thought State Machine with nice API, that focuses on logic and behaviour separation.

    Many teams are writing their own solutions for this:
    ex. Pathologic 2 with their combination of HFSM and Behaviour Tree, one FSM - many trees.
    Their thing is even connected to the game build with virtual machine, so you can manipulate every game object at any time. Pretty much like Live Link in ECS.

    And btw, designers may learn this kind of modular coding (instead of learning Bolt) just by reading manual, without need to know every aspect of the C#.
     
    Last edited: Oct 14, 2020
  9. DapperDino

    DapperDino

    Joined:
    Feb 18, 2018
    Posts:
    20
    I have always made really basic jumping in the past so I thought I'd try and implement a similar system with holding to jump longer so I tried to make that work with what I already had and it seems to work well :)
     
  10. alexchesser

    alexchesser

    Joined:
    Sep 15, 2017
    Posts:
    147
    I actually thought about this one overnight. Without being too hyperbolic, this is a tough call that has pretty massive implications for the course of the entire project.

    In looking at @Neonage's solution, it is really nice and elegant and seems pretty simple in principle. The problem in my mind arises where we're just kindof hand-waving over the intricacies of writing dozens of individual IStateData, IStateActions, IStateDecisions etc...

    • Does bolt open up the range of designers who are able to access and create custom behaviors?
    • Does folding the FSM under code limit who can work on it?
    • In future, does the hand-rolled FSM get replaced by the Unity native AI Planner package?
    • Is BOLT going to be added later in the project anyways (via popular community demand)?
    • Can BOLT scripts be designed to output IStateActions for the FSM?
    • Does the additional effort and overhead required to use BOLT offset by the fact that we are using a set of public tools as opposed to a hand-rolled option?
    I think the last question is most important to consider within the scope of this project.

    Working with widely accepted industry standard tools leads to skill growth for the team for things that can be easily generalized to future projects, while using a bespoke hand-rolled solution limits the range of development options in terms of things like available documentation, stack overflow questions, it limits the number developers who can "hit the ground running", and limits the "resume credit" of working with a hand-rolled framework.

    On balance I lean slightly towards using BOLT for the openness and accessibility angle. On the other hand - the FSM is way further along than a bolt system. Given a six month timeline bird-in-the-hand theory may apply here :)

    I'll keep an eye on how this progresses from everyone else's point of view and meantime maybe see if there is a way to make BOLT output StateActions (and the other critical features of the neonage FSM).

    Which in the end would address my only major concern.
     
    Neonage likes this.
  11. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    271
    It's a common modular approach, we only need to write small reusable pieces of code. Just like components and systems in ECS, much more natural for thinking.

    Argh!! Another package that I never knew before :(

    I'm also doing tons of research right now, so don't write me off before second iteration :)
     
    alexchesser likes this.
  12. AdrianFL

    AdrianFL

    Joined:
    Jul 15, 2020
    Posts:
    5
    Just to add my point of view to the Bolt vs hand-rolled option:

    In my opinion, I agree with Ciro on the drawbacks of the current proposals. Accepting a large amount of code at this point for a core system of the game means taking a decission that will not be easily undone if we later on decide to change to something else.

    However, I don't think Bolt is the solution here. First of all, even if its not for the FSM, at some point we will need to build complex systems in code during the development of the game, not doing it now is just moving the problem to the future. Moreover, I don't consider going with the Bolt solution is going for the industry standard. In fact, if I had to choose, I would consider coding a FSM machine to be the industry standard, and the internet is plenty of resources and examples about it.

    Finally, I don't consider a FSM on Bolt to be necessarily more simpler. Yes, it will probe to be more accessible to non-programmers, but for programmers will be less accessible, and that doesn't guarantee that the system doesn't grow exponentially in complexity. We are just moving the complexity from our code to a visual scripting language.

    What I think we should do instead is the following:
    1. Try to aim for a more simple V1. Instead of adding more code, or taking someone's solution, lets get the most basic version possible in, and collaborate between everyone here who is submitting PRs to start building from there. In this way, we are avoiding to depend from the author of the main PR, as we will have multiple responsibles of the FSM.
    2. Work more on documentation. This should be crucial to make sure we can onboard more people into the existing systems as the project advances. We should try to explain how the FSM works with diagrams and written documentation so that everyone can expand it.
    3. Expose a visual system so designers can interact with the FSM properly. We don't need to reinvent the wheel here, but this is something we could be discussing in the upcoming weeks into how to do best, after we have a foundation for the FSM accepted into the main branch.
     
  13. invadererik

    invadererik

    Joined:
    Oct 31, 2010
    Posts:
    148
    Just to clarify one point about "Large amounts of code", if we remove the examples and just have PR's with only the FSM code, its actually very little code:

    @Proryanator : 3 / 25 files ( the rest of the files are actual implementation of current character controller using FSM)
    @Neonage : 15 / 138 files out of which 4 are editors ( the rest of the files are an example using some critters that like pizza)
    @kcastagnini : 11 / 113 files out of which 2 are editors ( the rest of the files are an example with a capsule that can jump, shoot and crouch)

    Sorry about other PR's I havent looked at them.
     
    Last edited: Oct 15, 2020
    Walter_Hulsebos and kcastagnini like this.
  14. Zak_Ipatov

    Zak_Ipatov

    Joined:
    Jul 21, 2014
    Posts:
    4
    I'm also working on very basic FSM editor in Animation Controller style, so maybe it will fit this project.

    Despite this I also want to give a little opinion about what approach to choose. I think a lot of people look at this open project in educational way, because it's a good opportunity for learning and practicing. So it's definetly not a good way to use such tools as Bolt, espessially considering we are trying to simulate real production process. I'm sure that community-written approach is better. The rest was already written by AdrianFL in details.
     
    Neonage likes this.
  15. fran_m

    fran_m

    Joined:
    Jul 22, 2020
    Posts:
    40
    Sorry if I say something stupid due to my ignorance. If we use a FSM (coding, Bolt...), do we have always use this one? Cannot use both Bolt and a coding approach for differnt characters? The goal is not to mess or make it harder, the goal, and my goal, is to learn, so we can learn 2 different approaches, in case this is techically possible, I do not know.
     
  16. invadererik

    invadererik

    Joined:
    Oct 31, 2010
    Posts:
    148
    @fran_m there is nothing really blocking the project from using multiple similar tools, but I think most people are of the opinion that the project will be easier to understand and manage if only 1 tool is used.
     
  17. deivsky

    deivsky

    Joined:
    Nov 3, 2019
    Posts:
    87
    I've been working on (yet) another FSM. This is a long one so please bear with me.
    First off we have states, which can hold multiple actions and multiple transitions:
    upload_2020-10-15_17-12-32.png
    And each transition holds a target state, and a set of conditions:
    upload_2020-10-15_17-19-24.png
    Now, this seems basically the same thing everyone's doing except with crappy UI. However, what I'd like to share with you is my approach at solving one common problem with all of the SO-based FSM I've seen, which is handling per state machine data.

    @kcastagnini addresses this issue with generics. If we can make sure that passing in the same object to every state in a state machine is going to work, then that's great. And it totally works, I've taken this approach in the past. But a downside to it is that it binds each StateMachine<T>, State<T>, Action<T>, Transition<T>, Condition<T>, to... well... <T>. If you have an object with a slightly different Data Model, but some of the states are the same, you have to either use the same Data Model and add what's missing and ignore what you don't need, or make a new Data Model and copy and paste a bunch of code.

    @Neonage 's approach is basically adding a bunch of static dictionaries. It's super elaborate and robust, but doing lookups every update could lead to performance issues, and I'm just not a fan of static dictionaries.

    So I wanted to find a new solution, and came up with this. For those familiar with ECS, this approach could be seen as using SOs as authoring components for the states, transitions, actions, etc. Basically we need to split the runtime components from the designer-friendly components. So by taking a look at my solution explorer we can easily differentiate between the two:
    upload_2020-10-15_19-32-27.png

    Now, starting off, the StateMachine is the only MonoBehaviour, and it's going to hold a ScriptableState which will be its initial state. And as I said in the beginning, a ScriptableState is nothing but a container of ScriptableActions and ScriptableTransitions, and a ScriptableTransition is just a container for a target ScriptableState, and a set of ScriptableConditions. As their name implies, these are all ScriptableObjects and they're those ugly inspectors that you saw.

    During the StateMachine's Awake, the method GetState gets called on the initial ScriptableState:
    upload_2020-10-15_20-48-18.png
    This triggers a chain reaction in the behaviour tree in which all of the states, actions, transitions and conditions that compose it resolve into their corresponding runtime components (which are plain C# classes), to finally return the actual state object.

    All of these runtime components have an abstract Awake(StateMachine) which is called when instantiating them, and since they belong to one specific StateMachine, any GetComponent calls and initialization they might need can be done directly inside of it.

    Here's a super simple example of what I mean:
    upload_2020-10-15_20-9-33.png

    As you can see, there's a ScriptableMoveAction which is the ScriptableObject a designer can use to attach to multiple states; and then we have MoveAction, which is the actual object we're using at runtime and executes the action. Notice how we can simply cache the CharacterController since we know that one (and only one) instance of this Action belongs to one (and only one) instance of a StateMachine. No GetComponent every update, no lookups, no data models; this action will work on any state on any GameObject with a CharacterController.

    If you read through all of this, thank you. I'd like to hear your thoughts! :)
     
  18. invadererik

    invadererik

    Joined:
    Oct 31, 2010
    Posts:
    148
    PR or it didnt happen LOL = ]
     
  19. islesofurth

    islesofurth

    Joined:
    Oct 10, 2018
    Posts:
    6
    I put in a PR @ here https://github.com/UnityTechnologies/open-project-1/pull/91
    you can see my sugestion for how i think the Character Controller / State Machine should be set out.

    It is basic but not fully set up yet, it is just something for an idea to work from

    Inputs all reference a "Name" rather than a "Key" to simplify controller management.

    Each "State" area is refrenced with a comment, so you can see when it begins.


    The GDD does not mention how attacks or hits are to happen, so I Left the Attack open & added an invulnerability timer to the hit state.
    I also Assumed damage would be taken via collision & triggers.
    I would be nice to have some more information on areas like this, since the GDD is not up for discussion.
     
  20. fran_m

    fran_m

    Joined:
    Jul 22, 2020
    Posts:
    40
    I agree with you, it is obvious. From a educational o learning point of view is more interesting to learn different approaches. We must not forget that this "Open Project" forum is under the category "Community Learning and Teaching". Another option could be: one approach for this project and for the next one use a different one.
     
    Last edited: Oct 16, 2020
  21. kcastagnini

    kcastagnini

    Joined:
    Dec 14, 2019
    Posts:
    61
    Sorry, one question. In your ScriptableMoveAction example, where do you store the references to the instances of MoveAction objects?
    In other words how ScriptableStateAction<T> uses T?
     
  22. kcastagnini

    kcastagnini

    Joined:
    Dec 14, 2019
    Posts:
    61
    All the submitted implementations (except mine) tie transitions to states, while I prefer to keep all the transition logic in a transition table and decouple transitions from states (which are now just a collection of actions).

    Since I am the only who took that route I'd like to discuss this design approach with you, maybe I am missing something.
    I think that having a transition table will help a lot because all the logic is in one place and not scattered around, plus we can create a new transition logic (modify transition(s)) without having to modify/duplicate states.
    We can also easily do some powerful stuff like defining "any state" transitions.
    It looks like this:
    transitionTable.PNG

    What do you think are the benefits of having transitions tied to states on the other hand?
     
    Last edited: Oct 16, 2020
  23. deivsky

    deivsky

    Joined:
    Nov 3, 2019
    Posts:
    87
    I'm working on cleaning my fork and adding a few examples and then I'll submit my PR. But to answer your question, Action references are stored inside the States themselves, they're not stored inside the ScriptableObjects.
    And as for the ScriptableStateAction<T>, this is how it works:
    I have a base not-generic class that contains the internally called GetAction method which returns (in this case) the MoveAction:
    upload_2020-10-16_11-2-54.png

    The dictionary there is to avoid instantiating the same action, condition, etc, multiple times for the same StateMachine since they're likely to be repeated throughout the behaviour tree.

    You can see that this base class has an abstract CreateAction method. If you need a custom editor or want some exposed values to then pass to the Action, you'd just derive from the base class and make your own CreateAction. For simple actions, though, I made this to avoid boilerplate:
    upload_2020-10-16_11-24-0.png
     
    Walter_Hulsebos and kcastagnini like this.
  24. deivsky

    deivsky

    Joined:
    Nov 3, 2019
    Posts:
    87
    I actually like your approach. It's very neat and intuitive for the designer. I was mainly aiming at a proof-of-concept with my implementation, but I'm thinking a mix of your transition tables, @Neonage 's sick editor skills, and my separation between SOs and runtime behaviour would be ideal.

    Edit: I'd like to add though, the main problem I see with your approach is that the transition table could become really extensive. It might need a custom Editor Window where you could see and add per-state transitions or something like that.
     
    kcastagnini likes this.
  25. kcastagnini

    kcastagnini

    Joined:
    Dec 14, 2019
    Posts:
    61
    Yeah the idea was to group transitions per source state, I didn't implemented it because I just wanted to create a v1.
     
    deivsky likes this.
  26. Neonage

    Neonage

    Joined:
    May 22, 2020
    Posts:
    271
    Alright, as everyone are doing basically the same stuff now, I think we need to do a little recap of our first iteration and discuss important problems while brainstorming new ideas.

    What do you guys think of our current implementations?

    I personally struggling without Node Graph, even on simple stuff, as there is no connection / visualization, and single-object GUI is very limited and not scalable (no matter how sick I made it look - it's crumpled), I'll drop this idea.

    And @kcastagnini, you were right, making everything (transitions and actions) in one object is not very modular. Actions shouldn't know anything about transitions, so designers can combine them in any way they want.

    So, here's what I'll try in my second iteration:
    - Hierarchical Logic Graph.
    - Flow View as root, with all decisions and transitions in one place.
    - Behaviour Trees as sub-graphs instead of simple actions sequence.

    This of course is hard, and would require me to rewrite whole thing from scratch, but that's what you do in looking for ideal architecture! :)

    Oh, and one very important thing we haven't discussed yet -- Blackboard and data manipulation.
    Ex. Get Eyesight result Transform and Set into Chase Target. How do we implement this in code and expose to user?
    Here's how I deal with it right now:
    Implement OnAftermath method in which we invoke SetData based on made decision. Fine and dandy, but there is no way to know ahead which type is gonna be changed for Graph visualization... Any ideas?
     
  27. deivsky

    deivsky

    Joined:
    Nov 3, 2019
    Posts:
    87
  28. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    476
    Here is my approach to FSM.
    It uses MonoBehaviours and GameObjects hierarchy(but also can use ScriptableObjects if it really needs to).

    That's how it looks in action:
    (green is current impl, blue is FSM version, purple is FSM variant with double-jump)


    The structure(or better to say hierarchy) is quite simple:
    StateMachine-root
    --ConcreteState + [optional list of custom actions that are just components]->
    ----Transition0->
    ------Condition0
    ------Condition1
    ----Transition1->
    ------Condition0

    That's how looks current movement implemented with FSM:
    upload_2020-10-18_17-14-2.png

    Yeah, you can say it's kinda messy, but I would like to see how it will look using SO workflow(spoiler: most likely it will not fit a single screenshot)
    And I must note that there are NO editor scripts or extensions. That's all provided by the engine which leads to consistency and bug-proof.
    If in the future we will need to make some kind of FSM visualization(or even visual FSM editor) that would be really easy! "Back-end" stuff provided by unity and all you need to do is to somehow visualize it.


    What I also like in this approach is the ability to create variants or nested FSMs.
    For example, here is a prefab variant from 'Pig FSM Variant' that adds the ability to double jump.
    upload_2020-10-18_17-15-12.png

    I've made this implementation literally in one day. It's proof of concept. There is no dependency injection into states right now, but that just a matter of time. If someone is interested in this kind of approach I will continue to develop it.
    Otherwise, good luck with SO! I did everything I could;)
     
    islesofurth and peaj_metric like this.
  29. kcastagnini

    kcastagnini

    Joined:
    Dec 14, 2019
    Posts:
    61
    Hello guys, this is maybe a little OT but I'd like to share with you the PushdownAutomaton (fsm + stack) I am writing since I can't find one in the Unity asset store.
    This is a code only solution inspired by the StateMachine written by Jason (@Proryanator maybe you are interested in this).

    Code (CSharp):
    1.  
    2. //this class helps to define the transition logic
    3. var builder = new PushdownAutomatonBuilder();
    4.  
    5. //define a transition from standing state...
    6. builder.From(standing)
    7.     //...to jumping state if isGrounded and jumpRequested are true
    8.     .To(jumping, isGrounded, jumpRequested)
    9.     //...to crouching state if crouchRequested is true
    10.     .To(crouching, crouchRequested);
    11.  
    12. //define a transition from any state except firing (you can list other states to exclude them too)...
    13. builder.FromAny(firing)
    14.     //...to firing state when enemyInRange is true
    15.     .To(firing, enemyInRange);
    16.  
    17. //define a transition from firing...
    18. builder.From(firing)
    19.     //...to the state preceding firing when enemyKilled is true
    20.     .ToPrevious(enemyKilled);
    21.  
    22. PushdownAutomaton pda = builder.Build(standing); //specify the initial state
    23.  
    24. //call in Update or FixedUpdate etc.
    25. pda.Tick();
    The idea is really simple: you create transitions by defining a source state with the From(source), and a target state with the To(target, condition, params[] conditions) method.
    The conditions inside the To methods are Func<bool> expressions that need to be true in order for the transition to happen.
    When calling Tick() the pushdown automaton will try to transit from the current state if the conditions associated to the current state are true.
    Since this is a PushdownAutomaton it stores the history of the previous states we have been and we can transit to the previous state with a ToPrevious transition. This is not possible with a simple StateMachine.
     
    Last edited: Oct 18, 2020
    deivsky likes this.
  30. deivsky

    deivsky

    Joined:
    Nov 3, 2019
    Posts:
    87
    That's pretty neat, I'm definitely interested! I'd totally go for a code-only FSM for my own personal projects. How are states implemented, do you also have a Builder for them taking Action instead of Func<bool>?
     
  31. kcastagnini

    kcastagnini

    Joined:
    Dec 14, 2019
    Posts:
    61
    Thanks!
    States are classes that implement the IState interface.
    Code (CSharp):
    1. public interface IState
    2.     {
    3.         void OnEnter(); //called when entering the state
    4.         void OnExit(); //called when exiting the state
    5.         void OnTick(); //called by the automaton when this is the current state
    6.     }
    That way you have complete freedom on how to implement them, they can be MonoBehaviour, SO or just plain C# classes, whatever you want.

    This is one possible implementation for example:
    Code (CSharp):
    1. public class ActionState : IState
    2. {
    3.     public event Action OnEnterCallback = delegate { };
    4.     public event Action OnExitCallback = delegate { };
    5.     public event Action OnTickCallback = delegate { };
    6.  
    7.     private string _name;
    8.  
    9.     public ActionState(string name) => _name = name;
    10.  
    11.     public void OnEnter() => OnEnterCallback();
    12.     public void OnExit() => OnExitCallback();
    13.     public void OnTick() => OnTickCallback();
    14.  
    15.     public override string ToString() => _name;
    16. }
     
    Last edited: Oct 18, 2020
    deivsky likes this.
  32. mattinjersey

    mattinjersey

    Joined:
    Dec 3, 2016
    Posts:
    42
    Just my $0.02. I myself am pretty decent programmer but I guess I am a novice compared to many people here.
    If this project is just going to be highly skilled programmers debating the nuance of various techniques that I don't understand... its not going to be very interesting or useful for me.
     
    MehO and MUGIK like this.
  33. quibit

    quibit

    Joined:
    Jan 1, 2019
    Posts:
    12
    I've just started going over this, few hours in (don't worry I don't plan to make another FSM implementation), and I'm deeply enjoying this discussion.

    I'm primarily a Web developer by profession, game dev in free time, so with my limited time, I'm going over the solutions in this thread, and mostly learning and seeing how to break them and finding pros and cons, figure that's the best way to help right now.

    I've started with kcastagnini solution, and I'm finding it very elegant so far. Good use of generics and nice decoupling. I see you improved on the 'Pluggable AI' series by Unity by decoupling the Action from the StateController, that was pretty neat.

    I hope to have actual suggestions/critics soon, given my background and perspective, not all may be applicable, but new perspectives and discussions can only contribute to improving the end product. Looking forward to going over the solutions here, good job.
     
  34. peaj_metric

    peaj_metric

    Joined:
    Sep 15, 2014
    Posts:
    146
    @MUGIK that looks pretty much like the approach I took some time ago.
    Although the SO solutions look well thought out and sofisticated I think this is really the simplest most straight forward solution.

    The downside is a little overhead from enabling/disabling whole GameObjects.

    But on the Plus side:
    - It can use standard Unity components out of the box (Audio Source with PlayOnWake will just play when attached)
    - Everybody can just write Monobehaviours with OnEnable/OnDisable
    - It can be built/stored either in a scene or a prefab
    - It can be reused and modified via prefab variants
    - It even supports nested state machines
    - It does not require any editor scripts/UI (state changes can be observed in hierarchy)
    - It would be possible to separate states from transitions if necessary

    As I siad I tried this approach some time ago and was a bit worried that it was to simplistic at first but it ended up being used for the whole (small) game project and was pretty stable.
    I also had a custom node editor for it (which was easy to add on top) but it is not neccessary at all.
     
    MUGIK likes this.
  35. samlletas

    samlletas

    Joined:
    Jan 2, 2016
    Posts:
    30
    Thinking about it, a code-based approach seems like it would be a good idea, Unity's request for this task was to keep it simple anyways and we could expand on features later if needed. I saw some concerns about not having a visual representation of the states in @Proryanator 's approach but to be honest I'm not really sure if we need that right now, it would only add complexity to the code base.

    I'm liking @kcastagnini 's idea of using interfaces for states, very flexible.

    This reminds me of Stately, a code-based state machine solution. I'm wondering if we could take inspiration from it in how they handle transitions (e.g. transition to another state after some time, after N frames, when signals are received, etc.):

    https://stately-csharp.readthedocs.io/en/latest/transition.html
    https://gitlab.com/thatcosmonaut/stately/-/blob/master/Stately/src/Transition.cs
     
    Proryanator and deivsky like this.
  36. deivsky

    deivsky

    Joined:
    Nov 3, 2019
    Posts:
    87
    What did you expect from this project? If learning from others isn't interesting or useful to you, I really don't know what to say.
     
  37. deivsky

    deivsky

    Joined:
    Nov 3, 2019
    Posts:
    87
    I like where this conversation is going, let's overthrow SOs! Ok no, but it is true that this task is getting delayed a lot. Let's focus on the card:
    The card is only for the main character, and the possible transitions are quite obvious, there's no need to make it designer friendly any more than exposing a few fields, so we could make it code-based. We'll see if we regret it in the future, but for now I think we should get the work done or we won't finish in 6 months.
     
    quibit and Neonage like this.
  38. fran_m

    fran_m

    Joined:
    Jul 22, 2020
    Posts:
    40
    I am also newbie in Unity and game developing but I am learning a lot from these experienced people. Just try to read carefully and does not matter if you do not understand 100%, me neither and I am still learning. I have also experience programming, and the most difficult here at least for me, is not about coding, is about to understand how Unity and game development works.
     
    Zak_Ipatov and cirocontinisio like this.
  39. shuttle127

    shuttle127

    Joined:
    Oct 1, 2020
    Posts:
    183
    While I agree there's always something to be learned, maybe what @mattinjersey is trying to say is that you can't run (discuss nuances of techniques) before you walk (understand the techniques). I could see how it's a bit intimidating trying to, especially when everyone comes at things from a different perspective.

    For a little personal perspective, when I first found out about this project, I thought, "Oh hey, here's a cool way to get some credit for a project that will definitely get deployed," and then I came and saw some of these discussions and had a similar first impression to @mattinjersey. Then, I took a step back and saw other ways I could contribute or even benefit from the experience.

    Everyone is excited for this opportunity, but not everyone on the forums will be credited in the final game (me included). There are lots of people posting on the forums "Oh, I'd like to help, please let me know what I can do," which to me comes across as "I want to help but I'm not sure where to start." That could stem from being a bit overwhelmed by existing discussions already too.

    If the goal is to be credited by helping with coding and one feels overwhelmed by it, there are other ways to contribute, like story, art, QA/testing, and even the game title. During the first live stream, Ciro made sure to mention QA opportunities MULTIPLE times because he's aware that many people might feel a bit intimidated by the coding but would still want to contribute.

    Just my $0.02. :)
     
    Last edited: Oct 19, 2020
    MehO likes this.
  40. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    476
  41. deivsky

    deivsky

    Joined:
    Nov 3, 2019
    Posts:
    87
    I totally get that but...

    ... That's the thing, that's not supposed to be the goal of this event. We all want to contribute, obviously, but more than anything this project is about learning. Everyone is at different stages in terms of experience and knowledge, but we're all constantly learning and trying to improve.

    To give my personal perspective, I have about 2 years of personal experience with C# and Unity, no work experience in either, first time using github for other than my own repos. I was a little hesitant to join the conversation as well (this is also the first time I've participated in a forum), but at the same time I wanted to because this is a chance for me to sort of validate what I've learned on my own, compare it to what other people are doing, and make sure it is actually usable in a production environment.

    I'd never implemented an SO state machine, I first watched the pluggable AI tutorials, then I went through the multiple PRs, and then I tried to implement my own version with the few things I'd do differently. Will it be used? Doubt it. Did I learn from it? A lot. So if you don't understand something, look it up, watch tutorials, try to make it yourself. Also you can ask, even if you think it might be stupid, it adds way more to the conversation than going around saying this project isn't useful to you, the simple fact that you don't understand something means that it is.

    Let's just get back on topic now, I didn't mean to give this much importance to that post.
     
    Neonage and shuttle127 like this.
  42. cirocontinisio

    cirocontinisio

    Joined:
    Jun 20, 2016
    Posts:
    884
    Thanks everyone for the conversation, I'm also enjoying the back and forth.

    I hope you don't feel discouraged. In any case, whatever state machine we decide to use, we will do a review of the code and explain how it was done (most probably in one of the livestreams).

    Back on track: I pledged to make a decision this week, and 3 more solutions popped up. Which is not a bad thing! But I really want to pick one soon.

    In any case, as I said before, we want to credit everyone who made a viable solution even if it doesn't actually make it into the repo. We think it's important work because it furthered the conversation and eventually led to better solutions from everyone.
     
    Proryanator, konsnos, Fhenix and 2 others like this.
  43. alexchesser

    alexchesser

    Joined:
    Sep 15, 2017
    Posts:
    147
    You raise a really good point Matt. I think you'll find that even among the "debates" around FSM people seem to be coalescing around a solution. For example if you look at the @Neonage post above, they say

    "Alright, as everyone are doing basically the same stuff now, I think we need to do a little recap of our first iteration and discuss important problems while brainstorming new ideas."​

    So I think you're safe to hang back and not really worry about the details until one of the solution-candidates becomes "the real one." From that point you'll be able to put non-wasted effort into understanding the FSM that we are using without really having to understand the nuances between the various systems.

    Hang in there!

    I've been programming professionally since 1998 and tuned out of this debate 4 PR-solutions ago. :)

    When the final state machine is ready we can put some effort into understanding the one we have.
     
  44. peaj_metric

    peaj_metric

    Joined:
    Sep 15, 2014
    Posts:
    146
    @MUGIK

    Didnt have much time to look into the details yet but it looks promising.

    I am curious whats the advantage of having Transitions and Conditions on there own GameObjects?
    Couldnt they just be components on the State GameObject?
    This should describe their relationship pretty well -> A state has transitions
    It would also make it easier and more obvious to have sub statemachines as one statemachine would just be one hierachy level

    As complexity has been mentioned as a concern a few times thoughout this thread:
    The use of the interafaces (with using StateMachine builder, SOs or MBs) make this statemachine really flexible but it could be a lot simpler if it would rely MBs only.
    This way it would not even be neccessary to have OnEnter, OnUpdate and OnExit and propagate it throughout the states, transitions and conditions.
    All of them could just use OnEnter, OnExit and Update which are called by Unity anyway if the state/GameObject is active.
     
  45. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    476
    Transitions have to be on other children's GOs because that allows having several transitions from state. Also, States' GOs are already occupied by Action components.

    Conditions, however, could be on the same GO with the corresponding Transition component.
    But I like the idea that you can read the whole StateMachine from the inspector. Separate GOs allow setting names for States, Transitions, and Conditions individually, so you can get the basic idea of what is going on without deep diving into details and looking at each GO's components. Just read the hierarchy!

    One more thing is that when you creating a prefab variant from StateMachine that uses this structure, you can easily enable/disable/add/remove anything in that state machine! That's the power of the new prefab workflow. For example, add another condition to transition, or add a new transition from the state, or disable transition for certain variants. That's very flexible, and again, provided by Unity.

    That's true. I've just tried to take into account all previous suggestions, idk. It definitely shouldn't be merged into the project;)

    Don't you mean to use OnEnable/OnDisable for this?
    And yes, that way state machine would be really simple! I have no complaints about this approach.
    Hmmm, however, you wouldn't be able to run state machine on prefab like when using SO approach:)
     
  46. cirocontinisio

    cirocontinisio

    Joined:
    Jun 20, 2016
    Posts:
    884
    I renamed the thread to better reflect what it is about, since it has totally derailed from the intended original scope.

    Maybe one day we will get to a state machine to use on the character :D
     
    alexchesser, tmcdonald and MUGIK like this.
  47. javimtib92

    javimtib92

    Joined:
    Aug 15, 2020
    Posts:
    7
    First of all I'm sorry for creating another PR for a different approach of a State Machine, I can imagine @cirocontinisio that you are having a hard time reviewing all different options. I liked the approaches that I saw in this thread and I've learned a lot from them.

    I'm pretty new to Game development and I know my limitations atm, but for starting with my fun side project I've been using a simple state machine handled by code that has done the job for me to start with.

    As you asked for a simple generic state machine I thought it was a good idea to create one based on Bardent tutorial and integrate it with the current code of our character.

    My PR is not intended to be merged as it is, the purpose is to showcase this approach and see if it can help. If the idea is liked then we can change it a little bit to follow the conventions and to do things a little bit easier.

    The PR is this one https://github.com/UnityTechnologies/open-project-1/pull/99/files

    Also sorry for moving the character public variables to a ScriptableObject, it was out of the scope of this task, but I wanted to show how we could pass this through our states.

    Thanks for this initative. Even if this PR doesn't get to be reviewed or considered I'm learning from all of you
     
    MUGIK and cirocontinisio like this.
  48. tmcdonald

    tmcdonald

    Joined:
    Mar 20, 2016
    Posts:
    160
    I'm all for using Bolt as the FSM solution. It would make it easier for designers and non-programmers to contribute. @cirocontinisio any chance you can weigh in on the Inventory System thread? Last post was ~16 days ago, us asking for feedback. It also looks like the Inventory System ticket is in progress.
     
    cirocontinisio likes this.
  49. shuttle127

    shuttle127

    Joined:
    Oct 1, 2020
    Posts:
    183
    Check out the UI Wireframing thread, we've started talking about the inventory UI, maybe we can start coalescing the ideas?
     
  50. tmcdonald

    tmcdonald

    Joined:
    Mar 20, 2016
    Posts:
    160
    If that's the case then the other Inventory System thread should be deleted. As it stands, there were people working on it and awaiting some official feedback (per the contribution guidelines.)