-
Notifications
You must be signed in to change notification settings - Fork 4
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
Does Execute function mandatory to return IStateTransitionFacade Transition #75
Comments
Thanks for reaching out and sharing your questions about using UniState as a replacement for your existing state controller. Below are some suggestions and clarifications for each of the points you raised:
UniTaskCompletionSource<StateTransitionInfo> _completionSource = new UniTaskCompletionSource<StateTransitionInfo>();
public override UniTask<StateTransitionInfo> Execute(CancellationToken token)
{
await _view.Show(token);
// Add subscription to OnExitButtonClicked and OnNextButtonClicked
return await _completionSource.Task;
}
private void OnExitButtonClicked() => _completionSource.TrySetResult(Transition.GoToExit());
private void OnNextButtonClicked() => _completionSource.TrySetResult(Transition.GoTo<NextState>());
public class BarState : StateBase
{
public override UniTask<StateTransitionInfo> Execute(CancellationToken token)
{
//..
return Transition.GoTo<FooState>();
}
}
public class FooState : StateBase
{
private const string AddressableFooKey = "FooViewKey";
private readonly IAdressableManager _addressableManager;
private IView _view;
public FooState(IAdressableManager addressableManager)
{
_addressableManager = addressableManager;
}
public override async UniTask Initialize(CancellationToken token)
{
_view = await _addressableManager.Prewarn(AddressableFooKey, token);
Disposables.Add(()=> _addressableManager.Cleanup(_view));
// Disposables.Add(_view); // another option if IView is disposable
}
public override UniTask<StateTransitionInfo> Execute(CancellationToken token)
{
_view.Show();
// ...
}
} (b) If prewarming takes time and you need to ensure a seamless transition between states, you can use approach (a) in combination with the [InitializeOnStateTransition] attribute (link). In this scenario, FooState is initialized before BarState’s Exit() callback is triggered. That means you can hide UI/Prefabs/GameObjects in BarState.Exit(), and right after that, FooState will already be prewarmed. (c) If your Addressable assets are intended for use across multiple states, and it’s more efficient to prewarm them once, the optimal solution is to employ an internal state machine. Here’s how it works: the root state handles the prewarm step and then invokes the internal state machine that processes all states using those assets. When the internal state machine finishes, the root state also completes, and it can then clean up the Addressable assets. I recommend following the principle that whoever allocates the resources should also release them. This is why states provide a Disposables property—to make the cleanup process simpler. public class BazState : StateBase
{
private const string AddressableBazKey = "SomeKey";
private readonly IAdressableManager _addressableManager;
public BazStateBazState(IAdressableManager addressableManager)
{
_addressableManager = addressableManager;
}
public override async UniTask Initialize(CancellationToken token)
{
var prewarmedAsset = await _addressableManager.Prewarn(AddressableBazKey, token);
Disposables.Add(prewarmedAsset);
}
public override UniTask<StateTransitionInfo> Execute(CancellationToken token)
{
var stateMachine = StateMachineFactory.Create<StateMachine>();
await stateMachine.Execute<NextState>(token);
return Transition.GoToExit();
}
} |
For point 2. instead of calling Transition.GoTo() or Transition.GoToExit() im using messagepipe (https://github.com/Cysharp/MessagePipe) messaging library which can be integrated into vcontainer (https://vcontainer.hadashikick.jp/integrations/messagepipe) directly. Now at any point ill be publishing msg event for screen transition so that i dont need Transition.GoTo() at all. |
When you call The state can then wait for an event, look it up in your dictionary, and return the corresponding transition. If you want to build your application around this approach, you can move this logic into your base state (inheriting from public abstract class MessageStateBase : StateBase
{
private UniTaskCompletionSource<StateTransitionInfo> _completionSource = new();
private Dictionary<string, StateTransitionInfo> _transitionDictionary = new();
// Write state specific logic here for each separate state
protected abstract UniTask StateLogic(CancellationToken token);
public override UniTask Initialize(CancellationToken token)
{
// Note! Just an example how dictionary can be filled.
// In real project it is better to share data between states but not fill it each time
_transitionDictionary = new Dictionary<string, StateTransitionInfo>()
{
{ "message_foo", Transition.GoTo<FooState>() },
{ "message_bar", Transition.GoTo<BarState>() },
{ "message_exit", Transition.GoToExit() }
};
return base.Initialize(token);
}
public async override UniTask<StateTransitionInfo> Execute(CancellationToken token)
{
await StateLogic(token);
// Add subscription to OnMessageReceived
return await _completionSource.Task;
}
// Callback on receiving message from any message framework
private void OnMessageReceived(string message) =>
_completionSource.TrySetResult(_transitionDictionary[message]);
} Additionally, if you want to fill a collection of transitions outside the state, you can skip using the |
I've tried to implement the unistate, to replace my exisitng state controller. So the execute funciton is nearly forcing to implement the transition to either goback, goexit or goto, making state fully depeneded on _view.WaitForClick to get some action done.
The text was updated successfully, but these errors were encountered: