增加A2WToolBox工具集,增加Launch场景核LaunchPanel

This commit is contained in:
Wurui
2025-11-08 11:06:48 +08:00
parent 3e92e5684a
commit 3b43829e85
726 changed files with 87807 additions and 215 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9c8afd02806bc1d4cab6182962b1ccc4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
{
"name": "MonsterLove.StateMachine.Tests.EditorTests",
"rootNamespace": "",
"references": [
"MonsterLove.StateMachine.Runtime",
"MonsterLove.StateMachine.Tests.Runtime",
"UnityEngine.TestRunner",
"UnityEditor.TestRunner"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7a05261385aac3941b3b93eaf9a30bed
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,193 @@
using System;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using UnityEditor;
using System.Collections;
using Object = UnityEngine.Object;
[TestFixture]
[Category("State Machine Tests")]
internal class TestBasicTransitions
{
public enum States
{
One,
Two,
Three,
}
private GameObject go;
private ClassWithBasicStates behaviour;
private StateMachineRunner engine;
private StateMachine<States> fsm;
[SetUp]
public void Init()
{
go = new GameObject("stateTest");
behaviour = go.AddComponent<ClassWithBasicStates>();
engine = go.AddComponent<StateMachineRunner>();
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void NoTransitions()
{
fsm = engine.Initialize<States>(behaviour);
//Goes to start state by default;
Assert.AreEqual(0, behaviour.oneStats.enterCount);
Assert.AreEqual(0, behaviour.oneStats.updateCount);
Assert.AreEqual(0, behaviour.oneStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.oneStats.exitCount);
Assert.AreEqual(0, behaviour.oneStats.finallyCount);
Assert.AreEqual(0, behaviour.twoStats.enterCount);
Assert.AreEqual(0, behaviour.twoStats.updateCount);
Assert.AreEqual(0, behaviour.twoStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.twoStats.exitCount);
Assert.AreEqual(0, behaviour.twoStats.finallyCount);
Assert.AreEqual(0, behaviour.threeStats.enterCount);
Assert.AreEqual(0, behaviour.threeStats.updateCount);
Assert.AreEqual(0, behaviour.threeStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.threeStats.exitCount);
Assert.AreEqual(0, behaviour.threeStats.finallyCount);
}
[Test]
public void InitialTransition()
{
fsm = engine.Initialize<States>(behaviour, States.One);
fsm.ChangeState(States.Two);
Assert.AreEqual(1, behaviour.oneStats.enterCount);
Assert.AreEqual(0, behaviour.oneStats.updateCount);
Assert.AreEqual(0, behaviour.oneStats.lateUpdateCount);
Assert.AreEqual(1, behaviour.oneStats.exitCount);
Assert.AreEqual(1, behaviour.oneStats.finallyCount);
Assert.AreEqual(1, behaviour.twoStats.enterCount);
Assert.AreEqual(0, behaviour.twoStats.updateCount);
Assert.AreEqual(0, behaviour.twoStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.twoStats.exitCount);
Assert.AreEqual(0, behaviour.twoStats.finallyCount);
Assert.AreEqual(0, behaviour.threeStats.enterCount);
Assert.AreEqual(0, behaviour.threeStats.updateCount);
Assert.AreEqual(0, behaviour.threeStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.threeStats.exitCount);
Assert.AreEqual(0, behaviour.threeStats.finallyCount);
}
[Test]
public void IgnoreMultipleTransitions()
{
fsm = engine.Initialize<States>(behaviour, States.One);
fsm.ChangeState(States.Two);
fsm.ChangeState(States.Two);
Assert.AreEqual(1, behaviour.oneStats.enterCount);
Assert.AreEqual(0, behaviour.oneStats.updateCount);
Assert.AreEqual(0, behaviour.oneStats.lateUpdateCount);
Assert.AreEqual(1, behaviour.oneStats.exitCount);
Assert.AreEqual(1, behaviour.oneStats.finallyCount);
Assert.AreEqual(1, behaviour.twoStats.enterCount);
Assert.AreEqual(0, behaviour.twoStats.updateCount);
Assert.AreEqual(0, behaviour.twoStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.twoStats.exitCount);
Assert.AreEqual(0, behaviour.twoStats.finallyCount);
Assert.AreEqual(0, behaviour.threeStats.enterCount);
Assert.AreEqual(0, behaviour.threeStats.updateCount);
Assert.AreEqual(0, behaviour.threeStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.threeStats.exitCount);
Assert.AreEqual(0, behaviour.threeStats.finallyCount);
fsm.reenter = true;
fsm.ChangeState(States.Three);
fsm.ChangeState(States.Three);
Assert.AreEqual(1, behaviour.twoStats.enterCount);
Assert.AreEqual(0, behaviour.twoStats.updateCount);
Assert.AreEqual(0, behaviour.twoStats.lateUpdateCount);
Assert.AreEqual(1, behaviour.twoStats.exitCount);
Assert.AreEqual(1, behaviour.twoStats.finallyCount);
Assert.AreEqual(2, behaviour.threeStats.enterCount);
Assert.AreEqual(0, behaviour.threeStats.updateCount);
Assert.AreEqual(0, behaviour.threeStats.lateUpdateCount);
Assert.AreEqual(1, behaviour.threeStats.exitCount);
Assert.AreEqual(1, behaviour.threeStats.finallyCount);
}
[Test]
public void SpecifiedDefault()
{
fsm = engine.Initialize<States>(behaviour, States.Two);
Assert.AreEqual(0, behaviour.oneStats.enterCount);
Assert.AreEqual(0, behaviour.oneStats.updateCount);
Assert.AreEqual(0, behaviour.oneStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.oneStats.exitCount);
Assert.AreEqual(0, behaviour.oneStats.finallyCount);
Assert.AreEqual(1, behaviour.twoStats.enterCount);
Assert.AreEqual(0, behaviour.twoStats.updateCount);
Assert.AreEqual(0, behaviour.twoStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.twoStats.exitCount);
Assert.AreEqual(0, behaviour.twoStats.finallyCount);
Assert.AreEqual(0, behaviour.threeStats.enterCount);
Assert.AreEqual(0, behaviour.threeStats.updateCount);
Assert.AreEqual(0, behaviour.threeStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.threeStats.exitCount);
Assert.AreEqual(0, behaviour.threeStats.finallyCount);
}
[Test]
public void MultipleTransitions()
{
fsm = engine.Initialize<States>(behaviour, States.One);
fsm.ChangeState(States.One);
fsm.ChangeState(States.Two);
fsm.ChangeState(States.Three);
Assert.AreEqual(1, behaviour.oneStats.enterCount);
Assert.AreEqual(0, behaviour.oneStats.updateCount);
Assert.AreEqual(0, behaviour.oneStats.lateUpdateCount);
Assert.AreEqual(1, behaviour.oneStats.exitCount);
Assert.AreEqual(1, behaviour.oneStats.finallyCount);
Assert.AreEqual(1, behaviour.twoStats.enterCount);
Assert.AreEqual(0, behaviour.twoStats.updateCount);
Assert.AreEqual(0, behaviour.twoStats.lateUpdateCount);
Assert.AreEqual(1, behaviour.twoStats.exitCount);
Assert.AreEqual(1, behaviour.twoStats.finallyCount);
Assert.AreEqual(1, behaviour.threeStats.enterCount);
Assert.AreEqual(0, behaviour.threeStats.updateCount);
Assert.AreEqual(0, behaviour.threeStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.threeStats.exitCount);
Assert.AreEqual(0, behaviour.threeStats.finallyCount);
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 899062ccff9246a4c8873c29a4ac6bf4
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,108 @@
using System.Runtime.CompilerServices;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
/// This is an important test, enables subscription directly to driver objects
/// Eg. button.OnClick.AddListener(fsm.Driver.Foo.Invoke)
public class TestCachedDriver
{
public enum States
{
One,
Two,
Three,
Four,
}
public class Driver
{
public StateEvent Foo;
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States, Driver> fsm;
private Driver driver;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
fsm = new StateMachine<States, Driver>(behaviour);
driver = fsm.Driver;
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void TestCachedDriverEvents()
{
fsm.ChangeState(States.One);
driver.Foo.Invoke();
Assert.AreEqual(1, behaviour.oneFoo);
Assert.AreEqual(0, behaviour.twoFoo);
fsm.ChangeState(States.Two);
driver.Foo.Invoke();
Assert.AreEqual(1, behaviour.oneFoo);
Assert.AreEqual(1, behaviour.twoFoo);
}
private class StateClass : MonoBehaviour
{
public int oneEnter;
public int oneFoo;
public int oneExit;
public int twoEnter;
public int twoFoo;
public int twoExit;
void One_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_Foo()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Foo", Time.frameCount);
oneFoo++;
}
void One_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Exit", Time.frameCount);
oneExit++;
}
void Two_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Enter", Time.frameCount);
twoEnter++;
}
void Two_Foo()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Foo", Time.frameCount);
twoFoo++;
}
void Two_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Exit", Time.frameCount);
twoExit++;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 597262340b854411b6859c314743cbfe
timeCreated: 1568106780

View File

@@ -0,0 +1,179 @@
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
public class TestCustomDriver
{
public enum States
{
One,
Two,
Three,
Four,
}
public class Driver
{
public StateEvent Foo;
public StateEvent<int> Bar;
public StateEvent<int, int> Baz;
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States, Driver> fsm;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
fsm = new StateMachine<States, Driver>(behaviour);
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void TestDriverNotNull()
{
Assert.NotNull(fsm.Driver);
}
[Test]
public void TestCustomEvents()
{
fsm.ChangeState(States.One);
fsm.Driver.Foo.Invoke();
fsm.Driver.Bar.Invoke(5);
fsm.Driver.Baz.Invoke(6, 7);
Assert.AreEqual(1, behaviour.oneFoo);
Assert.AreEqual(1, behaviour.oneBar);
Assert.AreEqual(1, behaviour.oneBaz);
Assert.AreEqual(5, behaviour.oneBarValue);
Assert.AreEqual(6, behaviour.oneBazValueA);
Assert.AreEqual(7, behaviour.oneBazValueB);
Assert.AreEqual(0, behaviour.twoFoo);
Assert.AreEqual(0, behaviour.twoBar);
Assert.AreEqual(0, behaviour.twoBaz);
Assert.AreEqual(0, behaviour.twoBarValue);
Assert.AreEqual(0, behaviour.twoBazValueA);
Assert.AreEqual(0, behaviour.twoBazValueB);
fsm.ChangeState(States.Two);
fsm.Driver.Foo.Invoke();
fsm.Driver.Bar.Invoke(8);
fsm.Driver.Baz.Invoke(9, 10);
Assert.AreEqual(1, behaviour.oneFoo);
Assert.AreEqual(1, behaviour.oneBar);
Assert.AreEqual(1, behaviour.oneBaz);
Assert.AreEqual(5, behaviour.oneBarValue);
Assert.AreEqual(6, behaviour.oneBazValueA);
Assert.AreEqual(7, behaviour.oneBazValueB);
Assert.AreEqual(1, behaviour.twoFoo);
Assert.AreEqual(1, behaviour.twoBar);
Assert.AreEqual(1, behaviour.twoBaz);
Assert.AreEqual(8, behaviour.twoBarValue);
Assert.AreEqual(9, behaviour.twoBazValueA);
Assert.AreEqual(10, behaviour.twoBazValueB);
}
private class StateClass : MonoBehaviour
{
public int oneEnter;
public int oneFoo;
public int oneBar;
public int oneBaz;
public int oneExit;
public int oneBarValue;
public int oneBazValueA;
public int oneBazValueB;
public int twoEnter;
public int twoFoo;
public int twoBar;
public int twoBaz;
public int twoExit;
public int twoBarValue;
public int twoBazValueA;
public int twoBazValueB;
void One_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_Foo()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Foo", Time.frameCount);
oneFoo++;
}
void One_Bar(int value)
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Bar", Time.frameCount);
oneBar++;
oneBarValue = value;
}
void One_Baz(int valueA, int valueB)
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Baz", Time.frameCount);
oneBaz++;
oneBazValueA = valueA;
oneBazValueB = valueB;
}
void One_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Exit", Time.frameCount);
oneExit++;
}
void Two_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Enter", Time.frameCount);
twoEnter++;
}
void Two_Foo()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Foo", Time.frameCount);
twoFoo++;
}
void Two_Bar(int value)
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Bar", Time.frameCount);
twoBar++;
twoBarValue = value;
}
void Two_Baz(int valueA, int valueB)
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Baz", Time.frameCount);
twoBaz++;
twoBazValueA = valueA;
twoBazValueB = valueB;
}
void Two_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Exit", Time.frameCount);
twoExit++;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9ac0e8e3b6264af6ad5122d174f3e4b5
timeCreated: 1567780312

View File

@@ -0,0 +1,60 @@
using System;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using UnityEditor;
using System.Collections;
using Object = UnityEngine.Object;
[TestFixture]
[Category("State Machine Tests")]
internal class TestDerivedFromSuperClass
{
public enum States
{
One,
Two,
Three,
}
private GameObject go;
private ClassWithBasicStates behaviour;
private StateMachineRunner engine;
private StateMachine<States> fsm;
[SetUp]
public void Init()
{
go = new GameObject("stateTest");
behaviour = go.AddComponent<ClassDerivedFromSuperClass>();
engine = go.AddComponent<StateMachineRunner>();
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void InitialTransition()
{
fsm = engine.Initialize<States>(behaviour, States.One);
fsm.ChangeState(States.Two);
//Test for when we want to include superclass methods
Assert.AreEqual(1, behaviour.oneStats.enterCount);
Assert.AreEqual(0, behaviour.oneStats.updateCount);
Assert.AreEqual(0, behaviour.oneStats.lateUpdateCount);
Assert.AreEqual(1, behaviour.oneStats.exitCount);
Assert.AreEqual(1, behaviour.oneStats.finallyCount);
Assert.AreEqual(1, behaviour.twoStats.enterCount);
Assert.AreEqual(0, behaviour.twoStats.updateCount);
Assert.AreEqual(0, behaviour.twoStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.twoStats.exitCount);
Assert.AreEqual(0, behaviour.twoStats.finallyCount);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 61f4fd153167fd343a371f18957007dc
timeCreated: 1466595036
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,90 @@
using System;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using UnityEditor;
using System.Collections;
using Object = UnityEngine.Object;
[TestFixture]
[Category("State Machine Tests")]
internal class TestDisabledComponent
{
public enum States
{
One,
Two,
Three,
}
private GameObject go;
private ClassWithBasicStates behaviour;
private StateMachineRunner engine;
private StateMachine<States> fsm;
[SetUp]
public void Init()
{
go = new GameObject("stateTest");
behaviour = go.AddComponent<ClassWithBasicStates>();
engine = go.AddComponent<StateMachineRunner>();
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void InitialTransition()
{
fsm = engine.Initialize<States>(behaviour, States.One);
fsm.ChangeState(States.Two);
Assert.AreEqual(1, behaviour.oneStats.enterCount);
Assert.AreEqual(0, behaviour.oneStats.updateCount);
Assert.AreEqual(0, behaviour.oneStats.lateUpdateCount);
Assert.AreEqual(1, behaviour.oneStats.exitCount);
Assert.AreEqual(1, behaviour.oneStats.finallyCount);
Assert.AreEqual(1, behaviour.twoStats.enterCount);
Assert.AreEqual(0, behaviour.twoStats.updateCount);
Assert.AreEqual(0, behaviour.twoStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.twoStats.exitCount);
Assert.AreEqual(0, behaviour.twoStats.finallyCount);
Assert.AreEqual(0, behaviour.threeStats.enterCount);
Assert.AreEqual(0, behaviour.threeStats.updateCount);
Assert.AreEqual(0, behaviour.threeStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.threeStats.exitCount);
Assert.AreEqual(0, behaviour.threeStats.finallyCount);
behaviour.enabled = false;
fsm.ChangeState(States.Three);
Assert.AreEqual(1, behaviour.oneStats.enterCount);
Assert.AreEqual(0, behaviour.oneStats.updateCount);
Assert.AreEqual(0, behaviour.oneStats.lateUpdateCount);
Assert.AreEqual(1, behaviour.oneStats.exitCount);
Assert.AreEqual(1, behaviour.oneStats.finallyCount);
Assert.AreEqual(1, behaviour.twoStats.enterCount);
Assert.AreEqual(0, behaviour.twoStats.updateCount);
Assert.AreEqual(0, behaviour.twoStats.lateUpdateCount);
Assert.AreEqual(1, behaviour.twoStats.exitCount);
Assert.AreEqual(1, behaviour.twoStats.finallyCount);
Assert.AreEqual(1, behaviour.threeStats.enterCount);
Assert.AreEqual(0, behaviour.threeStats.updateCount);
Assert.AreEqual(0, behaviour.threeStats.lateUpdateCount);
Assert.AreEqual(0, behaviour.threeStats.exitCount);
Assert.AreEqual(0, behaviour.threeStats.finallyCount);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ee524972135f5c140a4a5a973cd64ce7
timeCreated: 1457610908
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,145 @@
using System.Collections;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
using UnityEngine.PlayerLoop;
using UnityEngine.TestTools;
public class TestDriverLifecycle
{
public enum States
{
One,
Two,
Three,
Four,
}
public class Driver
{
public StateEvent Foo;
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States, Driver> fsm;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
fsm = new StateMachine<States, Driver>(behaviour);
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void TestDriverEventDoesntFireBeforeStateSet()
{
fsm.Driver.Foo.Invoke();
Assert.AreEqual(0, behaviour.oneFoo);
fsm.ChangeState(States.One);
fsm.Driver.Foo.Invoke();
Assert.AreEqual(1, behaviour.oneFoo);
}
private class StateClass : MonoBehaviour
{
public int oneEnter;
public int oneFoo;
public int oneBar;
public int oneBaz;
public int oneExit;
public int oneBarValue;
public int oneBazValueA;
public int oneBazValueB;
public int twoEnter;
public int twoFoo;
public int twoBar;
public int twoBaz;
public int twoExit;
public int twoBarValue;
public int twoBazValueA;
public int twoBazValueB;
void One_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_Foo()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Foo", Time.frameCount);
oneFoo++;
}
void One_Bar(int value)
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Bar", Time.frameCount);
oneBar++;
oneBarValue = value;
}
void One_Baz(int valueA, int valueB)
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Baz", Time.frameCount);
oneBaz++;
oneBazValueA = valueA;
oneBazValueB = valueB;
}
void One_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Exit", Time.frameCount);
oneExit++;
}
void Two_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Enter", Time.frameCount);
twoEnter++;
}
void Two_Foo()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Foo", Time.frameCount);
twoFoo++;
}
void Two_Bar(int value)
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Bar", Time.frameCount);
twoBar++;
twoBarValue = value;
}
void Two_Baz(int valueA, int valueB)
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Baz", Time.frameCount);
twoBaz++;
twoBazValueA = valueA;
twoBazValueB = valueB;
}
void Two_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Exit", Time.frameCount);
twoExit++;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1ef0a3dffdbf4a6e8c8ff686a0b6efa3
timeCreated: 1616931919

View File

@@ -0,0 +1,147 @@
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
public class TestEmptyDriver
{
public enum States
{
One,
Two,
Three,
Four,
}
public class Driver
{
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States, Driver> fsm;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
fsm = new StateMachine<States, Driver>(behaviour);
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void TestEmptyDriverUpdate()
{
fsm.ChangeState(States.One);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(0, behaviour.oneExit);
Assert.AreEqual(0, behaviour.twoEnter);
Assert.AreEqual(0, behaviour.twoExit);
fsm.ChangeState(States.Two);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(1, behaviour.oneExit);
Assert.AreEqual(1, behaviour.twoEnter);
Assert.AreEqual(0, behaviour.twoExit);
}
private class StateClass : MonoBehaviour
{
public int oneEnter;
public int oneFoo;
public int oneBar;
public int oneBaz;
public int oneExit;
public int oneBarValue;
public int oneBazValueA;
public int oneBazValueB;
public int twoEnter;
public int twoFoo;
public int twoBar;
public int twoBaz;
public int twoExit;
public int twoBarValue;
public int twoBazValueA;
public int twoBazValueB;
void One_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_Foo()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Foo", Time.frameCount);
oneFoo++;
}
void One_Bar(int value)
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Bar", Time.frameCount);
oneBar++;
oneBarValue = value;
}
void One_Baz(int valueA, int valueB)
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Baz", Time.frameCount);
oneBaz++;
oneBazValueA = valueA;
oneBazValueB = valueB;
}
void One_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Exit", Time.frameCount);
oneExit++;
}
void Two_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Enter", Time.frameCount);
twoEnter++;
}
void Two_Foo()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Foo", Time.frameCount);
twoFoo++;
}
void Two_Bar(int value)
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Bar", Time.frameCount);
twoBar++;
twoBarValue = value;
}
void Two_Baz(int valueA, int valueB)
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Baz", Time.frameCount);
twoBaz++;
twoBazValueA = valueA;
twoBazValueB = valueB;
}
void Two_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Exit", Time.frameCount);
twoExit++;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d6391192757a422793fc48ab8a3fd5b7
timeCreated: 1568191151

View File

@@ -0,0 +1,129 @@
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
public class TestInheritedDriver
{
public enum States
{
One,
Two,
Three,
Four,
}
public class Driver : StateDriverUnity
{
public StateEvent Foo;
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States, Driver> fsm;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
fsm = new StateMachine<States, Driver>(behaviour);
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void TestDriverNotNull()
{
Assert.NotNull(fsm.Driver);
}
[Test]
public void TestCustomEvents()
{
fsm.ChangeState(States.One);
fsm.Driver.Foo.Invoke();
fsm.Driver.Update.Invoke();
Assert.AreEqual(1, behaviour.oneFoo);
Assert.AreEqual(1, behaviour.oneUpdate);
Assert.AreEqual(0, behaviour.twoFoo);
Assert.AreEqual(0, behaviour.twoUpdate);
fsm.ChangeState(States.Two);
fsm.Driver.Foo.Invoke();
fsm.Driver.Update.Invoke();
Assert.AreEqual(1, behaviour.oneFoo);
Assert.AreEqual(1, behaviour.oneUpdate);
Assert.AreEqual(1, behaviour.twoFoo);
Assert.AreEqual(1, behaviour.twoUpdate);
}
private class StateClass : MonoBehaviour
{
public int oneEnter;
public int oneFoo;
public int oneUpdate;
public int oneExit;
public int twoEnter;
public int twoFoo;
public int twoUpdate;
public int twoExit;
void One_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_Foo()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Foo", Time.frameCount);
oneFoo++;
}
void One_Update()
{
oneUpdate++;
}
void One_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Exit", Time.frameCount);
oneExit++;
}
void Two_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Enter", Time.frameCount);
twoEnter++;
}
void Two_Foo()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Foo", Time.frameCount);
twoFoo++;
}
void Two_Update()
{
twoUpdate++;
}
void Two_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Exit", Time.frameCount);
twoExit++;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7fe6b2aed376482ab4ab9842c0e791b3
timeCreated: 1568136312

View File

@@ -0,0 +1,81 @@
using System;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using UnityEditor;
using System.Collections;
using Object = UnityEngine.Object;
[TestFixture]
[Category("State Machine Tests")]
internal class TestMultipleSubscribers
{
public enum States
{
One,
Two,
Three,
}
private GameObject go;
private ClassWithBasicStates behaviour1;
private ClassWithBasicStates behaviour2;
private ClassWithBasicStates behaviour3;
private StateMachineRunner engine;
private StateMachine<States> fsm;
[SetUp]
public void Init()
{
go = new GameObject("stateTest");
behaviour1 = go.AddComponent<ClassWithBasicStates>();
behaviour2 = go.AddComponent<ClassWithBasicStates>();
behaviour3 = go.AddComponent<ClassWithBasicStates>();
engine = go.AddComponent<StateMachineRunner>();
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void TestNoCrossTalk()
{
var fsm1 = engine.Initialize<States>(behaviour1, States.One);
var fsm2 = engine.Initialize<States>(behaviour2, States.Two);
var fsm3 = engine.Initialize<States>(behaviour3, States.One);
fsm2.ChangeState(States.Three);
fsm2.ChangeState(States.Two);
fsm3.ChangeState(States.Three);
Assert.AreEqual(1, behaviour1.oneStats.enterCount);
Assert.AreEqual(0, behaviour1.oneStats.exitCount);
Assert.AreEqual(0, behaviour1.twoStats.enterCount);
Assert.AreEqual(0, behaviour1.twoStats.exitCount);
Assert.AreEqual(0, behaviour1.threeStats.enterCount);
Assert.AreEqual(0, behaviour1.threeStats.exitCount);
Assert.AreEqual(0, behaviour2.oneStats.enterCount);
Assert.AreEqual(0, behaviour2.oneStats.exitCount);
Assert.AreEqual(2, behaviour2.twoStats.enterCount);
Assert.AreEqual(1, behaviour2.twoStats.exitCount);
Assert.AreEqual(1, behaviour2.threeStats.enterCount);
Assert.AreEqual(1, behaviour2.threeStats.exitCount);
Assert.AreEqual(1, behaviour3.oneStats.enterCount);
Assert.AreEqual(1, behaviour3.oneStats.exitCount);
Assert.AreEqual(0, behaviour3.twoStats.enterCount);
Assert.AreEqual(0, behaviour3.twoStats.exitCount);
Assert.AreEqual(1, behaviour3.threeStats.enterCount);
Assert.AreEqual(0, behaviour3.threeStats.exitCount);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 871e6dc4ae40b964f999b5a2b4b88147
timeCreated: 1457534452
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
using Object = UnityEngine.Object;
public class TestNonStandardEnums
{
private enum StatesUlong : ulong
{
Foo = ulong.MaxValue,
}
private GameObject go;
private StateClass behaviour;
private StateMachine<StatesUlong, TestCachedDriver.Driver> fsm;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void TestNonIntEnumErrors()
{
Assert.Catch(typeof(ArgumentException), () =>
{
fsm = new StateMachine<StatesUlong, TestCachedDriver.Driver>(behaviour);
});
}
private class StateClass : MonoBehaviour
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 58f27538abe6462f9ed6996603c5017b
timeCreated: 1616936058

View File

@@ -0,0 +1,109 @@
using System;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using Object = UnityEngine.Object;
public class TestStateClassTypesMismatchDriver
{
public enum States
{
One,
Two,
Three,
Four,
}
public class Driver
{
public StateEvent Foo;
public StateEvent<int> Bar;
public StateEvent<int, int> Baz;
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States, Driver> fsm;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void TestMismatchedEvents()
{
Assert.Throws<ArgumentException>(() =>
new StateMachine<States, Driver>(behaviour)
);
}
private class StateClass : MonoBehaviour
{
public int oneEnter;
public int oneFoo;
public int oneBar;
public int oneBaz;
public int oneExit;
public int oneBarValue;
public int oneBazValueA;
public int oneBazValueB;
public int twoEnter;
public int twoExit;
void One_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_Baz()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Foo", Time.frameCount);
oneFoo++;
}
void One_Foo(int value)
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Bar", Time.frameCount);
oneBar++;
oneBarValue = value;
}
void One_Bar(int valueA, int valueB)
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Baz", Time.frameCount);
oneBaz++;
oneBazValueA = valueA;
oneBazValueB = valueB;
}
void One_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "One Exit", Time.frameCount);
oneExit++;
}
void Two_Enter()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Enter", Time.frameCount);
twoEnter++;
}
void Two_Exit()
{
//Debug.LogFormat("State:{0} Frame:{1}", "Two Exit", Time.frameCount);
twoExit++;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ac06595e9bcd40348af830ec6a29a7a5
timeCreated: 1568133089

View File

@@ -0,0 +1,101 @@
using System;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using Object = UnityEngine.Object;
[TestFixture]
[Category("State Machine Tests")]
public class TestStateEngineInitialization
{
public enum TestStates
{
StateInit,
StatePlay,
StateEnd,
}
public enum TestNoDefines
{
}
private GameObject go;
private ClassWithBasicStates behaviour;
private StateMachineRunner engine;
[SetUp]
public void Init()
{
go = new GameObject("stateTest");
behaviour = go.AddComponent<ClassWithBasicStates>();
engine = go.AddComponent<StateMachineRunner>();
}
[TearDown]
public void Kill()
{
Object.DestroyImmediate(go);
}
[Test]
public void TestInitializedTwice()
{
//Should this throw an error? I'm not sure?
var fsm = engine.Initialize<TestStates>(behaviour);
fsm = engine.Initialize<TestStates>(behaviour);
}
[Test]
public void TestStatesDefined()
{
Assert.Throws<ArgumentException>(
() => { engine.Initialize<TestNoDefines>(behaviour); }
);
}
[Test]
public void TestStatePropBeforeChange()
{
var fsm = new StateMachine<TestStates, StateDriverUnity>(behaviour);
Assert.Throws<NullReferenceException>(() =>
{
TestStates state = fsm.State;
});
fsm.ChangeState(TestStates.StateInit);
Assert.AreEqual(TestStates.StateInit, fsm.State);
}
[Test]
public void TestLastStatePropBeforeChange()
{
var fsm = new StateMachine<TestStates, StateDriverUnity>(behaviour);
Assert.Throws<NullReferenceException>(() =>
{
TestStates state = fsm.LastState;
});
Assert.IsFalse(fsm.LastStateExists);
fsm.ChangeState(TestStates.StateInit);
//Conflicted about this. Prefer to return default values, or the current state
//but that would undermine correctness
Assert.Throws<NullReferenceException>(() =>
{
TestStates state = fsm.LastState;
});
Assert.IsFalse(fsm.LastStateExists);
fsm.ChangeState(TestStates.StatePlay);
Assert.AreEqual(TestStates.StateInit, fsm.LastState);
Assert.IsTrue(fsm.LastStateExists);
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d88daf46dc6100c44a16b31a04a34481
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4f46855213027aa4c83ef9e551448ea5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
using UnityEngine;
using System.Collections;
using MonsterLove.StateMachine;
public class ClassDerivedFromSuperClass : ClassWithBasicStates
{
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 56b834ac2387fd9428fa8e3d03e15af9
timeCreated: 1466594866
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,95 @@
using MonsterLove.StateMachine;
using UnityEngine;
using System.Collections;
public class ClassWithBasicStates : MonoBehaviour
{
public ClassWithBasicStatesTestHelper oneStats = new ClassWithBasicStatesTestHelper();
public ClassWithBasicStatesTestHelper twoStats = new ClassWithBasicStatesTestHelper();
public ClassWithBasicStatesTestHelper threeStats = new ClassWithBasicStatesTestHelper();
protected void One_Enter()
{
oneStats.enterCount++;
}
protected void One_Update()
{
oneStats.updateCount++;
}
protected void One_LateUpdate()
{
oneStats.lateUpdateCount++;
}
protected void One_Exit()
{
oneStats.exitCount++;
}
protected void One_Finally()
{
oneStats.finallyCount++;
}
protected void Two_Enter()
{
twoStats.enterCount++;
}
protected void Two_Update()
{
twoStats.updateCount++;
}
protected void Two_LateUpdate()
{
twoStats.lateUpdateCount++;
}
protected void Two_Exit()
{
twoStats.exitCount++;
}
protected void Two_Finally()
{
twoStats.finallyCount++;
}
protected void Three_Enter()
{
threeStats.enterCount++;
}
protected void Three_Update()
{
threeStats.updateCount++;
}
protected void Three_LateUpdate()
{
threeStats.lateUpdateCount++;
}
protected void Three_Exit()
{
threeStats.exitCount++;
}
protected void Three_Finally()
{
threeStats.finallyCount++;
}
}
[System.Serializable]
public class ClassWithBasicStatesTestHelper
{
public int enterCount;
public int updateCount;
public int lateUpdateCount;
public int exitCount;
public int finallyCount;
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f41bf36ff667bf844808b5e9fa28af3f
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,21 @@
{
"name": "MonsterLove.StateMachine.Tests.Runtime",
"references": [
"MonsterLove.StateMachine.Runtime",
"UnityEngine.TestRunner",
"UnityEditor.TestRunner"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f9fb370cdd6625f4fb8a0dec85124b0c
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,199 @@
using System.Collections;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class TestAsyncCustomDriver
{
public enum States
{
One,
Two,
Three,
Four,
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States, StateDriverUnity> fsm;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
fsm = new StateMachine<States, StateDriverUnity>(behaviour);
behaviour.fsm = fsm;
}
[TearDown]
public void Kill()
{
Object.Destroy(go);
}
[UnityTest]
public IEnumerator TestChange()
{
// /1
fsm.ChangeState(States.One);
yield return null;
Assert.AreEqual(0, behaviour.oneEnter);
Assert.AreEqual(0, behaviour.oneUpdate); //Enter still running, no update called
yield return null;
Assert.AreEqual(1, behaviour.oneEnter); //Enter now complete
Assert.AreEqual(0, behaviour.oneUpdate); //Update executes before co-routine, therefore update not run yet
yield return null;
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(1, behaviour.oneUpdate); //Update has first chance to run
}
private class StateClass : MonoBehaviour
{
public StateMachine<States, StateDriverUnity> fsm;
public int oneEnter;
public int oneUpdate;
public int oneExit;
public int oneFinally;
public int twoEnter;
public int twoUpdate;
public int twoExit;
public int twoFinally;
public int threeEnter;
public int threeUpdate;
public int threeExit;
public int threeFinally;
public int fourEnter;
public int fourUpdate;
public int fourExit;
public int fourFinally;
void Update()
{
fsm.Driver.Update.Invoke();
}
IEnumerator One_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Enter Start", Time.frameCount);
yield return null;
yield return null;
Debug.LogFormat("State:{0} Frame:{1}", "One Enter End", Time.frameCount);
oneEnter++;
}
void One_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Update", Time.frameCount);
oneUpdate++;
}
IEnumerator One_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Exit Start", Time.frameCount);
yield return null;
yield return null;
Debug.LogFormat("State:{0} Frame:{1}", "One Exit End", Time.frameCount);
oneExit++;
}
void One_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Finally", Time.frameCount);
oneFinally++;
}
void Two_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Enter", Time.frameCount);
twoEnter++;
}
void Two_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Update", Time.frameCount);
twoUpdate++;
}
void Two_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Exit", Time.frameCount);
twoExit++;
}
void Two_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Finally", Time.frameCount);
twoFinally++;
}
void Three_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Enter", Time.frameCount);
threeEnter++;
}
void Three_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Update", Time.frameCount);
threeUpdate++;
}
void Three_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Exit", Time.frameCount);
threeExit++;
}
void Three_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Finally", Time.frameCount);
threeFinally++;
}
void Four_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Enter", Time.frameCount);
fourEnter++;
}
void Four_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Update", Time.frameCount);
fourUpdate++;
}
void Four_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Exit", Time.frameCount);
fourExit++;
}
void Four_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Finally", Time.frameCount);
fourFinally++;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7b734601d42952c488c972b05398a234
timeCreated: 1567675903

View File

@@ -0,0 +1,286 @@
using System.Collections;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class TestChangeAsyncOverwrite
{
public enum States
{
One,
Two,
Three,
Four,
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States> fsm;
private float duration = 0.5f;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
behaviour.duration = duration;
fsm = StateMachine<States>.Initialize(behaviour);
}
[TearDown]
public void Kill()
{
Object.Destroy(go);
}
[UnityTest]
public IEnumerator TestAsyncEnterExit()
{
// 1
fsm.ChangeState(States.One, StateTransition.Overwrite);
// 1*__/2
fsm.ChangeState(States.Two, StateTransition.Overwrite);
Assert.AreEqual(States.One, fsm.LastState);
Assert.AreEqual(States.Two, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
yield return new WaitForSeconds(duration + 0.2f);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(0, behaviour.oneUpdate);
Assert.AreEqual(0, behaviour.oneExit);
Assert.AreEqual(1, behaviour.oneFinally);
Assert.AreEqual(1, behaviour.twoEnter);
Assert.AreEqual(States.One, fsm.LastState);
Assert.AreEqual(States.Two, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
}
[UnityTest]
public IEnumerator TestChangeDuringAsyncEnter()
{
// 1
fsm.ChangeState(States.One, StateTransition.Overwrite);
// 1\__/2
fsm.ChangeState(States.Two, StateTransition.Safe);
Assert.AreEqual(false, fsm.LastStateExists);
Assert.AreEqual(States.One, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
yield return new WaitForSeconds(duration + duration * 0.5f);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(0, behaviour.oneUpdate);
Assert.AreEqual(1, behaviour.oneExit);
Assert.AreEqual(1, behaviour.oneFinally);
Assert.AreEqual(0, behaviour.twoEnter);
Assert.AreEqual(0, behaviour.threeEnter);
Assert.AreEqual(States.One, fsm.LastState);
Assert.AreEqual(States.Two, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
// 1\__*2__3
fsm.ChangeState(States.Three, StateTransition.Overwrite);
Assert.AreEqual(0, behaviour.twoEnter); //Intro never completes
Assert.AreEqual(1, behaviour.twoExit); //Single frame Exit still fires. Arguably more consistent that exit doesn't fire, instead relying on finally(), however this would be a breaking change
Assert.AreEqual(0, behaviour.twoUpdate);
Assert.AreEqual(1, behaviour.twoFinally);
Assert.AreEqual(1, behaviour.threeEnter);
Assert.AreEqual(States.Two, fsm.LastState);
Assert.AreEqual(States.Three, fsm.State);
Assert.AreEqual(States.Three, fsm.NextState);
}
[UnityTest]
public IEnumerator TestChangeDuringAsyncExit()
{
// 1
fsm.ChangeState(States.One, StateTransition.Overwrite);
// 1\__/2
fsm.ChangeState(States.Two, StateTransition.Safe);
Assert.AreEqual(false, fsm.LastStateExists);
Assert.AreEqual(States.One, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
yield return new WaitForSeconds(duration * 0.5f);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(0, behaviour.oneUpdate);
Assert.AreEqual(0, behaviour.oneExit);
Assert.AreEqual(0, behaviour.oneFinally);
Assert.AreEqual(0, behaviour.twoEnter);
Assert.AreEqual(false, fsm.LastStateExists);
Assert.AreEqual(States.One, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
// 1*__/4
fsm.ChangeState(States.Four, StateTransition.Overwrite);
Assert.AreEqual(States.One, fsm.LastState);
Assert.AreEqual(States.Four, fsm.State);
Assert.AreEqual(States.Four, fsm.NextState);
yield return new WaitForSeconds(duration + 0.2f);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(0, behaviour.oneUpdate);
Assert.AreEqual(0, behaviour.oneExit); //Cancelled - never completed
Assert.AreEqual(1, behaviour.oneFinally);
Assert.AreEqual(0, behaviour.twoEnter); //Never entered
Assert.AreEqual(1, behaviour.fourEnter);
Assert.AreEqual(States.One, fsm.LastState);
Assert.AreEqual(States.Four, fsm.State);
Assert.AreEqual(States.Four, fsm.NextState);
}
private class StateClass : MonoBehaviour
{
public float duration;
public int oneEnter;
public int oneUpdate;
public int oneExit;
public int oneFinally;
public int twoEnter;
public int twoUpdate;
public int twoExit;
public int twoFinally;
public int threeEnter;
public int threeUpdate;
public int threeExit;
public int threeFinally;
public int fourEnter;
public int fourUpdate;
public int fourExit;
public int fourFinally;
void One_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Update", Time.frameCount);
oneUpdate++;
}
IEnumerator One_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Exit Start", Time.frameCount);
yield return new WaitForSeconds(duration);
Debug.LogFormat("State:{0} Frame:{1}", "One Exit End", Time.frameCount);
oneExit++;
}
void One_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Finally", Time.frameCount);
oneFinally++;
}
IEnumerator Two_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Enter Start", Time.frameCount);
yield return new WaitForSeconds(duration);
Debug.LogFormat("State:{0} Frame:{1}", "Two Enter End", Time.frameCount);
twoEnter++;
}
void Two_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Update", Time.frameCount);
twoUpdate++;
}
void Two_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Exit", Time.frameCount);
twoExit++;
}
void Two_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Finally", Time.frameCount);
twoFinally++;
}
void Three_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Enter", Time.frameCount);
threeEnter++;
}
void Three_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Update", Time.frameCount);
threeUpdate++;
}
void Three_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Exit", Time.frameCount);
threeExit++;
}
void Three_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Finally", Time.frameCount);
threeFinally++;
}
IEnumerator Four_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Enter Start", Time.frameCount);
yield return new WaitForSeconds(duration);
Debug.LogFormat("State:{0} Frame:{1}", "Four Enter End", Time.frameCount);
fourEnter++;
}
void Four_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Update", Time.frameCount);
fourUpdate++;
}
void Four_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Exit", Time.frameCount);
fourExit++;
}
void Four_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Finally", Time.frameCount);
fourFinally++;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1a082dc9366ca784087bde0dde49a5ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,302 @@
using System.Collections;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class TestChangeAsyncSafe
{
public enum States
{
One,
Two,
Three,
Four,
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States> fsm;
private float duration = 0.5f;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
behaviour.duration = duration;
fsm = StateMachine<States>.Initialize(behaviour);
}
[TearDown]
public void Kill()
{
Object.Destroy(go);
}
[UnityTest]
public IEnumerator TestAsyncEnterExit()
{
// 1
fsm.ChangeState(States.One, StateTransition.Safe);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(0, behaviour.oneExit);
Assert.AreEqual(0, behaviour.twoEnter);
// 1\__/2
fsm.ChangeState(States.Two, StateTransition.Safe);
Assert.Catch(() => { var state = fsm.LastState;});
Assert.AreEqual(States.One, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(0, behaviour.oneExit);
Assert.AreEqual(0, behaviour.twoEnter);
yield return new WaitForSeconds(duration + duration + 0.2f);
Assert.AreEqual(States.One, fsm.LastState);
Assert.AreEqual(States.Two, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(1, behaviour.oneExit);
Assert.AreEqual(1, behaviour.twoEnter);
}
[UnityTest]
public IEnumerator TestChangeDuringAsyncEnter()
{
// 3
fsm.ChangeState(States.Three, StateTransition.Safe);
// 3__/2
fsm.ChangeState(States.Two);
Assert.AreEqual(1, behaviour.threeExit);
Assert.AreEqual(0, behaviour.twoEnter);
Assert.AreEqual(States.Three, fsm.LastState);
Assert.AreEqual(States.Two, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
yield return new WaitForSeconds(duration / 2f);
// 3__/2\__4 //In safe mode, once a state is entered, both enter and exit are allowed to finish
fsm.ChangeState(States.Four);
Assert.AreEqual(1, behaviour.threeExit);
Assert.AreEqual(0, behaviour.twoEnter);
Assert.AreEqual(0, behaviour.twoUpdate);
Assert.AreEqual(0, behaviour.twoExit);
Assert.AreEqual(0, behaviour.twoFinally);
Assert.AreEqual(0, behaviour.fourEnter);
Assert.AreEqual(States.Three, fsm.LastState);
Assert.AreEqual(States.Two, fsm.State);
Assert.AreEqual(States.Four, fsm.NextState);
yield return new WaitForSeconds(duration / 2f + duration + 0.2f);
Assert.AreEqual(1, behaviour.threeExit);
Assert.AreEqual(1, behaviour.twoEnter);
Assert.AreEqual(1, behaviour.twoUpdate); //Single frame update while changing from Enter To Exit Routines. Not sure this is desired behaviour (zero update frames is more consistent), but don't want to cause a breaking change
Assert.AreEqual(1, behaviour.twoExit);
Assert.AreEqual(1, behaviour.twoFinally);
Assert.AreEqual(1, behaviour.fourEnter);
Assert.AreEqual(States.Two, fsm.LastState);
Assert.AreEqual(States.Four, fsm.State);
Assert.AreEqual(States.Four, fsm.NextState);
}
[UnityTest]
public IEnumerator TestChangeDuringAsyncExit()
{
// 1
fsm.ChangeState(States.One, StateTransition.Safe);
// 1\__3
fsm.ChangeState(States.Three, StateTransition.Safe);
yield return new WaitForSeconds(duration / 2f);
Assert.AreEqual(0, behaviour.oneExit);
Assert.AreEqual(0, behaviour.threeEnter);
Assert.AreEqual(0, behaviour.threeExit);
Assert.AreEqual(0, behaviour.fourEnter);
Assert.Catch(() => { var state = fsm.LastState;});
Assert.AreEqual(States.One, fsm.State);
Assert.AreEqual(States.Three, fsm.NextState);
// 1\__4 //In safe mode, before state is entered, newer state will supersede queued state
fsm.ChangeState(States.Four);
Assert.AreEqual(0, behaviour.oneExit);
Assert.AreEqual(0, behaviour.threeEnter);
Assert.AreEqual(0, behaviour.threeExit);
Assert.AreEqual(0, behaviour.fourEnter);
Assert.Catch(() => { var state = fsm.LastState;});
Assert.AreEqual(States.One, fsm.State);
Assert.AreEqual(States.Four, fsm.NextState);
yield return new WaitForSeconds(duration / 2f + 0.2f);
Assert.AreEqual(1, behaviour.oneExit);
Assert.AreEqual(0, behaviour.threeEnter); //Three never runs
Assert.AreEqual(0, behaviour.threeExit);
Assert.AreEqual(1, behaviour.fourEnter);
Assert.AreEqual(States.One, fsm.LastState);
Assert.AreEqual(States.Four, fsm.State);
Assert.AreEqual(States.Four, fsm.NextState);
}
private class StateClass : MonoBehaviour
{
public float duration;
public int oneEnter;
public int oneUpdate;
public int oneExit;
public int oneFinally;
public int twoEnter;
public int twoUpdate;
public int twoExit;
public int twoFinally;
public int threeEnter;
public int threeUpdate;
public int threeExit;
public int threeFinally;
public int fourEnter;
public int fourUpdate;
public int fourExit;
public int fourFinally;
void One_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Update", Time.frameCount);
oneUpdate++;
}
IEnumerator One_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Exit Start", Time.frameCount);
yield return new WaitForSeconds(duration);
Debug.LogFormat("State:{0} Frame:{1}", "One Exit End", Time.frameCount);
oneExit++;
}
void One_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Finally", Time.frameCount);
oneFinally++;
}
IEnumerator Two_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Enter Start", Time.frameCount);
yield return new WaitForSeconds(duration);
Debug.LogFormat("State:{0} Frame:{1}", "Two Enter End", Time.frameCount);
twoEnter++;
}
void Two_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Update", Time.frameCount);
twoUpdate++;
}
IEnumerator Two_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Exit Start", Time.frameCount);
twoExit++;
yield return new WaitForSeconds(duration);
Debug.LogFormat("State:{0} Frame:{1}", "Two Exit End", Time.frameCount);
}
void Two_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Finally", Time.frameCount);
twoFinally++;
}
void Three_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Enter", Time.frameCount);
threeEnter++;
}
void Three_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Update", Time.frameCount);
threeUpdate++;
}
void Three_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Exit", Time.frameCount);
threeExit++;
}
void Three_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Finally", Time.frameCount);
threeFinally++;
}
void Four_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Enter", Time.frameCount);
fourEnter++;
}
void Four_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Update", Time.frameCount);
fourUpdate++;
}
void Four_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Exit", Time.frameCount);
fourExit++;
}
void Four_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Finally", Time.frameCount);
fourFinally++;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ba617b22bb510241b31b54b32315873
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,220 @@
using System;
using System.Collections;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.Analytics;
using UnityEngine.TestTools;
using Object = UnityEngine.Object;
namespace Tests
{
// TEST DESCRIPTION
//
// Coverage for the scenario where state transition is aborted based on a flag evaluated within transition Enter and Exit methods
public class TestChangeFromTransition
{
public enum States
{
One,
Two,
Three,
Four,
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States> fsm;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
fsm = StateMachine<States>.Initialize(behaviour);
behaviour.fsm = fsm;
}
[TearDown]
public void Kill()
{
Object.Destroy(go);
}
[Test]
public void TestChangeFromExit()
{
//TODO stack overflow is not the expected behaviour - also seems to be periodically crashing test suite. Disable for now
// // 1
// fsm.ChangeState(States.One);
//
//
//
// // 1-__3 //One_Exit contains change to 3
// Assert.Throws<StackOverflowException>(
// ()=> fsm.ChangeState(States.Two)
// );
//
//
//
// // Assert.AreEqual(1, behaviour.oneEnter);
// // Assert.AreEqual(0, behaviour.oneUpdate);
// // Assert.AreEqual(1, behaviour.oneExit);
// // Assert.AreEqual(1, behaviour.oneFinally);
// //
// // Assert.AreEqual(0, behaviour.twoEnter);
// // Assert.AreEqual(0, behaviour.twoUpdate);
// // Assert.AreEqual(0, behaviour.twoFinally);
// //
// // Assert.AreEqual(1, behaviour.threeEnter);
}
[Test]
public void TestChangeFromEnter()
{
fsm.ChangeState(States.Two);
// -4__3 //Four_Enter contains change to 3
fsm.ChangeState(States.Four);
Assert.AreEqual(1, behaviour.fourEnter); //This will complete after Exit and Finally. Not sure how to make this subtle side effect more obvious
Assert.AreEqual(0, behaviour.fourUpdate);
Assert.AreEqual(1, behaviour.fourExit);
Assert.AreEqual(1, behaviour.fourFinally);
Assert.AreEqual(1, behaviour.threeEnter);
Assert.AreEqual(States.Four, fsm.LastState);
Assert.AreEqual(States.Three, fsm.State);
Assert.AreEqual(States.Three, fsm.NextState);
}
private class StateClass : MonoBehaviour
{
public StateMachine<States> fsm;
public int oneEnter;
public int oneUpdate;
public int oneExit;
public int oneFinally;
public int twoEnter;
public int twoUpdate;
public int twoExit;
public int twoFinally;
public int threeEnter;
public int threeUpdate;
public int threeExit;
public int threeFinally;
public int fourEnter;
public int fourUpdate;
public int fourExit;
public int fourFinally;
void One_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Update", Time.frameCount);
oneUpdate++;
}
void One_Exit()
{
fsm.ChangeState(States.Three);
Debug.LogFormat("State:{0} Frame:{1}", "One Exit", Time.frameCount);
oneExit++;
}
void One_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Finally", Time.frameCount);
oneFinally++;
}
void Two_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Enter", Time.frameCount);
twoEnter++;
}
void Two_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Update", Time.frameCount);
twoUpdate++;
}
void Two_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Exit", Time.frameCount);
twoExit++;
}
void Two_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Finally", Time.frameCount);
twoFinally++;
}
void Three_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Enter", Time.frameCount);
threeEnter++;
}
void Three_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Update", Time.frameCount);
threeUpdate++;
}
void Three_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Exit", Time.frameCount);
threeExit++;
}
void Three_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Finally", Time.frameCount);
threeFinally++;
}
void Four_Enter()
{
fsm.ChangeState(States.Three);
Debug.LogFormat("State:{0} Frame:{1}", "Four Enter", Time.frameCount);
fourEnter++;
}
void Four_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Update", Time.frameCount);
fourUpdate++;
}
void Four_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Exit", Time.frameCount);
fourExit++;
}
void Four_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Finally", Time.frameCount);
fourFinally++;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: edc9ab4afa17406b8cdfe574960c6177
timeCreated: 1567694365

View File

@@ -0,0 +1,213 @@
using System.Collections;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class TestChangeState
{
public enum States
{
One,
Two,
Three,
Four,
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States> fsm;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
fsm = StateMachine<States>.Initialize(behaviour);
}
[TearDown]
public void Kill()
{
Object.Destroy(go);
}
[UnityTest]
public IEnumerator TestChange()
{
fsm.ChangeState(States.One);
Assert.Catch(()=>
{
var last = fsm.LastState;
});
Assert.AreEqual(States.One, fsm.State);
Assert.AreEqual(States.One, fsm.NextState);
yield return null;
fsm.ChangeState(States.Two);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(1, behaviour.oneUpdate);
Assert.AreEqual(1, behaviour.oneExit);
Assert.AreEqual(1, behaviour.oneFinally);
Assert.AreEqual(1, behaviour.twoEnter);
Assert.AreEqual(0, behaviour.twoUpdate); //Only changed this frame, hasn't had a chance to update yet
Assert.AreEqual(States.One, fsm.LastState);
Assert.AreEqual(States.Two, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
yield return null;
Assert.AreEqual(1, behaviour.twoUpdate); //First update runs a frame later
}
[UnityTest]
public IEnumerator TestChangeSameFrame()
{
fsm.ChangeState(States.One);
fsm.ChangeState(States.Two);
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(0, behaviour.oneUpdate); //Update never has chance to fire during same frame change
Assert.AreEqual(1, behaviour.oneExit);
Assert.AreEqual(1, behaviour.oneFinally);
Assert.AreEqual(1, behaviour.twoEnter);
Assert.AreEqual(0, behaviour.twoUpdate);
Assert.AreEqual(States.One, fsm.LastState);
Assert.AreEqual(States.Two, fsm.State);
Assert.AreEqual(States.Two, fsm.NextState);
yield return null;
Assert.AreEqual(0, behaviour.oneUpdate);
Assert.AreEqual(1, behaviour.twoUpdate); //First frame runs in state two
}
private class StateClass : MonoBehaviour
{
public int oneEnter;
public int oneUpdate;
public int oneExit;
public int oneFinally;
public int twoEnter;
public int twoUpdate;
public int twoExit;
public int twoFinally;
public int threeEnter;
public int threeUpdate;
public int threeExit;
public int threeFinally;
public int fourEnter;
public int fourUpdate;
public int fourExit;
public int fourFinally;
void One_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Update", Time.frameCount);
oneUpdate++;
}
void One_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Exit", Time.frameCount);
oneExit++;
}
void One_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Finally", Time.frameCount);
oneFinally++;
}
void Two_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Enter", Time.frameCount);
twoEnter++;
}
void Two_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Update", Time.frameCount);
twoUpdate++;
}
void Two_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Exit", Time.frameCount);
twoExit++;
}
void Two_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Two Finally", Time.frameCount);
twoFinally++;
}
void Three_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Enter", Time.frameCount);
threeEnter++;
}
void Three_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Update", Time.frameCount);
threeUpdate++;
}
void Three_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Exit", Time.frameCount);
threeExit++;
}
void Three_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Three Finally", Time.frameCount);
threeFinally++;
}
void Four_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Enter", Time.frameCount);
fourEnter++;
}
void Four_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Update", Time.frameCount);
fourUpdate++;
}
void Four_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Exit", Time.frameCount);
fourExit++;
}
void Four_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "Four Finally", Time.frameCount);
fourFinally++;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4306d2f2aa71459c9ea87a83001fd117
timeCreated: 1567675903

View File

@@ -0,0 +1,100 @@
using System.Collections;
using MonsterLove.StateMachine;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class TestMonoBehaviourUpdates
{
public enum States
{
One,
Two,
Three,
Four,
}
private GameObject go;
private StateClass behaviour;
private StateMachine<States> fsm;
[SetUp]
public void Init()
{
go = new GameObject();
behaviour = go.AddComponent<StateClass>();
fsm = StateMachine<States>.Initialize(behaviour);
}
[TearDown]
public void Kill()
{
Object.Destroy(go);
}
[UnityTest]
public IEnumerator TestUpdate()
{
fsm.ChangeState(States.One);
yield return null;
Assert.AreEqual(1, behaviour.oneEnter);
Assert.AreEqual(1, behaviour.oneUpdate);
Assert.AreEqual(1, behaviour.oneLateUpdate);
yield return new WaitForSeconds(Time.fixedDeltaTime);
Assert.GreaterOrEqual(behaviour.oneFixedUpdate, 1);
}
private class StateClass : MonoBehaviour
{
public int oneEnter;
public int oneUpdate;
public int oneFixedUpdate;
public int oneLateUpdate;
public int oneExit;
public int oneFinally;
void One_Enter()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Enter", Time.frameCount);
oneEnter++;
}
void One_FixedUpdate()
{
Debug.LogFormat("State:{0} Frame:{1}", "One FixedUpdate", Time.frameCount);
oneFixedUpdate++;
}
void One_Update()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Update", Time.frameCount);
oneUpdate++;
}
void One_LateUpdate()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Late Update", Time.frameCount);
oneLateUpdate++;
}
void One_Exit()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Exit", Time.frameCount);
oneExit++;
}
void One_Finally()
{
Debug.LogFormat("State:{0} Frame:{1}", "One Finally", Time.frameCount);
oneFinally++;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 87d1cfcf5f33f2441b2b848c6053dbcf
timeCreated: 1567675903