Единство, сопрограмма не начнется - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть простой конечный автомат, написанный мной. У меня есть переходы и состояния. Вот как StateTransition выглядит изнутри:

////////////////////////////////////////////////////////////////////////////

public delegate void ActionCaller(IEnumerator action); // Take note of this delegate

private readonly ActionCaller caller;
private readonly IEnumerator action; // This is my State action

////////////////////////////////////////////////////////////////////////////

public void Execute()
{
    caller.Invoke(action); // Here I call my `action` through `caller`
}

////////////////////////////////////////////////////////////////////////////

А вот мой MonoBehaviour код, который создает такие состояния:

////////////////////////////////////////////////////////////////////////////
private void Start()
{
    // Here I initialize my states and pass a method which will be called in `StateTransition.Execute` to execute passed method and `CallAction` to start Coroutine in my `MonoBehaviour` class
    States = new Dictionary<State, StateTransition>()
    {
        { State.Idling, new StateTransition(State.Idling, DoNothing(), CallAction) },
        { State.WanderingAround, new StateTransition(State.WanderingAround, WanderAround(), CallAction) }
    };

    StateMachine = new FiniteStateMachine(new List<Transition>()
    {
        new Transition(States[State.Idling], States[State.WanderingAround], Input.Wandering),
        new Transition(States[State.WanderingAround], States[State.Idling], Input.Nothing)
    });

    StateMachine.NextState(Input.Wandering);
}

////////////////////////////////////////////////////////////////////////////

private void CallAction(IEnumerator routine)
{
    if (currentActionCoroutine != null)
    {
        StopCoroutine(currentActionCoroutine);
    }

    currentActionCoroutine = StartCoroutine(routine); // This code right here starts my passed `routine`
}

////////////////////////////////////////////////////////////////////////////

И вот проблема, когда я звоню своему первому NextState он вызывает WanderAround, который затем вызывает DoNothing, и после этого он должен снова нормально вызывать WanderAround, но проблема в том, что он просто не вызывает его. Там не происходит ни одной ошибки. Сопрограмма просто не хочет начинать. Но если я позвоню, скажем, DoNothing StartCoroutine(WanderAround()) - это работает! Но не через мои странные StateTransition/Action/Execute отношения.

////////////////////////////////////////////////////////////////////////////

private IEnumerator DoNothing()
{
    Debug.Log("DoNothing:Enter");

    do
    {
        yield return new WaitForSeconds(2.5f);
    } while (CurrentState == State.Dead);

    Debug.Log("DoNothing:Exit");

    StateMachine.NextState(Input.Wandering); // Calls `StateTransition.Execute`
}

private IEnumerator WanderAround()
{
    Debug.Log("WanderAround:Enter");

    Vector2 randomPosition = new Vector2(Random.Range(-5f, 5f), Random.Range(-5f, 5f));

    movementController.RotateAndMoveTo(randomPosition, Genes[Gene.MovementSpeed], Genes[Gene.TurnSpeed]);

    while (movementController.IsMoving || movementController.IsRotating)
    {
        yield return new WaitForSeconds(Time.deltaTime);
    }

    Debug.Log("WanderAround:Exit");

    StateMachine.NextState(Input.Nothing); // Calls `StateTransition.Execute`
}

////////////////////////////////////////////////////////////////////////////

Что мне делать? Спасибо!

PS Очень жаль, если это не имеет для вас никакого смысла, я просто не знаю, как объяснить это более четко.

1 Ответ

1 голос
/ 03 апреля 2020

Хорошо, я понял это.

Я изменил свой тип action с IEnumerator на System.Func<IEnumerator> и ... он работал!

Теперь мой код выглядит следующим образом :

////////////////////////////////////////////////////////////////////////////

public delegate void ActionCaller(IEnumerator action); // Take note of this delegate

private readonly ActionCaller caller;
private readonly System.Func<IEnumerator> action; // This is my State action

////////////////////////////////////////////////////////////////////////////

public void Execute()
{
    caller(action()); // Here I call my `action` through `caller`
}

////////////////////////////////////////////////////////////////////////////

И в конструкторе StateTransition я передаю SomeFunc вместо SomeFunc().

Приветствия!

...