using Cysharp.Threading.Tasks; using System; using System.Collections.Generic; using UnityEngine; public interface IAsyncState { UniTask Enter(T context); UniTask Execute(T context); UniTask Exit(T context); } public class AsyncStateMachine { private IAsyncState currentState; private Dictionary, List> transitions = new Dictionary, List>(); private List globalTransitions = new List(); public async UniTask ChangeState(IAsyncState newState, T context) { if (newState == currentState) { return; } if (currentState != null) { await currentState.Exit(context); } //Debug.Log($"{context} -> {currentState} -> {newState}"); currentState = newState; if (currentState != null) { await currentState.Enter(context); } } public async UniTask Update(T context) { foreach (var transition in globalTransitions) { if (transition.Condition()) { await ChangeState(transition.TargetState, context); return; } } if (currentState != null && transitions.ContainsKey(currentState)) { foreach (var transition in transitions[currentState]) { if (transition.Condition()) { await ChangeState(transition.TargetState, context); return; } } } if (currentState != null) { await currentState.Execute(context); } } public void AddTransition(IAsyncState fromState, IAsyncState toState, Func condition) { if (!transitions.ContainsKey(fromState)) { transitions[fromState] = new List(); } transitions[fromState].Add(new Transition(toState, condition)); } public void AddGlobalTransition(IAsyncState toState, Func condition) { globalTransitions.Add(new Transition(toState, condition)); } /// /// 상태머신 내부 데이터를 초기화합니다. /// public void Clear() { currentState = null; transitions.Clear(); globalTransitions.Clear(); } private class Transition { public IAsyncState TargetState { get; } public Func Condition { get; } public Transition(IAsyncState targetState, Func condition) { TargetState = targetState; Condition = condition; } } }