Skip to content

Commit

Permalink
Merge pull request #37 from bazyleu/bugfix/go-back-fix
Browse files Browse the repository at this point in the history
Bugfix/go back fix
  • Loading branch information
bazyleu authored Sep 2, 2024
2 parents c6142e0 + 0da88d3 commit 6f64e42
Show file tree
Hide file tree
Showing 22 changed files with 249 additions and 20 deletions.
36 changes: 22 additions & 14 deletions Assets/UniState/Runtime/Core/StateMachine/StateMachine.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using UniState;

namespace UniState
{
Expand Down Expand Up @@ -32,15 +31,15 @@ private async UniTask ExecuteInternal(StateTransitionInfo initialTransition, Can
var activeStateMetadata = new StateWithMetadata();
var nextStateMetadata = new StateWithMetadata();

activeStateMetadata.SetData(initialTransition.Creator.Create(), initialTransition.StateBehaviourData);
activeStateMetadata.BuildState(initialTransition, initialTransition.StateBehaviourData);

try
{
await InitializeSafe(activeStateMetadata.State, token);

var transitionInfo = await ExecuteSafe(activeStateMetadata.State, token);

ProcessTransitionInfo(transitionInfo, ref nextStateMetadata);
ProcessTransitionInfo(transitionInfo, activeStateMetadata.TransitionInfo, nextStateMetadata);

while (!nextStateMetadata.IsEmpty && !token.IsCancellationRequested)
{
Expand All @@ -55,11 +54,11 @@ private async UniTask ExecuteInternal(StateTransitionInfo initialTransition, Can
await InitializeSafe(nextStateMetadata.State, token);
}

activeStateMetadata.SetData(nextStateMetadata);
activeStateMetadata.CopyData(nextStateMetadata);

transitionInfo = await ExecuteSafe(activeStateMetadata.State, token);

ProcessTransitionInfo(transitionInfo, ref nextStateMetadata);
ProcessTransitionInfo(transitionInfo, activeStateMetadata.TransitionInfo, nextStateMetadata);
}

await ExitAndDisposeSafe(activeStateMetadata.State, token);
Expand Down Expand Up @@ -90,20 +89,29 @@ private void OnError(Exception exception, StateMachineErrorType phase)
//Call Handler
}

private void ProcessTransitionInfo(StateTransitionInfo transitionInfo, ref StateWithMetadata stateWithMetadata)
private void ProcessTransitionInfo(StateTransitionInfo nextTransition,
StateTransitionInfo previousTransition,
StateWithMetadata stateWithMetadata)
{
stateWithMetadata.Clear();

if (transitionInfo.Transition != TransitionType.Exit)
if (nextTransition.Transition == TransitionType.Exit)
{
var item = transitionInfo.Transition == TransitionType.State
? _history.Push(transitionInfo)
: GetInfoFromHistory();
return;
}

if (item != null)
{
stateWithMetadata.SetData(item.Creator.Create(), item.StateBehaviourData);
}
var transitionToState = nextTransition.Transition == TransitionType.State;

var item = transitionToState ? nextTransition : GetInfoFromHistory();

if (transitionToState && previousTransition != null)
{
_history.Push(previousTransition);
}

if (item != null)
{
stateWithMetadata.BuildState(item, item.StateBehaviourData);
}
}

Expand Down
14 changes: 10 additions & 4 deletions Assets/UniState/Runtime/Core/StateMachine/StateWithMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,42 @@ namespace UniState
{
public class StateWithMetadata : IDisposable
{
public StateTransitionInfo TransitionInfo { get; private set; }
public IExecutableState State { get; private set; }
public StateBehaviourData BehaviourData { get; private set; }

private bool _disposed = false;
private bool _disposed;

public bool IsEmpty => State == null;

public void SetData(IExecutableState state, StateBehaviourData behaviourData)
public void BuildState(StateTransitionInfo transitionInfo, StateBehaviourData behaviourData)
{
State = state;
TransitionInfo = transitionInfo;
State = transitionInfo.Creator.Create();
BehaviourData = behaviourData;

_disposed = false;
}

public void SetData(StateWithMetadata data)
public void CopyData(StateWithMetadata data)
{
if (data != null)
{
TransitionInfo = data.TransitionInfo;
State = data.State;
BehaviourData = data.BehaviourData;
}
else
{
Clear();
}

_disposed = false;
}

public void Clear()
{
TransitionInfo = null;
State = null;
BehaviourData = null;
_disposed = false;
Expand Down
3 changes: 3 additions & 0 deletions Assets/UniStateTests/PlayMode/Common.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Assets/UniStateTests/PlayMode/Common/IStateLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace UniStateTests.PlayMode.Common
{
//TODO: Refactor to more complex logger
public interface IStateLogger
{
void LogLine(string line);
string GetFullLog();
}
}
3 changes: 3 additions & 0 deletions Assets/UniStateTests/PlayMode/Common/IStateLogger.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions Assets/UniStateTests/PlayMode/Common/StateLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Text;

namespace UniStateTests.PlayMode.Common
{
public class StateLogger : IStateLogger
{
private readonly StringBuilder _stringBuilder = new(500);
public void LogLine(string line) => _stringBuilder.AppendLine(line);
public string GetFullLog() => _stringBuilder.ToString();
}
}
3 changes: 3 additions & 0 deletions Assets/UniStateTests/PlayMode/Common/StateLogger.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBack.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBack/GoBackTestFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace UniStateTests.PlayMode.GoBack
{
public class GoBackTestFlags
{
public bool ExecutedState1 = false;
public bool ExecutedState2 = false;
}
}
3 changes: 3 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBack/GoBackTestFlags.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBack/StateGoBack1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Threading;
using Cysharp.Threading.Tasks;
using UniState;
using UniStateTests.PlayMode.Common;

namespace UniStateTests.PlayMode.GoBack
{
public class StateGoBack1 : StateBase
{
private readonly IStateLogger _stateLogger;
private readonly GoBackTestFlags _flags;

public StateGoBack1(IStateLogger stateLogger, GoBackTestFlags flags)
{
_stateLogger = stateLogger;
_flags = flags;
}

public override async UniTask<StateTransitionInfo> Execute(CancellationToken token)
{
_stateLogger.LogLine("StateGoBack1 - Execute");

await UniTask.Yield();

if (_flags.ExecutedState1)
{
return Transition.GoBack();
}

_flags.ExecutedState1 = true;

return Transition.GoTo<StateGoBack2>();
}
}
}
3 changes: 3 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBack/StateGoBack1.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBack/StateGoBack2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Threading;
using Cysharp.Threading.Tasks;
using UniState;
using UniStateTests.PlayMode.Common;

namespace UniStateTests.PlayMode.GoBack
{
public class StateGoBack2 : StateBase
{
private readonly IStateLogger _stateLogger;
private readonly GoBackTestFlags _flags;

public StateGoBack2(IStateLogger stateLogger, GoBackTestFlags flags)
{
_stateLogger = stateLogger;
_flags = flags;
}

public override async UniTask<StateTransitionInfo> Execute(CancellationToken token)
{
_stateLogger.LogLine("StateGoBack2 - Execute");

await UniTask.Yield();

if (_flags.ExecutedState2)
{
return Transition.GoBack();
}

_flags.ExecutedState2 = true;

return Transition.GoTo<StateGoBack3>();
}
}
}
3 changes: 3 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBack/StateGoBack2.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBack/StateGoBack3.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Threading;
using Cysharp.Threading.Tasks;
using UniState;
using UniStateTests.PlayMode.Common;

namespace UniStateTests.PlayMode.GoBack
{
public class StateGoBack3 : StateBase
{
private readonly IStateLogger _stateLogger;
private readonly GoBackTestFlags _flags;

public StateGoBack3(IStateLogger stateLogger, GoBackTestFlags flags)
{
_stateLogger = stateLogger;
_flags = flags;
}

public override async UniTask<StateTransitionInfo> Execute(CancellationToken token)
{
_stateLogger.LogLine("StateGoBack3 - Execute");

await UniTask.Yield();

return Transition.GoBack();
}
}
}
3 changes: 3 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBack/StateGoBack3.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 62 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBackTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Collections;
using System.Threading;
using Cysharp.Threading.Tasks;
using NUnit.Framework;
using UniState;
using UniStateTests.PlayMode.Common;
using UniStateTests.PlayMode.GoBack;
using UnityEngine.TestTools;
using Zenject;

namespace UniStateTests.PlayMode
{
[TestFixture]
public class GoBackTests
{
[UnityTest]
public IEnumerator RunChaneOfState_GoBackFromTheChain_ExitFromStateMachineWithCorrectOrderOfStates() => UniTask.ToCoroutine(async () =>
{
//TODO: Refactor this test

const string expectedLog = @"Create and execute State Machine
StateGoBack1 - Execute
StateGoBack2 - Execute
StateGoBack3 - Execute
StateGoBack2 - Execute
StateGoBack1 - Execute
State Machine is finished
";

var container = new DiContainer(StaticContext.Container);

container.BindInterfacesTo<StateLogger>().AsSingle();
container.Bind<GoBackTestFlags>().ToSelf().AsSingle();

container.Bind<StateMachine>().ToSelf().AsTransient();
container.Bind<StateGoBack1>().ToSelf().AsTransient();
container.Bind<StateGoBack2>().ToSelf().AsTransient();
container.Bind<StateGoBack3>().ToSelf().AsTransient();

CancellationTokenSource cts = new CancellationTokenSource();

//TODO: Move to base class
using var slim = cts.CancelAfterSlim(TimeSpan.FromSeconds(5), DelayType.UnscaledDeltaTime);

var logger = container.Resolve<IStateLogger>();

logger.LogLine("Create and execute State Machine");
var stateMachine = StateMachineHelper.CreateStateMachine<StateMachine>(container.ToTypeResolver());
await stateMachine.Execute<StateGoBack1>(cts.Token);

logger.LogLine("State Machine is finished");

var actualLog = logger.GetFullLog();

//TODO: Move to base class
StaticContext.Clear();

Assert.AreEqual(actualLog, expectedLog);
});
}
}
3 changes: 3 additions & 0 deletions Assets/UniStateTests/PlayMode/GoBackTests.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace UniStateTests.PlayMode
{
[TestFixture]
public class VContainerIntegrationTest
public class VContainerIntegrationTests
{
private GameObject _containerHolder;
private IObjectResolver _objectResolver;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace UniStateTests.PlayMode
{
[TestFixture]
public class ZenjectIntegrationTest
public class ZenjectIntegrationTests
{
[UnityTest]
public IEnumerator SimpleRun() => UniTask.ToCoroutine(async () =>
Expand Down

0 comments on commit 6f64e42

Please sign in to comment.