Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Calling fsm.StateCanExit in StateBase.OnEnter does not allow the state to exit #50

Open
japsuu opened this issue Jun 7, 2024 · 0 comments

Comments

@japsuu
Copy link

japsuu commented Jun 7, 2024

When a state calls fsm.StateCanExit while in its OnEnter method, the call seems to be ignored. The state will never exit. However, if the call is moved inside the OnLogic method, everything works as expected.

Not quite sure if this is intended behavior or not, thus labelling this as an issue for now.

If this indeed is intended behavior, I'd recommend adding a warning to the README and to fsm.StateCanExit XML docs about this.

Example script that showcases the behavior:

using UnityEngine;
using UnityHFSM;

namespace UnityHFSMTest
{
    public class TestState : StateBase
    {
        public TestState() : base(needsExitTime:true) { }


        public override void OnEnter()
        {
            Debug.Log("TestState.OnEnter");
            
            // Calling "fsm.StateCanExit" in OnEnter does not allow the state to exit.
            fsm.StateCanExit();
            Debug.Log("TestState.OnEnter: StateCanExit called");
        }


        public override void OnLogic()
        {
            Debug.Log("TestState.OnLogic");
        }
    }
    
    /// <summary>
    /// This example demonstrates how the calling "StateCanExit" in OnEnter does not allow the state to exit.
    /// </summary>
    public class UnityHFSMStateCanExitTest : MonoBehaviour
    {
        private StateMachine _rootFsm;


        private void Awake()
        {
            _rootFsm = new StateMachine();
            
            // ----- States -----
            _rootFsm.AddState("StateA",
                onEnter: _ =>
                {
                    print("StateA.OnEnter");
                },
                onLogic: state =>
                {
                    if (state.timer.Elapsed > 1)
                        state.fsm.StateCanExit();
                },
                needsExitTime: true
            );
            
            _rootFsm.AddState("TestState", new TestState());
            
            // ----- Transitions -----
            // Alternate between "state A" and "TestState".
            _rootFsm.AddTransition(new Transition("StateA", "TestState"));
            _rootFsm.AddTransition(new Transition("TestState", "StateA"));
        }
        
        private void Start() => _rootFsm.Init();
        private void Update() => _rootFsm.OnLogic();
    }
}

Expected output:

The "TestState.OnLogic" debug line would NOT get printed.

Actual output:

The exit call is ignored.
image

Temporary fix:

If we move the fsm.StateCanExit() call to the OnLogic method, the state is exited as expected:
image

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant