I think this is a bug but please check my logic and the patch I used to fix it.
I have an FSM for handling UI popups. It has states like “Normal HUD”, “Pause Menu”, “Respawning”, etc. I wanted to handle controller disconnect events but since these can come up any time I decided to make another state machine to make it easier to return to the normal UI state after the disconnect event is handled. So I have a second FSM which checks disconnect events. When a controller is disconnected, it pauses the first state machine and takes control. Once the situation is resolved (either by reconnecting or dropping the player) it resumes the Main FSM.
The Main FSM gets paused on the first disconnect event, then resumes normally after it’s handled. On the second disconnect however, it gets stopped and obviously loses its state. Subsequent disconnects always make it stop instead of just pausing.
Here’s the faulty code path I debugged:
MonoManager.Update() calls onUpdate();
Disconnect FSM handles update and calls PauseBehavior() on Main FSM
Graph.Pause() deregisters from the onUpdate() action (Graph.cs line 623)
FSM.OnGraphPaused() sets currentState to null
FSM.OnGraphUpdate() still gets called for the Main FSM even though it’s been paused! This makes it hit the first check (currentState == null) and forces it to stop
The problem seems to be with the MonoManager’s onUpdate Action. OnGraphUpdate() shouldn’t be called on the paused FSM but it looks like it’s being called one more time because the action has already fired when it was still subscribed. My patch was to add a simple if (isPaused) return; check at the top of FSM.OnGraphUpdate().
Just to confirm, how are you Pausing the FSM? Are you doing it from within the FSM itself and if yes, do you use the included “GraphOwnerControl” action, or a direct call to PauseGraph()?
If you check the “GraphOwnerControl” action code, you will notice that for that reason, Pausing, or Stopping the graph from within it’s own update call, is done with a co-routine that simply yields one frame. This way, Pausing or Stopping the graph is called after the Update call is completely done.
What you do though to solve it seems quite logical as well 🙂
I will take a look at if your fix creates any other problems and if not I will make that change as well, otherwise I will try find an alternate solution, since I understand that a co-routine solution like it is done in the included action, is certainly not ideal.
Thanks again for taking the time to explain the situation thoroughly!