Announcement

Collapse
No announcement yet.

GC FSM - Event-driven, hierarchical finite state machines in blueprint

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    I see. What is happening here is that the when an event is triggered it is queued in all FSMs that are currently available and are in the target policy. The problem is that when the main FSM is in the Traveling state, the Combat sub-FSM has not yet been created, so it can't get the event. In fact you have:
    Code:
    LogGCFSM (VeryVerbose) FSM Adventure (in state Traveling, class AdventureState_Traveling_C): event ToCombat queued (0 matching events discarded from queue)
    LogGCFSM (VeryVerbose) FSM Adventure (in state Traveling, class AdventureState_Traveling_C): event NPCTurn queued (0 matching events discarded from queue)
    When the Combat sub-FSM gets created, it's too late and it won't get the event.

    (Compare with the different case, when you later you trigger the Stop event. In that case you see
    Code:
    LogGCFSM (VeryVerbose) FSM Adventure (in state Combat, submachine Combat): event Stop queued (0 matching events discarded from queue)
    LogGCFSM (VeryVerbose) FSM Adventure/Combat/Combat (in state Player's Turn, class AdventureState_Combat_C): event Stop queued (0 matching events discarded from queue)
    and the Stop event is thus properly queued in the Combat sub-FSM, although it won't handle it.)

    Although a bit surprising, the behaviour now makes sense to me. I can't classify this as a bug, although I agree that your use-case is legit. I'm not sure what would be the best course of action to make it work, though. I can't just queue all parent-FSM events to the sub-FSM when it's being created, since the original target policy may forbid it and that information is not longer available.

    To solve your issue, you can either:
    1. wait for a tick before triggering the second event (ugly, but gives the sub-FSM the time to appear and get the event)
    2. use a bool to select the first state to enter in the Combat FSM. Although maybe less elegant, this approach as the advantage that you never enter the "Player's Turn" state when the NPC's turn is expected to be the first, so in the end it might actually be more correct (for some definition of "correct").
    Gamecentric

    Comment


      Edit: actually the "To Combat" event is superfluous. Just use the NPCTurn and and PlayerTurn event right in the Traveling state.
      Last edited by gamecentric; 06-19-2019, 12:43 PM.
      Gamecentric

      Comment


        Just an idea for save/reload: Some kind of functionality that makes it possible to go directly to a state only when the FSM is launched might work? So in order to use it again, the FSM must be stopped and restarted. That might be enough of a deterrent to prevent bypassing the graph structure willy-nilly...

        Comment


          Edit: actually the "To Combat" event is superfluous. Just use the NPCTurn and and PlayerTurn event right in the Traveling state.
          It was about knowledge separation (I assume that a lot more states will be added into both adventure and combat state machines so I've tried to minimize dependencies). I think not using submachine at all is better than add-boolean fix.

          this approach as the advantage that you never enter the "Player's Turn" state when the NPC's turn is expected to be the first, so in the end it might actually be more correct (for some definition of "correct").
          I've just added initial "Idle" state to avoid possible issues in future.

          At the end I think I will try delay fix or just leave it as is (simple flat SM) for now.
          Thanks a lot for the help!

          Comment


            Originally posted by DsyD View Post
            Just an idea for save/reload: Some kind of functionality that makes it possible to go directly to a state only when the FSM is launched might work? So in order to use it again, the FSM must be stopped and restarted. That might be enough of a deterrent to prevent bypassing the graph structure willy-nilly...
            My two cents If your SM has a chain of states each of which changes game state somehow it can be incorrect to just skip to the last one when game is loaded (assuming the game state is complex). Or you will need to carefully duplicate logic in each state somehow (thinking about which state game is allowed to be saved in etc.). I would just trigger events in the same way both during the game and when game is loaded to ensure game state consistency.

            Comment


              Well, if your states are modifying game properties, it's easier and more efficient to just save and restore those properties directly, isn't it?

              Re-triggering states might work in some narrow cases, but it's not a general solution, since the path to a state is not generally unique. You cannot observe the machine's current state and infer how it got there, except in very limited cases (e.g., each state has one parent and the FSM is acyclic). And there are plenty of situations where re-triggering each parent state produces incorrect results, too. Plus, if your states are doing performance-hungry things on entry/exit, like loading/unloading sublevels, it's really not a good idea to force the game to do an entire sequence of those tasks if it only needs the last one.

              Comment


                Agreed, I think I am just using plugin for different kind of stuff.

                Comment


                  Will this plugin support serialization at some point? I am trying to write it into the plugin myself but the code is not really serialization friendly right now. The approach I'm trying right now is to make everything a UPROP and non-transient for the time being and then I have to recreate all the state and FSM objects on load and then somehow invoke the correct entry points to recreate the BP stack.
                  Last edited by Cobryis; 07-29-2019, 10:59 AM.

                  Comment


                    Okay so I ended up writing a custom serialization approach where I take advantage of the replication features (activeNodeGuid) to "replicate" the state stack on deserialization.

                    Comment


                      Sounds interesting, mind describing it a little?

                      I still think the plugin could really benefit from a built-in way of restoring states from savegames. Hopefully the author is looking into it.

                      Comment


                        Originally posted by Cobryis View Post
                        Okay so I ended up writing a custom serialization approach where I take advantage of the replication features (activeNodeGuid) to "replicate" the state stack on deserialization.

                        I'm also interested...

                        Comment


                          Originally posted by DsyD View Post
                          Sounds interesting, mind describing it a little?

                          I still think the plugin could really benefit from a built-in way of restoring states from savegames. Hopefully the author is looking into it.
                          Yes, I confirm that I’m looking into that. The idea of exploiting the network replication features, which include the activeNodeGuid, is precisely what I thinking about.
                          Gamecentric

                          Comment

                          Working...
                          X