Inspiaaa / UnityHFSM

A simple yet powerful class-based hierarchical finite state machine for Unity
MIT License
1.13k stars 125 forks source link

some new features #20

Closed Chocolaic closed 6 months ago

Chocolaic commented 1 year ago

Hello, I'm trying a way to handle complex logic in time sequence

An example shows that the player enters the aiming mode after holding down the right mouse button for one second. use 'yield return true;' to transition to another state and false to restart transition.

public PlayerAimState(StateMachine fsm)
{
    fsm.AddTransition(new TransitionAwait("Move", "Aim", ToggleAimOn));
}

IEnumerator ToggleAimOn(TransitionAwait t)
{
    yield return t.WaitForSeconds(0.2f);
    float startTime = Time.timeSinceLevelLoad;
    while (Time.timeSinceLevelLoad - startTime < 1f)
    {
        if (Input.GetKey(KeyCode.Mouse1)) yield return null;
        else yield return false;
    }
    yield return true;
}

However, it not a coroutine in unity thus 'yield return new WaitForSeconds()' may not work. This requires manual implementation of the method in the coroutine. XD (I didn't find a method like OnExit in Transition to stop coroutine properly or ignored by me)

rafaeldolfe commented 1 year ago

Feels a bit like this is more complexity than needed imo! Coroutines are a mess

Inspiaaa commented 6 months ago

Hi @Chocolaic, Thanks for your PR! Having coroutine-based transitions is very interesting and a feature I hadn't considered before.

One of the main architectural choices of transitions in UnityHFSM is that they do not have any side-effects, i.e. they do not "do" anything, but only tell the state machine when a state change is allowed to happen. "Doing" things and elegantly writing the code for sequential behaviour is one of the main advantages of using coroutines. Timing without performing actions is already supported by UnityHFSM. For instance, you could implement your example using two transitions: one transition for when the key is pressed, and one for when the delay elapses (using a TransitionAfter).

As UnityHFSM can essentially already do what you are asking for and using coroutines makes the code more complex, I will not be merging this pull request. I do, however, appreciate the effort.