summaryrefslogtreecommitdiff
path: root/WorldlineKeepers/Assets
diff options
context:
space:
mode:
Diffstat (limited to 'WorldlineKeepers/Assets')
-rw-r--r--WorldlineKeepers/Assets/Bundle/characters/ronin/ronin.json19
-rw-r--r--WorldlineKeepers/Assets/Bundle/metadata/default_items.csv2
-rw-r--r--WorldlineKeepers/Assets/Bundle/metadata/default_items.csv.meta7
-rw-r--r--WorldlineKeepers/Assets/Plugins.meta8
-rw-r--r--WorldlineKeepers/Assets/Plugins/Trinary Software.meta9
-rw-r--r--WorldlineKeepers/Assets/Plugins/Trinary Software/Editor.meta9
-rw-r--r--WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.pngbin0 -> 36388 bytes
-rw-r--r--WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png.meta57
-rw-r--r--WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdfbin0 -> 690071 bytes
-rw-r--r--WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf.meta8
-rw-r--r--WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs2738
-rw-r--r--WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs.meta12
-rw-r--r--WorldlineKeepers/Assets/Scenes/Test.unity26
-rw-r--r--WorldlineKeepers/Assets/Scripts/Buffs/Buff.cs2
-rw-r--r--WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs (renamed from WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs)2
-rw-r--r--WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs.meta (renamed from WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs.meta)0
-rw-r--r--WorldlineKeepers/Assets/Scripts/Common/Statemachine.cs254
-rw-r--r--WorldlineKeepers/Assets/Scripts/Common/Statemachine.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Data/DataManager.cs13
-rw-r--r--WorldlineKeepers/Assets/Scripts/EntityBase.cs2
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/Inventory.cs15
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/Inventory.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/Item.cs21
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/Item.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/ItemBehaviour.cs27
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/ItemBehaviour.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/ItemDaggerBehaviour.cs15
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/ItemDaggerBehaviour.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/ItemHellbellBehaviour.cs15
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/ItemHellbellBehaviour.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/ItemMetadata.cs23
-rw-r--r--WorldlineKeepers/Assets/Scripts/Items/ItemMetadata.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/StaticDefine.cs2
-rw-r--r--WorldlineKeepers/Assets/Scripts/Stats/CharacterStatsBase.cs28
-rw-r--r--WorldlineKeepers/Assets/Scripts/Stats/CharacterStatsMetadata.cs2
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs40
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools.meta8
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/GlobalEventManager.cs97
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/GlobalEventManager.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/NotificationCenter.cs167
-rw-r--r--WorldlineKeepers/Assets/Scripts/Tools/NotificationCenter.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs (renamed from WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs)0
-rw-r--r--WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs.meta (renamed from WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs.meta)0
-rw-r--r--WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterMetadata.cs23
-rw-r--r--WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterMetadata.cs.meta11
-rw-r--r--WorldlineKeepers/Assets/Scripts/Unit/Characters/PlayerController.cs6
-rw-r--r--WorldlineKeepers/Assets/Scripts/Unit/Characters/Ronin/RoninBehaviour.cs3
-rw-r--r--WorldlineKeepers/Assets/Scripts/Unit/Enemies/SpiritScript.cs4
-rw-r--r--WorldlineKeepers/Assets/Scripts/Unit/UnitManager.cs15
-rw-r--r--WorldlineKeepers/Assets/Scripts/Unit/UnitManager.cs.meta11
51 files changed, 3787 insertions, 24 deletions
diff --git a/WorldlineKeepers/Assets/Bundle/characters/ronin/ronin.json b/WorldlineKeepers/Assets/Bundle/characters/ronin/ronin.json
index b3600b9..c8afbb1 100644
--- a/WorldlineKeepers/Assets/Bundle/characters/ronin/ronin.json
+++ b/WorldlineKeepers/Assets/Bundle/characters/ronin/ronin.json
@@ -1,10 +1,13 @@
{
- "id" = "ronin",
- "name" = "RONIN",
- "stats" = [
- {"max_level"=0},
- "",
- "",
- ],
-
+ "uid" : "ronin",
+ "name_key" : "CHARACTER_RONIN",
+ "stats" : {
+ "max_level" : "100",
+ "level" : "1",
+ "health" : "100",
+ "max_health" : "10000000",
+ "exp" : "0"
+ },
+ "behaviour":"RoninBehaviour",
+ "extra_data":""
} \ No newline at end of file
diff --git a/WorldlineKeepers/Assets/Bundle/metadata/default_items.csv b/WorldlineKeepers/Assets/Bundle/metadata/default_items.csv
new file mode 100644
index 0000000..b9316e4
--- /dev/null
+++ b/WorldlineKeepers/Assets/Bundle/metadata/default_items.csv
@@ -0,0 +1,2 @@
+uid name_key desc_key icon_path behaviour extra_data
+item_dagger ITEM_DAGGER_NAME ITEM_DAGGER_DESC ItemDaggerBehaviour
diff --git a/WorldlineKeepers/Assets/Bundle/metadata/default_items.csv.meta b/WorldlineKeepers/Assets/Bundle/metadata/default_items.csv.meta
new file mode 100644
index 0000000..101f537
--- /dev/null
+++ b/WorldlineKeepers/Assets/Bundle/metadata/default_items.csv.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 1d38e67da21d65b4db492be4eb6d8688
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Plugins.meta b/WorldlineKeepers/Assets/Plugins.meta
new file mode 100644
index 0000000..88249e6
--- /dev/null
+++ b/WorldlineKeepers/Assets/Plugins.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1b753ffcfa62cb64eba81764eded5f49
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software.meta b/WorldlineKeepers/Assets/Plugins/Trinary Software.meta
new file mode 100644
index 0000000..616b6fb
--- /dev/null
+++ b/WorldlineKeepers/Assets/Plugins/Trinary Software.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 78018ab10cd0fdf48ba17bb3bc57ed62
+folderAsset: yes
+timeCreated: 1456470394
+licenseType: Store
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor.meta b/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor.meta
new file mode 100644
index 0000000..2e833c9
--- /dev/null
+++ b/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 0d53480b6fb0cb246b44b84ec5156cc6
+folderAsset: yes
+timeCreated: 1475431041
+licenseType: Store
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png b/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png
new file mode 100644
index 0000000..caf3365
--- /dev/null
+++ b/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png
Binary files differ
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png.meta b/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png.meta
new file mode 100644
index 0000000..733447a
--- /dev/null
+++ b/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png.meta
@@ -0,0 +1,57 @@
+fileFormatVersion: 2
+guid: a0f854455b10ba44d819f36586b0909b
+timeCreated: 1510247977
+licenseType: Store
+TextureImporter:
+ fileIDToRecycleName: {}
+ serializedVersion: 2
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ linearTexture: 1
+ correctGamma: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 0
+ cubemapConvolution: 0
+ cubemapConvolutionSteps: 7
+ cubemapConvolutionExponent: 1.5
+ seamlessCubemap: 0
+ textureFormat: -3
+ maxTextureSize: 64
+ textureSettings:
+ filterMode: 2
+ aniso: 1
+ mipBias: -1
+ wrapMode: 1
+ nPOTScale: 0
+ lightmap: 0
+ rGBM: 0
+ compressionQuality: 50
+ allowsAlphaSplitting: 0
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spritePixelsToUnits: 100
+ alphaIsTransparency: 1
+ textureType: 2
+ buildTargetSettings: []
+ spriteSheet:
+ sprites: []
+ outline: []
+ spritePackingTag:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf b/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf
new file mode 100644
index 0000000..e2f028f
--- /dev/null
+++ b/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf
Binary files differ
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf.meta b/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf.meta
new file mode 100644
index 0000000..4a34c89
--- /dev/null
+++ b/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a2df0cfe12cb0d64c9d151d10f8ec206
+timeCreated: 1456009584
+licenseType: Store
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs b/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs
new file mode 100644
index 0000000..c61b93e
--- /dev/null
+++ b/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs
@@ -0,0 +1,2738 @@
+using UnityEngine;
+using System.Collections.Generic;
+using UnityEngine.Assertions;
+#if UNITY_5_5_OR_NEWER
+using UnityEngine.Profiling;
+#endif
+
+// /////////////////////////////////////////////////////////////////////////////////////////
+// More Effective Coroutines
+// v3.10.2
+//
+// This is an improved implementation of coroutines that boasts zero per-frame memory allocations,
+// runs about twice as fast as Unity's built in coroutines and has a range of extra features.
+//
+// This is the free version. MEC also has a pro version, which can be found here:
+// https://www.assetstore.unity3d.com/en/#!/content/68480
+// The pro version contains exactly the same core that the free version uses, but also
+// contains many additional features. Every function that exists in MEC Free also exists in MEC Pro,
+// so you can upgrade at any time without breaking existing code.
+//
+// For manual, support, or upgrade guide visit http://trinary.tech/
+//
+// Created by Teal Rogers
+// Trinary Software
+// All rights preserved
+// /////////////////////////////////////////////////////////////////////////////////////////
+
+namespace MEC
+{
+ public class Timing : MonoBehaviour
+ {
+ /// <summary>
+ /// The time between calls to SlowUpdate.
+ /// </summary>
+ [Tooltip("How quickly the SlowUpdate segment ticks.")]
+ public float TimeBetweenSlowUpdateCalls = 1f / 7f;
+ /// <summary>
+ /// The amount that each coroutine should be seperated inside the Unity profiler. NOTE: When the profiler window
+ /// is not open this value is ignored and all coroutines behave as if "None" is selected.
+ /// </summary>
+ [Tooltip("How much data should be sent to the profiler window when it's open.")]
+ public DebugInfoType ProfilerDebugAmount;
+ /// <summary>
+ /// The number of coroutines that are being run in the Update segment.
+ /// </summary>
+ [Tooltip("A count of the number of Update coroutines that are currently running."), Space(12)]
+ public int UpdateCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the FixedUpdate segment.
+ /// </summary>
+ [Tooltip("A count of the number of FixedUpdate coroutines that are currently running.")]
+ public int FixedUpdateCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the LateUpdate segment.
+ /// </summary>
+ [Tooltip("A count of the number of LateUpdate coroutines that are currently running.")]
+ public int LateUpdateCoroutines;
+ /// <summary>
+ /// The number of coroutines that are being run in the SlowUpdate segment.
+ /// </summary>
+ [Tooltip("A count of the number of SlowUpdate coroutines that are currently running.")]
+ public int SlowUpdateCoroutines;
+ /// <summary>
+ /// The time in seconds that the current segment has been running.
+ /// </summary>
+ [System.NonSerialized]
+ public float localTime;
+ /// <summary>
+ /// The time in seconds that the current segment has been running.
+ /// </summary>
+ public static float LocalTime { get { return Instance.localTime; } }
+ /// <summary>
+ /// The amount of time in fractional seconds that elapsed between this frame and the last frame.
+ /// </summary>
+ [System.NonSerialized]
+ public float deltaTime;
+ /// <summary>
+ /// The amount of time in fractional seconds that elapsed between this frame and the last frame.
+ /// </summary>
+ public static float DeltaTime { get { return Instance.deltaTime; } }
+ /// <summary>
+ /// Used for advanced coroutine control.
+ /// </summary>
+ public static System.Func<IEnumerator<float>, CoroutineHandle, IEnumerator<float>> ReplacementFunction;
+ /// <summary>
+ /// This event fires just before each segment is run.
+ /// </summary>
+ public static event System.Action OnPreExecute;
+ /// <summary>
+ /// You can use "yield return Timing.WaitForOneFrame;" inside a coroutine function to go to the next frame.
+ /// </summary>
+ public const float WaitForOneFrame = float.NegativeInfinity;
+ /// <summary>
+ /// The main thread that (almost) everything in unity runs in.
+ /// </summary>
+ public static System.Threading.Thread MainThread { get; private set; }
+ /// <summary>
+ /// The handle of the current coroutine that is running.
+ /// </summary>
+ public static CoroutineHandle CurrentCoroutine
+ {
+ get
+ {
+ for (int i = 0; i < ActiveInstances.Length; i++)
+ if (ActiveInstances[i] != null && ActiveInstances[i].currentCoroutine.IsValid)
+ return ActiveInstances[i].currentCoroutine;
+ return default(CoroutineHandle);
+ }
+ }
+ /// <summary>
+ /// The handle of the current coroutine that is running.
+ /// </summary>
+ public CoroutineHandle currentCoroutine { get; private set; }
+
+ private static object _tmpRef;
+ private static bool _tmpBool;
+ private static CoroutineHandle _tmpHandle;
+
+ private int _currentUpdateFrame;
+ private int _currentLateUpdateFrame;
+ private int _currentSlowUpdateFrame;
+ private int _nextUpdateProcessSlot;
+ private int _nextLateUpdateProcessSlot;
+ private int _nextFixedUpdateProcessSlot;
+ private int _nextSlowUpdateProcessSlot;
+ private int _lastUpdateProcessSlot;
+ private int _lastLateUpdateProcessSlot;
+ private int _lastFixedUpdateProcessSlot;
+ private int _lastSlowUpdateProcessSlot;
+ private float _lastUpdateTime;
+ private float _lastLateUpdateTime;
+ private float _lastFixedUpdateTime;
+ private float _lastSlowUpdateTime;
+ private float _lastSlowUpdateDeltaTime;
+ private ushort _framesSinceUpdate;
+ private ushort _expansions = 1;
+ [SerializeField, HideInInspector]
+ private byte _instanceID;
+
+ private readonly Dictionary<CoroutineHandle, HashSet<CoroutineHandle>> _waitingTriggers = new Dictionary<CoroutineHandle, HashSet<CoroutineHandle>>();
+ private readonly HashSet<CoroutineHandle> _allWaiting = new HashSet<CoroutineHandle>();
+ private readonly Dictionary<CoroutineHandle, ProcessIndex> _handleToIndex = new Dictionary<CoroutineHandle, ProcessIndex>();
+ private readonly Dictionary<ProcessIndex, CoroutineHandle> _indexToHandle = new Dictionary<ProcessIndex, CoroutineHandle>();
+ private readonly Dictionary<CoroutineHandle, string> _processTags = new Dictionary<CoroutineHandle, string>();
+ private readonly Dictionary<string, HashSet<CoroutineHandle>> _taggedProcesses = new Dictionary<string, HashSet<CoroutineHandle>>();
+
+ private IEnumerator<float>[] UpdateProcesses = new IEnumerator<float>[InitialBufferSizeLarge];
+ private IEnumerator<float>[] LateUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ private IEnumerator<float>[] FixedUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
+ private IEnumerator<float>[] SlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
+
+ private bool[] UpdatePaused = new bool[InitialBufferSizeLarge];
+ private bool[] LateUpdatePaused = new bool[InitialBufferSizeSmall];
+ private bool[] FixedUpdatePaused = new bool[InitialBufferSizeMedium];
+ private bool[] SlowUpdatePaused = new bool[InitialBufferSizeMedium];
+ private bool[] UpdateHeld = new bool[InitialBufferSizeLarge];
+ private bool[] LateUpdateHeld = new bool[InitialBufferSizeSmall];
+ private bool[] FixedUpdateHeld = new bool[InitialBufferSizeMedium];
+ private bool[] SlowUpdateHeld = new bool[InitialBufferSizeMedium];
+
+ private const ushort FramesUntilMaintenance = 64;
+ private const int ProcessArrayChunkSize = 64;
+ private const int InitialBufferSizeLarge = 256;
+ private const int InitialBufferSizeMedium = 64;
+ private const int InitialBufferSizeSmall = 8;
+
+ private static Timing[] ActiveInstances = new Timing[16];
+ private static Timing _instance;
+
+ public static Timing Instance
+ {
+ get
+ {
+ if (_instance == null || !_instance.gameObject)
+ {
+ GameObject instanceHome = GameObject.Find("Timing Controller");
+
+ if (instanceHome == null)
+ {
+ instanceHome = new GameObject { name = "Timing Controller" };
+
+ DontDestroyOnLoad(instanceHome);
+ }
+
+ _instance = instanceHome.GetComponent<Timing>() ?? instanceHome.AddComponent<Timing>();
+
+ _instance.InitializeInstanceID();
+ }
+
+ return _instance;
+ }
+ set { _instance = value; }
+ }
+
+ void OnDestroy()
+ {
+ if (_instance == this)
+ _instance = null;
+ }
+
+ void OnEnable()
+ {
+ if (MainThread == null)
+ MainThread = System.Threading.Thread.CurrentThread;
+
+ InitializeInstanceID();
+ }
+
+ void OnDisable()
+ {
+ if (_instanceID < ActiveInstances.Length)
+ ActiveInstances[_instanceID] = null;
+ }
+
+ private void InitializeInstanceID()
+ {
+ if (ActiveInstances[_instanceID] == null)
+ {
+ if (_instanceID == 0x00)
+ _instanceID++;
+
+ for (; _instanceID <= 0x10; _instanceID++)
+ {
+ if (_instanceID == 0x10)
+ {
+ GameObject.Destroy(gameObject);
+ throw new System.OverflowException("You are only allowed 15 different contexts for MEC to run inside at one time.");
+ }
+
+ if (ActiveInstances[_instanceID] == null)
+ {
+ ActiveInstances[_instanceID] = this;
+ break;
+ }
+ }
+ }
+ }
+
+ void Update()
+ {
+ if (OnPreExecute != null)
+ OnPreExecute();
+
+ if (_lastSlowUpdateTime + TimeBetweenSlowUpdateCalls < Time.realtimeSinceStartup && _nextSlowUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.SlowUpdate };
+ if (UpdateTimeValues(coindex.seg))
+ _lastSlowUpdateProcessSlot = _nextSlowUpdateProcessSlot;
+
+ for (coindex.i = 0; coindex.i < _lastSlowUpdateProcessSlot; coindex.i++)
+ {
+ try
+ {
+ if (!SlowUpdatePaused[coindex.i] && !SlowUpdateHeld[coindex.i] && SlowUpdateProcesses[coindex.i] != null && !(localTime < SlowUpdateProcesses[coindex.i].Current))
+ {
+ currentCoroutine = _indexToHandle[coindex];
+
+ if (ProfilerDebugAmount != DebugInfoType.None && _indexToHandle.ContainsKey(coindex))
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine (Slow Update)" +
+ (_processTags.ContainsKey(_indexToHandle[coindex]) ? ", tag " + _processTags[_indexToHandle[coindex]] : ", no tag"))
+ : "Processing Coroutine (Slow Update)");
+ }
+
+ if (!SlowUpdateProcesses[coindex.i].MoveNext())
+ {
+ if (_indexToHandle.ContainsKey(coindex))
+ KillCoroutinesOnInstance(_indexToHandle[coindex]);
+ }
+ else if (SlowUpdateProcesses[coindex.i] != null && float.IsNaN(SlowUpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction != null)
+ {
+ SlowUpdateProcesses[coindex.i] = ReplacementFunction(SlowUpdateProcesses[coindex.i], _indexToHandle[coindex]);
+ ReplacementFunction = null;
+ }
+ coindex.i--;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+ catch (System.Exception ex)
+ {
+ Debug.LogException(ex);
+
+ if (ex is MissingReferenceException)
+ Debug.LogError("This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\n"
+ + "Example: Timing.RunCoroutine(_foo().CancelWith(gameObject), Segment.SlowUpdate);");
+ }
+ }
+ }
+
+ if (_nextUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.Update };
+ if (UpdateTimeValues(coindex.seg))
+ _lastUpdateProcessSlot = _nextUpdateProcessSlot;
+
+ for (coindex.i = 0; coindex.i < _lastUpdateProcessSlot; coindex.i++)
+ {
+ try
+ {
+ if (!UpdatePaused[coindex.i] && !UpdateHeld[coindex.i] && UpdateProcesses[coindex.i] != null && !(localTime < UpdateProcesses[coindex.i].Current))
+ {
+ currentCoroutine = _indexToHandle[coindex];
+
+ if (ProfilerDebugAmount != DebugInfoType.None && _indexToHandle.ContainsKey(coindex))
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine" +
+ (_processTags.ContainsKey(_indexToHandle[coindex]) ? ", tag " + _processTags[_indexToHandle[coindex]] : ", no tag"))
+ : "Processing Coroutine");
+ }
+
+ if (!UpdateProcesses[coindex.i].MoveNext())
+ {
+ if (_indexToHandle.ContainsKey(coindex))
+ KillCoroutinesOnInstance(_indexToHandle[coindex]);
+ }
+ else if (UpdateProcesses[coindex.i] != null && float.IsNaN(UpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction != null)
+ {
+ UpdateProcesses[coindex.i] = ReplacementFunction(UpdateProcesses[coindex.i], _indexToHandle[coindex]);
+ ReplacementFunction = null;
+ }
+ coindex.i--;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+ catch (System.Exception ex)
+ {
+ Debug.LogException(ex);
+
+ if (ex is MissingReferenceException)
+ Debug.LogError("This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\n"
+ + "Example: Timing.RunCoroutine(_foo().CancelWith(gameObject));");
+ }
+ }
+ }
+
+ currentCoroutine = default(CoroutineHandle);
+
+ if(++_framesSinceUpdate > FramesUntilMaintenance)
+ {
+ _framesSinceUpdate = 0;
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.BeginSample("Maintenance Task");
+
+ RemoveUnused();
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+
+ void FixedUpdate()
+ {
+ if (OnPreExecute != null)
+ OnPreExecute();
+
+ if (_nextFixedUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.FixedUpdate };
+ if (UpdateTimeValues(coindex.seg))
+ _lastFixedUpdateProcessSlot = _nextFixedUpdateProcessSlot;
+
+ for (coindex.i = 0; coindex.i < _lastFixedUpdateProcessSlot; coindex.i++)
+ {
+ try
+ {
+ if (!FixedUpdatePaused[coindex.i] && !FixedUpdateHeld[coindex.i] && FixedUpdateProcesses[coindex.i] != null && !(localTime < FixedUpdateProcesses[coindex.i].Current))
+ {
+ currentCoroutine = _indexToHandle[coindex];
+
+
+ if (ProfilerDebugAmount != DebugInfoType.None && _indexToHandle.ContainsKey(coindex))
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine" +
+ (_processTags.ContainsKey(_indexToHandle[coindex]) ? ", tag " + _processTags[_indexToHandle[coindex]] : ", no tag"))
+ : "Processing Coroutine");
+ }
+
+ if (!FixedUpdateProcesses[coindex.i].MoveNext())
+ {
+ if (_indexToHandle.ContainsKey(coindex))
+ KillCoroutinesOnInstance(_indexToHandle[coindex]);
+ }
+ else if (FixedUpdateProcesses[coindex.i] != null && float.IsNaN(FixedUpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction != null)
+ {
+ FixedUpdateProcesses[coindex.i] = ReplacementFunction(FixedUpdateProcesses[coindex.i], _indexToHandle[coindex]);
+ ReplacementFunction = null;
+ }
+ coindex.i--;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+ catch (System.Exception ex)
+ {
+ Debug.LogException(ex);
+
+ if (ex is MissingReferenceException)
+ Debug.LogError("This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\n"
+ + "Example: Timing.RunCoroutine(_foo().CancelWith(gameObject), Segment.FixedUpdate);");
+ }
+ }
+
+ currentCoroutine = default(CoroutineHandle);
+ }
+ }
+
+ void LateUpdate()
+ {
+ if (OnPreExecute != null)
+ OnPreExecute();
+
+ if (_nextLateUpdateProcessSlot > 0)
+ {
+ ProcessIndex coindex = new ProcessIndex { seg = Segment.LateUpdate };
+ if (UpdateTimeValues(coindex.seg))
+ _lastLateUpdateProcessSlot = _nextLateUpdateProcessSlot;
+
+ for (coindex.i = 0; coindex.i < _lastLateUpdateProcessSlot; coindex.i++)
+ {
+ try
+ {
+ if (!LateUpdatePaused[coindex.i] && !LateUpdateHeld[coindex.i] && LateUpdateProcesses[coindex.i] != null && !(localTime < LateUpdateProcesses[coindex.i].Current))
+ {
+ currentCoroutine = _indexToHandle[coindex];
+
+
+ if (ProfilerDebugAmount != DebugInfoType.None && _indexToHandle.ContainsKey(coindex))
+ {
+ Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine" +
+ (_processTags.ContainsKey(_indexToHandle[coindex]) ? ", tag " + _processTags[_indexToHandle[coindex]] : ", no tag"))
+ : "Processing Coroutine");
+ }
+
+ if (!LateUpdateProcesses[coindex.i].MoveNext())
+ {
+ if (_indexToHandle.ContainsKey(coindex))
+ KillCoroutinesOnInstance(_indexToHandle[coindex]);
+ }
+ else if (LateUpdateProcesses[coindex.i] != null && float.IsNaN(LateUpdateProcesses[coindex.i].Current))
+ {
+ if (ReplacementFunction != null)
+ {
+ LateUpdateProcesses[coindex.i] = ReplacementFunction(LateUpdateProcesses[coindex.i], _indexToHandle[coindex]);
+ ReplacementFunction = null;
+ }
+ coindex.i--;
+ }
+
+ if (ProfilerDebugAmount != DebugInfoType.None)
+ Profiler.EndSample();
+ }
+ }
+ catch (System.Exception ex)
+ {
+ Debug.LogException(ex);
+
+ if (ex is MissingReferenceException)
+ Debug.LogError("This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\n"
+ + "Example: Timing.RunCoroutine(_foo().CancelWith(gameObject), Segment.LateUpdate);");
+ }
+ }
+ currentCoroutine = default(CoroutineHandle);
+ }
+ }
+
+ private void RemoveUnused()
+ {
+ var waitTrigsEnum = _waitingTriggers.GetEnumerator();
+ while (waitTrigsEnum.MoveNext())
+ {
+ if (waitTrigsEnum.Current.Value.Count == 0)
+ {
+ _waitingTriggers.Remove(waitTrigsEnum.Current.Key);
+ waitTrigsEnum = _waitingTriggers.GetEnumerator();
+ continue;
+ }
+
+ if (_handleToIndex.ContainsKey(waitTrigsEnum.Current.Key) && CoindexIsNull(_handleToIndex[waitTrigsEnum.Current.Key]))
+ {
+ CloseWaitingProcess(waitTrigsEnum.Current.Key);
+ waitTrigsEnum = _waitingTriggers.GetEnumerator();
+ }
+ }
+
+ ProcessIndex outer, inner;
+ outer.seg = inner.seg = Segment.Update;
+
+ for (outer.i = inner.i = 0; outer.i < _nextUpdateProcessSlot; outer.i++)
+ {
+ if (UpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ UpdateProcesses[inner.i] = UpdateProcesses[outer.i];
+ UpdatePaused[inner.i] = UpdatePaused[outer.i];
+ UpdateHeld[inner.i] = UpdateHeld[outer.i];
+
+ if (_indexToHandle.ContainsKey(inner))
+ {
+ RemoveTag(_indexToHandle[inner]);
+ _handleToIndex.Remove(_indexToHandle[inner]);
+ _indexToHandle.Remove(inner);
+ }
+
+ _handleToIndex[_indexToHandle[outer]] = inner;
+ _indexToHandle.Add(inner, _indexToHandle[outer]);
+ _indexToHandle.Remove(outer);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextUpdateProcessSlot; outer.i++)
+ {
+ UpdateProcesses[outer.i] = null;
+ UpdatePaused[outer.i] = false;
+ UpdateHeld[outer.i] = false;
+
+ if (_indexToHandle.ContainsKey(outer))
+ {
+ RemoveTag(_indexToHandle[outer]);
+
+ _handleToIndex.Remove(_indexToHandle[outer]);
+ _indexToHandle.Remove(outer);
+ }
+ }
+
+ _lastUpdateProcessSlot -= _nextUpdateProcessSlot - inner.i;
+ UpdateCoroutines = _nextUpdateProcessSlot = inner.i;
+
+ outer.seg = inner.seg = Segment.FixedUpdate;
+ for (outer.i = inner.i = 0; outer.i < _nextFixedUpdateProcessSlot; outer.i++)
+ {
+ if (FixedUpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ FixedUpdateProcesses[inner.i] = FixedUpdateProcesses[outer.i];
+ FixedUpdatePaused[inner.i] = FixedUpdatePaused[outer.i];
+ FixedUpdateHeld[inner.i] = FixedUpdateHeld[outer.i];
+
+ if (_indexToHandle.ContainsKey(inner))
+ {
+ RemoveTag(_indexToHandle[inner]);
+ _handleToIndex.Remove(_indexToHandle[inner]);
+ _indexToHandle.Remove(inner);
+ }
+
+ _handleToIndex[_indexToHandle[outer]] = inner;
+ _indexToHandle.Add(inner, _indexToHandle[outer]);
+ _indexToHandle.Remove(outer);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextFixedUpdateProcessSlot; outer.i++)
+ {
+ FixedUpdateProcesses[outer.i] = null;
+ FixedUpdatePaused[outer.i] = false;
+ FixedUpdateHeld[outer.i] = false;
+
+ if (_indexToHandle.ContainsKey(outer))
+ {
+ RemoveTag(_indexToHandle[outer]);
+
+ _handleToIndex.Remove(_indexToHandle[outer]);
+ _indexToHandle.Remove(outer);
+ }
+ }
+
+ _lastFixedUpdateProcessSlot -= _nextFixedUpdateProcessSlot - inner.i;
+ FixedUpdateCoroutines = _nextFixedUpdateProcessSlot = inner.i;
+
+ outer.seg = inner.seg = Segment.LateUpdate;
+ for (outer.i = inner.i = 0; outer.i < _nextLateUpdateProcessSlot; outer.i++)
+ {
+ if (LateUpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ LateUpdateProcesses[inner.i] = LateUpdateProcesses[outer.i];
+ LateUpdatePaused[inner.i] = LateUpdatePaused[outer.i];
+ LateUpdateHeld[inner.i] = LateUpdateHeld[outer.i];
+
+ if (_indexToHandle.ContainsKey(inner))
+ {
+ RemoveTag(_indexToHandle[inner]);
+ _handleToIndex.Remove(_indexToHandle[inner]);
+ _indexToHandle.Remove(inner);
+ }
+
+ _handleToIndex[_indexToHandle[outer]] = inner;
+ _indexToHandle.Add(inner, _indexToHandle[outer]);
+ _indexToHandle.Remove(outer);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextLateUpdateProcessSlot; outer.i++)
+ {
+ LateUpdateProcesses[outer.i] = null;
+ LateUpdatePaused[outer.i] = false;
+ LateUpdateHeld[outer.i] = false;
+
+ if (_indexToHandle.ContainsKey(outer))
+ {
+ RemoveTag(_indexToHandle[outer]);
+
+ _handleToIndex.Remove(_indexToHandle[outer]);
+ _indexToHandle.Remove(outer);
+ }
+ }
+
+ _lastLateUpdateProcessSlot -= _nextLateUpdateProcessSlot - inner.i;
+ LateUpdateCoroutines = _nextLateUpdateProcessSlot = inner.i;
+
+ outer.seg = inner.seg = Segment.SlowUpdate;
+ for (outer.i = inner.i = 0; outer.i < _nextSlowUpdateProcessSlot; outer.i++)
+ {
+ if (SlowUpdateProcesses[outer.i] != null)
+ {
+ if (outer.i != inner.i)
+ {
+ SlowUpdateProcesses[inner.i] = SlowUpdateProcesses[outer.i];
+ SlowUpdatePaused[inner.i] = SlowUpdatePaused[outer.i];
+ SlowUpdateHeld[inner.i] = SlowUpdateHeld[outer.i];
+
+ if (_indexToHandle.ContainsKey(inner))
+ {
+ RemoveTag(_indexToHandle[inner]);
+ _handleToIndex.Remove(_indexToHandle[inner]);
+ _indexToHandle.Remove(inner);
+ }
+
+ _handleToIndex[_indexToHandle[outer]] = inner;
+ _indexToHandle.Add(inner, _indexToHandle[outer]);
+ _indexToHandle.Remove(outer);
+ }
+ inner.i++;
+ }
+ }
+ for (outer.i = inner.i; outer.i < _nextSlowUpdateProcessSlot; outer.i++)
+ {
+ SlowUpdateProcesses[outer.i] = null;
+ SlowUpdatePaused[outer.i] = false;
+ SlowUpdateHeld[outer.i] = false;
+
+ if (_indexToHandle.ContainsKey(outer))
+ {
+ RemoveTag(_indexToHandle[outer]);
+
+ _handleToIndex.Remove(_indexToHandle[outer]);
+ _indexToHandle.Remove(outer);
+ }
+ }
+
+ _lastSlowUpdateProcessSlot -= _nextSlowUpdateProcessSlot - inner.i;
+ SlowUpdateCoroutines = _nextSlowUpdateProcessSlot = inner.i;
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, Segment.Update, null, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used for Kill operations.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, Segment.Update, tag, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="segment">The segment that the coroutine should run in.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment segment)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, segment, null, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="segment">The segment that the coroutine should run in.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used for Kill operations.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment segment, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : Instance.RunCoroutineInternal(coroutine, segment, tag, new CoroutineHandle(Instance._instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, Segment.Update, null, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used for Kill operations.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, Segment.Update, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="segment">The segment that the coroutine should run in.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment segment)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, segment, null, new CoroutineHandle(_instanceID), true);
+ }
+
+ /// <summary>
+ /// Run a new coroutine on this Timing instance.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="segment">The segment that the coroutine should run in.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used for Kill operations.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment segment, string tag)
+ {
+ return coroutine == null ? new CoroutineHandle()
+ : RunCoroutineInternal(coroutine, segment, tag, new CoroutineHandle(_instanceID), true);
+ }
+
+
+ private CoroutineHandle RunCoroutineInternal(IEnumerator<float> coroutine, Segment segment, string tag, CoroutineHandle handle, bool prewarm)
+ {
+ ProcessIndex slot = new ProcessIndex { seg = segment };
+
+ if (_handleToIndex.ContainsKey(handle))
+ {
+ _indexToHandle.Remove(_handleToIndex[handle]);
+ _handleToIndex.Remove(handle);
+ }
+
+ float currentLocalTime = localTime;
+ float currentDeltaTime = deltaTime;
+ CoroutineHandle cachedHandle = currentCoroutine;
+ currentCoroutine = handle;
+
+ switch (segment)
+ {
+ case Segment.Update:
+
+ if (_nextUpdateProcessSlot >= UpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = UpdateProcesses;
+ bool[] oldPausedArray = UpdatePaused;
+ bool[] oldHeldArray = UpdateHeld;
+
+ UpdateProcesses = new IEnumerator<float>[UpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ UpdatePaused = new bool[UpdateProcesses.Length];
+ UpdateHeld = new bool[UpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ UpdateProcesses[i] = oldProcArray[i];
+ UpdatePaused[i] = oldPausedArray[i];
+ UpdateHeld[i] = oldHeldArray[i];
+ }
+ }
+
+ if (UpdateTimeValues(slot.seg))
+ _lastUpdateProcessSlot = _nextUpdateProcessSlot;
+
+ slot.i = _nextUpdateProcessSlot++;
+ UpdateProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, handle);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ while (prewarm)
+ {
+ if (!UpdateProcesses[slot.i].MoveNext())
+ {
+ if (_indexToHandle.ContainsKey(slot))
+ KillCoroutinesOnInstance(_indexToHandle[slot]);
+
+ prewarm = false;
+ }
+ else if (UpdateProcesses[slot.i] != null && float.IsNaN(UpdateProcesses[slot.i].Current))
+ {
+ if (ReplacementFunction != null)
+ {
+ UpdateProcesses[slot.i] = ReplacementFunction(UpdateProcesses[slot.i], _indexToHandle[slot]);
+ ReplacementFunction = null;
+ }
+ prewarm = !UpdatePaused[slot.i] && !UpdateHeld[slot.i];
+ }
+ else
+ {
+ prewarm = false;
+ }
+ }
+
+ break;
+
+ case Segment.FixedUpdate:
+
+ if (_nextFixedUpdateProcessSlot >= FixedUpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = FixedUpdateProcesses;
+ bool[] oldPausedArray = FixedUpdatePaused;
+ bool[] oldHeldArray = FixedUpdateHeld;
+
+ FixedUpdateProcesses = new IEnumerator<float>[FixedUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ FixedUpdatePaused = new bool[FixedUpdateProcesses.Length];
+ FixedUpdateHeld = new bool[FixedUpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ FixedUpdateProcesses[i] = oldProcArray[i];
+ FixedUpdatePaused[i] = oldPausedArray[i];
+ FixedUpdateHeld[i] = oldHeldArray[i];
+ }
+ }
+
+ if (UpdateTimeValues(slot.seg))
+ _lastFixedUpdateProcessSlot = _nextFixedUpdateProcessSlot;
+
+ slot.i = _nextFixedUpdateProcessSlot++;
+ FixedUpdateProcesses[slot.i] = coroutine;
+
+ if (null != tag)
+ AddTag(tag, handle);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ while (prewarm)
+ {
+ if (!FixedUpdateProcesses[slot.i].MoveNext())
+ {
+ if (_indexToHandle.ContainsKey(slot))
+ KillCoroutinesOnInstance(_indexToHandle[slot]);
+
+ prewarm = false;
+ }
+ else if (FixedUpdateProcesses[slot.i] != null && float.IsNaN(FixedUpdateProcesses[slot.i].Current))
+ {
+ if (ReplacementFunction != null)
+ {
+ FixedUpdateProcesses[slot.i] = ReplacementFunction(FixedUpdateProcesses[slot.i], _indexToHandle[slot]);
+ ReplacementFunction = null;
+ }
+ prewarm = !FixedUpdatePaused[slot.i] && !FixedUpdateHeld[slot.i];
+ }
+ else
+ {
+ prewarm = false;
+ }
+ }
+
+ break;
+
+ case Segment.LateUpdate:
+
+ if (_nextLateUpdateProcessSlot >= LateUpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = LateUpdateProcesses;
+ bool[] oldPausedArray = LateUpdatePaused;
+ bool[] oldHeldArray = LateUpdateHeld;
+
+ LateUpdateProcesses = new IEnumerator<float>[LateUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ LateUpdatePaused = new bool[LateUpdateProcesses.Length];
+ LateUpdateHeld = new bool[LateUpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ LateUpdateProcesses[i] = oldProcArray[i];
+ LateUpdatePaused[i] = oldPausedArray[i];
+ LateUpdateHeld[i] = oldHeldArray[i];
+ }
+ }
+
+ if (UpdateTimeValues(slot.seg))
+ _lastLateUpdateProcessSlot = _nextLateUpdateProcessSlot;
+
+ slot.i = _nextLateUpdateProcessSlot++;
+ LateUpdateProcesses[slot.i] = coroutine;
+
+ if (tag != null)
+ AddTag(tag, handle);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ while (prewarm)
+ {
+ if (!LateUpdateProcesses[slot.i].MoveNext())
+ {
+ if (_indexToHandle.ContainsKey(slot))
+ KillCoroutinesOnInstance(_indexToHandle[slot]);
+
+ prewarm = false;
+ }
+ else if (LateUpdateProcesses[slot.i] != null && float.IsNaN(LateUpdateProcesses[slot.i].Current))
+ {
+ if (ReplacementFunction != null)
+ {
+ LateUpdateProcesses[slot.i] = ReplacementFunction(LateUpdateProcesses[slot.i], _indexToHandle[slot]);
+ ReplacementFunction = null;
+ }
+ prewarm = !LateUpdatePaused[slot.i] && !LateUpdateHeld[slot.i];
+ }
+ else
+ {
+ prewarm = false;
+ }
+ }
+
+ break;
+
+ case Segment.SlowUpdate:
+
+ if (_nextSlowUpdateProcessSlot >= SlowUpdateProcesses.Length)
+ {
+ IEnumerator<float>[] oldProcArray = SlowUpdateProcesses;
+ bool[] oldPausedArray = SlowUpdatePaused;
+ bool[] oldHeldArray = SlowUpdateHeld;
+
+ SlowUpdateProcesses = new IEnumerator<float>[SlowUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)];
+ SlowUpdatePaused = new bool[SlowUpdateProcesses.Length];
+ SlowUpdateHeld = new bool[SlowUpdateProcesses.Length];
+
+ for (int i = 0; i < oldProcArray.Length; i++)
+ {
+ SlowUpdateProcesses[i] = oldProcArray[i];
+ SlowUpdatePaused[i] = oldPausedArray[i];
+ SlowUpdateHeld[i] = oldHeldArray[i];
+ }
+ }
+
+ if (UpdateTimeValues(slot.seg))
+ _lastSlowUpdateProcessSlot = _nextSlowUpdateProcessSlot;
+
+ slot.i = _nextSlowUpdateProcessSlot++;
+ SlowUpdateProcesses[slot.i] = coroutine;
+
+ if (tag != null)
+ AddTag(tag, handle);
+
+ _indexToHandle.Add(slot, handle);
+ _handleToIndex.Add(handle, slot);
+
+ while (prewarm)
+ {
+ if (!SlowUpdateProcesses[slot.i].MoveNext())
+ {
+ if (_indexToHandle.ContainsKey(slot))
+ KillCoroutinesOnInstance(_indexToHandle[slot]);
+
+ prewarm = false;
+ }
+ else if (SlowUpdateProcesses[slot.i] != null && float.IsNaN(SlowUpdateProcesses[slot.i].Current))
+ {
+ if (ReplacementFunction != null)
+ {
+ SlowUpdateProcesses[slot.i] = ReplacementFunction(SlowUpdateProcesses[slot.i], _indexToHandle[slot]);
+ ReplacementFunction = null;
+ }
+ prewarm = !SlowUpdatePaused[slot.i] && !SlowUpdateHeld[slot.i];
+ }
+ else
+ {
+ prewarm = false;
+ }
+ }
+
+ break;
+
+ default:
+ handle = new CoroutineHandle();
+ break;
+ }
+
+ localTime = currentLocalTime;
+ deltaTime = currentDeltaTime;
+ currentCoroutine = cachedHandle;
+
+ return handle;
+ }
+
+ /// <summary>
+ /// This will kill all coroutines running on the main MEC instance and reset the context.
+ /// NOTE: If you call this function from within a running coroutine then you MUST end the current
+ /// coroutine. If the running coroutine has more work to do you may run a new "part 2" coroutine
+ /// function to complete the task before ending the current one.
+ /// </summary>
+ /// <returns>The number of coroutines that were killed.</returns>
+ public static int KillCoroutines()
+ {
+ return _instance == null ? 0 : _instance.KillCoroutinesOnInstance();
+ }
+
+ /// <summary>
+ /// This will kill all coroutines running on the current MEC instance and reset the context.
+ /// NOTE: If you call this function from within a running coroutine then you MUST end the current
+ /// coroutine. If the running coroutine has more work to do you may run a new "part 2" coroutine
+ /// function to complete the task before ending the current one.
+ /// </summary>
+ /// <returns>The number of coroutines that were killed.</returns>
+ public int KillCoroutinesOnInstance()
+ {
+ int retVal = _nextUpdateProcessSlot + _nextLateUpdateProcessSlot + _nextFixedUpdateProcessSlot + _nextSlowUpdateProcessSlot;
+
+ UpdateProcesses = new IEnumerator<float>[InitialBufferSizeLarge];
+ UpdatePaused = new bool[InitialBufferSizeLarge];
+ UpdateHeld = new bool[InitialBufferSizeLarge];
+ UpdateCoroutines = 0;
+ _nextUpdateProcessSlot = 0;
+
+ LateUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall];
+ LateUpdatePaused = new bool[InitialBufferSizeSmall];
+ LateUpdateHeld = new bool[InitialBufferSizeSmall];
+ LateUpdateCoroutines = 0;
+ _nextLateUpdateProcessSlot = 0;
+
+ FixedUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
+ FixedUpdatePaused = new bool[InitialBufferSizeMedium];
+ FixedUpdateHeld = new bool[InitialBufferSizeMedium];
+ FixedUpdateCoroutines = 0;
+ _nextFixedUpdateProcessSlot = 0;
+
+ SlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium];
+ SlowUpdatePaused = new bool[InitialBufferSizeMedium];
+ SlowUpdateHeld = new bool[InitialBufferSizeMedium];
+ SlowUpdateCoroutines = 0;
+ _nextSlowUpdateProcessSlot = 0;
+
+ _processTags.Clear();
+ _taggedProcesses.Clear();
+ _handleToIndex.Clear();
+ _indexToHandle.Clear();
+ _waitingTriggers.Clear();
+ _expansions = (ushort)((_expansions / 2) + 1);
+
+ return retVal;
+ }
+
+ /// <summary>
+ /// Kills the instances of the coroutine handle if it exists.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to kill.</param>
+ /// <returns>The number of coroutines that were found and killed (0 or 1).</returns>
+ public static int KillCoroutines(CoroutineHandle handle)
+ {
+ return ActiveInstances[handle.Key] != null ? GetInstance(handle.Key).KillCoroutinesOnInstance(handle) : 0;
+ }
+
+ /// <summary>
+ /// Kills the instance of the coroutine handle on this Timing instance if it exists.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to kill.</param>
+ /// <returns>The number of coroutines that were found and killed (0 or 1).</returns>
+ public int KillCoroutinesOnInstance(CoroutineHandle handle)
+ {
+ bool foundOne = false;
+
+ if (_handleToIndex.ContainsKey(handle))
+ {
+ if (_waitingTriggers.ContainsKey(handle))
+ CloseWaitingProcess(handle);
+
+ foundOne = CoindexExtract(_handleToIndex[handle]) != null;
+ RemoveTag(handle);
+ }
+
+ return foundOne ? 1 : 0;
+ }
+
+ /// <summary>
+ /// Kills all coroutines that have the given tag.
+ /// </summary>
+ /// <param name="tag">All coroutines with this tag will be killed.</param>
+ /// <returns>The number of coroutines that were found and killed.</returns>
+ public static int KillCoroutines(string tag)
+ {
+ return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(tag);
+ }
+
+ /// <summary>
+ /// Kills all coroutines that have the given tag.
+ /// </summary>
+ /// <param name="tag">All coroutines with this tag will be killed.</param>
+ /// <returns>The number of coroutines that were found and killed.</returns>
+ public int KillCoroutinesOnInstance(string tag)
+ {
+ if (tag == null) return 0;
+ int numberFound = 0;
+
+ while (_taggedProcesses.ContainsKey(tag))
+ {
+ var matchEnum = _taggedProcesses[tag].GetEnumerator();
+ matchEnum.MoveNext();
+
+ if (Nullify(_handleToIndex[matchEnum.Current]))
+ {
+ if (_waitingTriggers.ContainsKey(matchEnum.Current))
+ CloseWaitingProcess(matchEnum.Current);
+
+ numberFound++;
+ }
+
+ RemoveTag(matchEnum.Current);
+
+ if (_handleToIndex.ContainsKey(matchEnum.Current))
+ {
+ _indexToHandle.Remove(_handleToIndex[matchEnum.Current]);
+ _handleToIndex.Remove(matchEnum.Current);
+ }
+ }
+
+ return numberFound;
+ }
+
+ /// <summary>
+ /// This will pause all coroutines running on the current MEC instance until ResumeCoroutines is called.
+ /// </summary>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public static int PauseCoroutines()
+ {
+ return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance();
+ }
+
+ /// <summary>
+ /// This will pause all coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
+ /// </summary>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public int PauseCoroutinesOnInstance()
+ {
+ int count = 0;
+ int i;
+ for (i = 0; i < _nextUpdateProcessSlot; i++)
+ {
+ if (!UpdatePaused[i] && UpdateProcesses[i] != null)
+ {
+ count++;
+ UpdatePaused[i] = true;
+
+ if (UpdateProcesses[i].Current > GetSegmentTime(Segment.Update))
+ UpdateProcesses[i] = _InjectDelay(UpdateProcesses[i],
+ UpdateProcesses[i].Current - GetSegmentTime(Segment.Update));
+ }
+ }
+
+ for (i = 0; i < _nextLateUpdateProcessSlot; i++)
+ {
+ if (!LateUpdatePaused[i] && LateUpdateProcesses[i] != null)
+ {
+ count++;
+ LateUpdatePaused[i] = true;
+
+ if (LateUpdateProcesses[i].Current > GetSegmentTime(Segment.LateUpdate))
+ LateUpdateProcesses[i] = _InjectDelay(LateUpdateProcesses[i],
+ LateUpdateProcesses[i].Current - GetSegmentTime(Segment.LateUpdate));
+ }
+ }
+
+ for (i = 0; i < _nextFixedUpdateProcessSlot; i++)
+ {
+ if (!FixedUpdatePaused[i] && FixedUpdateProcesses[i] != null)
+ {
+ count++;
+ FixedUpdatePaused[i] = true;
+
+ if (FixedUpdateProcesses[i].Current > GetSegmentTime(Segment.FixedUpdate))
+ FixedUpdateProcesses[i] = _InjectDelay(FixedUpdateProcesses[i],
+ FixedUpdateProcesses[i].Current - GetSegmentTime(Segment.FixedUpdate));
+ }
+ }
+
+ for (i = 0; i < _nextSlowUpdateProcessSlot; i++)
+ {
+ if (!SlowUpdatePaused[i] && SlowUpdateProcesses[i] != null)
+ {
+ count++;
+ SlowUpdatePaused[i] = true;
+
+ if (SlowUpdateProcesses[i].Current > GetSegmentTime(Segment.SlowUpdate))
+ SlowUpdateProcesses[i] = _InjectDelay(SlowUpdateProcesses[i],
+ SlowUpdateProcesses[i].Current - GetSegmentTime(Segment.SlowUpdate));
+ }
+ }
+
+ return count;
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines until ResumeCoroutines is called.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to pause.</param>
+ /// <returns>The number of coroutines that were paused (0 or 1).</returns>
+ public static int PauseCoroutines(CoroutineHandle handle)
+ {
+ return ActiveInstances[handle.Key] != null ? GetInstance(handle.Key).PauseCoroutinesOnInstance(handle) : 0;
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to pause.</param>
+ /// <returns>The number of coroutines that were paused (0 or 1).</returns>
+ public int PauseCoroutinesOnInstance(CoroutineHandle handle)
+ {
+ return _handleToIndex.ContainsKey(handle) && !CoindexIsNull(_handleToIndex[handle]) && !SetPause(_handleToIndex[handle], true) ? 1 : 0;
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines running on the current MEC instance until ResumeCoroutines is called.
+ /// </summary>
+ /// <param name="tag">Any coroutines with a matching tag will be paused.</param>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public static int PauseCoroutines(string tag)
+ {
+ return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(tag);
+ }
+
+ /// <summary>
+ /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called.
+ /// </summary>
+ /// <param name="tag">Any coroutines with a matching tag will be paused.</param>
+ /// <returns>The number of coroutines that were paused.</returns>
+ public int PauseCoroutinesOnInstance(string tag)
+ {
+ if (tag == null || !_taggedProcesses.ContainsKey(tag))
+ return 0;
+
+ int count = 0;
+ var matchesEnum = _taggedProcesses[tag].GetEnumerator();
+
+ while (matchesEnum.MoveNext())
+ if (!CoindexIsNull(_handleToIndex[matchesEnum.Current]) && !SetPause(_handleToIndex[matchesEnum.Current], true))
+ count++;
+
+ return count;
+ }
+
+ /// <summary>
+ /// This resumes all coroutines on the current MEC instance if they are currently paused, otherwise it has
+ /// no effect.
+ /// </summary>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public static int ResumeCoroutines()
+ {
+ return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance();
+ }
+
+ /// <summary>
+ /// This resumes all coroutines on this MEC instance if they are currently paused, otherwise it has no effect.
+ /// </summary>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public int ResumeCoroutinesOnInstance()
+ {
+ int count = 0;
+ ProcessIndex coindex;
+ for (coindex.i = 0, coindex.seg = Segment.Update; coindex.i < _nextUpdateProcessSlot; coindex.i++)
+ {
+ if (UpdatePaused[coindex.i] && UpdateProcesses[coindex.i] != null)
+ {
+ UpdatePaused[coindex.i] = false;
+ count++;
+ }
+ }
+
+ for (coindex.i = 0, coindex.seg = Segment.LateUpdate; coindex.i < _nextLateUpdateProcessSlot; coindex.i++)
+ {
+ if (LateUpdatePaused[coindex.i] && LateUpdateProcesses[coindex.i] != null)
+ {
+ LateUpdatePaused[coindex.i] = false;
+ count++;
+ }
+ }
+
+ for (coindex.i = 0, coindex.seg = Segment.FixedUpdate; coindex.i < _nextFixedUpdateProcessSlot; coindex.i++)
+ {
+ if (FixedUpdatePaused[coindex.i] && FixedUpdateProcesses[coindex.i] != null)
+ {
+ FixedUpdatePaused[coindex.i] = false;
+ count++;
+ }
+ }
+
+ for (coindex.i = 0, coindex.seg = Segment.SlowUpdate; coindex.i < _nextSlowUpdateProcessSlot; coindex.i++)
+ {
+ if (SlowUpdatePaused[coindex.i] && SlowUpdateProcesses[coindex.i] != null)
+ {
+ SlowUpdatePaused[coindex.i] = false;
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ /// <summary>
+ /// This will resume any matching coroutines.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to resume.</param>
+ /// <returns>The number of coroutines that were resumed (0 or 1).</returns>
+ public static int ResumeCoroutines(CoroutineHandle handle)
+ {
+ return ActiveInstances[handle.Key] != null ? GetInstance(handle.Key).ResumeCoroutinesOnInstance(handle) : 0;
+ }
+
+ /// <summary>
+ /// This will resume any matching coroutines running on this MEC instance.
+ /// </summary>
+ /// <param name="handle">The handle of the coroutine to resume.</param>
+ /// <returns>The number of coroutines that were resumed (0 or 1).</returns>
+ public int ResumeCoroutinesOnInstance(CoroutineHandle handle)
+ {
+ return _handleToIndex.ContainsKey(handle) &&
+ !CoindexIsNull(_handleToIndex[handle]) && SetPause(_handleToIndex[handle], false) ? 1 : 0;
+ }
+
+ /// <summary>
+ /// This resumes any matching coroutines on the current MEC instance if they are currently paused, otherwise it has
+ /// no effect.
+ /// </summary>
+ /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public static int ResumeCoroutines(string tag)
+ {
+ return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(tag);
+ }
+
+ /// <summary>
+ /// This resumes any matching coroutines on this MEC instance if they are currently paused, otherwise it has no effect.
+ /// </summary>
+ /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param>
+ /// <returns>The number of coroutines that were resumed.</returns>
+ public int ResumeCoroutinesOnInstance(string tag)
+ {
+ if (tag == null || !_taggedProcesses.ContainsKey(tag))
+ return 0;
+ int count = 0;
+
+ var indexesEnum = _taggedProcesses[tag].GetEnumerator();
+ while (indexesEnum.MoveNext())
+ {
+ if (!CoindexIsNull(_handleToIndex[indexesEnum.Current]) && SetPause(_handleToIndex[indexesEnum.Current], false))
+ {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ private bool UpdateTimeValues(Segment segment)
+ {
+ switch(segment)
+ {
+ case Segment.Update:
+ if (_currentUpdateFrame != Time.frameCount)
+ {
+ deltaTime = Time.deltaTime;
+ _lastUpdateTime += deltaTime;
+ localTime = _lastUpdateTime;
+ _currentUpdateFrame = Time.frameCount;
+ return true;
+ }
+ else
+ {
+ deltaTime = Time.deltaTime;
+ localTime = _lastUpdateTime;
+ return false;
+ }
+ case Segment.LateUpdate:
+ if (_currentLateUpdateFrame != Time.frameCount)
+ {
+ deltaTime = Time.deltaTime;
+ _lastLateUpdateTime += deltaTime;
+ localTime = _lastLateUpdateTime;
+ _currentLateUpdateFrame = Time.frameCount;
+ return true;
+ }
+ else
+ {
+ deltaTime = Time.deltaTime;
+ localTime = _lastLateUpdateTime;
+ return false;
+ }
+ case Segment.FixedUpdate:
+ deltaTime = Time.fixedDeltaTime;
+ localTime = Time.fixedTime;
+
+ if (_lastFixedUpdateTime + 0.0001f < Time.fixedTime)
+ {
+ _lastFixedUpdateTime = Time.fixedTime;
+ return true;
+ }
+
+ return false;
+ case Segment.SlowUpdate:
+ if (_currentSlowUpdateFrame != Time.frameCount)
+ {
+ deltaTime = _lastSlowUpdateDeltaTime = Time.realtimeSinceStartup - _lastSlowUpdateTime;
+ localTime = _lastSlowUpdateTime = Time.realtimeSinceStartup;
+ _currentSlowUpdateFrame = Time.frameCount;
+ return true;
+ }
+ else
+ {
+ deltaTime = _lastSlowUpdateDeltaTime;
+ localTime = _lastSlowUpdateTime;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private float GetSegmentTime(Segment segment)
+ {
+ switch (segment)
+ {
+ case Segment.Update:
+ if (_currentUpdateFrame == Time.frameCount)
+ return _lastUpdateTime;
+ else
+ return _lastUpdateTime + Time.deltaTime;
+ case Segment.LateUpdate:
+ if (_currentUpdateFrame == Time.frameCount)
+ return _lastLateUpdateTime;
+ else
+ return _lastLateUpdateTime + Time.deltaTime;
+ case Segment.FixedUpdate:
+ return Time.fixedTime;
+ case Segment.SlowUpdate:
+ return Time.realtimeSinceStartup;
+ default:
+ return 0f;
+ }
+ }
+
+ /// <summary>
+ /// Retrieves the MEC manager that corresponds to the supplied instance id.
+ /// </summary>
+ /// <param name="ID">The instance ID.</param>
+ /// <returns>The manager, or null if not found.</returns>
+ public static Timing GetInstance(byte ID)
+ {
+ if (ID >= 0x10)
+ return null;
+ return ActiveInstances[ID];
+ }
+
+ private void AddTag(string tag, CoroutineHandle coindex)
+ {
+ _processTags.Add(coindex, tag);
+
+ if (_taggedProcesses.ContainsKey(tag))
+ _taggedProcesses[tag].Add(coindex);
+ else
+ _taggedProcesses.Add(tag, new HashSet<CoroutineHandle> { coindex });
+ }
+
+ private void RemoveTag(CoroutineHandle coindex)
+ {
+ if (_processTags.ContainsKey(coindex))
+ {
+ if (_taggedProcesses[_processTags[coindex]].Count > 1)
+ _taggedProcesses[_processTags[coindex]].Remove(coindex);
+ else
+ _taggedProcesses.Remove(_processTags[coindex]);
+
+ _processTags.Remove(coindex);
+ }
+ }
+
+ /// <returns>Whether it was already null.</returns>
+ private bool Nullify(ProcessIndex coindex)
+ {
+ bool retVal;
+
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ retVal = UpdateProcesses[coindex.i] != null;
+ UpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.FixedUpdate:
+ retVal = FixedUpdateProcesses[coindex.i] != null;
+ FixedUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.LateUpdate:
+ retVal = LateUpdateProcesses[coindex.i] != null;
+ LateUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.SlowUpdate:
+ retVal = SlowUpdateProcesses[coindex.i] != null;
+ SlowUpdateProcesses[coindex.i] = null;
+ return retVal;
+ default:
+ return false;
+ }
+ }
+
+ private IEnumerator<float> CoindexExtract(ProcessIndex coindex)
+ {
+ IEnumerator<float> retVal;
+
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ retVal = UpdateProcesses[coindex.i];
+ UpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.FixedUpdate:
+ retVal = FixedUpdateProcesses[coindex.i];
+ FixedUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.LateUpdate:
+ retVal = LateUpdateProcesses[coindex.i];
+ LateUpdateProcesses[coindex.i] = null;
+ return retVal;
+ case Segment.SlowUpdate:
+ retVal = SlowUpdateProcesses[coindex.i];
+ SlowUpdateProcesses[coindex.i] = null;
+ return retVal;
+ default:
+ return null;
+ }
+ }
+
+ private IEnumerator<float> CoindexPeek(ProcessIndex coindex)
+ {
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ return UpdateProcesses[coindex.i];
+ case Segment.FixedUpdate:
+ return FixedUpdateProcesses[coindex.i];
+ case Segment.LateUpdate:
+ return LateUpdateProcesses[coindex.i];
+ case Segment.SlowUpdate:
+ return SlowUpdateProcesses[coindex.i];
+ default:
+ return null;
+ }
+ }
+
+ private bool CoindexIsNull(ProcessIndex coindex)
+ {
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ return UpdateProcesses[coindex.i] == null;
+ case Segment.FixedUpdate:
+ return FixedUpdateProcesses[coindex.i] == null;
+ case Segment.LateUpdate:
+ return LateUpdateProcesses[coindex.i] == null;
+ case Segment.SlowUpdate:
+ return SlowUpdateProcesses[coindex.i] == null;
+ default:
+ return true;
+ }
+ }
+
+ private bool SetPause(ProcessIndex coindex, bool newPausedState)
+ {
+ if (CoindexPeek(coindex) == null)
+ return false;
+
+ bool isPaused;
+
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ isPaused = UpdatePaused[coindex.i];
+ UpdatePaused[coindex.i] = newPausedState;
+
+ if (newPausedState && UpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
+ UpdateProcesses[coindex.i] = _InjectDelay(UpdateProcesses[coindex.i],
+ UpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
+
+ return isPaused;
+ case Segment.FixedUpdate:
+ isPaused = FixedUpdatePaused[coindex.i];
+ FixedUpdatePaused[coindex.i] = newPausedState;
+
+ if (newPausedState && FixedUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
+ FixedUpdateProcesses[coindex.i] = _InjectDelay(FixedUpdateProcesses[coindex.i],
+ FixedUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
+
+ return isPaused;
+ case Segment.LateUpdate:
+ isPaused = LateUpdatePaused[coindex.i];
+ LateUpdatePaused[coindex.i] = newPausedState;
+
+ if (newPausedState && LateUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
+ LateUpdateProcesses[coindex.i] = _InjectDelay(LateUpdateProcesses[coindex.i],
+ LateUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
+
+ return isPaused;
+ case Segment.SlowUpdate:
+ isPaused = SlowUpdatePaused[coindex.i];
+ SlowUpdatePaused[coindex.i] = newPausedState;
+
+ if (newPausedState && SlowUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
+ SlowUpdateProcesses[coindex.i] = _InjectDelay(SlowUpdateProcesses[coindex.i],
+ SlowUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
+
+ return isPaused;
+ default:
+ return false;
+ }
+ }
+
+ private bool SetHeld(ProcessIndex coindex, bool newHeldState)
+ {
+ if (CoindexPeek(coindex) == null)
+ return false;
+
+ bool isHeld;
+
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ isHeld = UpdateHeld[coindex.i];
+ UpdateHeld[coindex.i] = newHeldState;
+
+ if (newHeldState && UpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
+ UpdateProcesses[coindex.i] = _InjectDelay(UpdateProcesses[coindex.i],
+ UpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
+
+ return isHeld;
+ case Segment.FixedUpdate:
+ isHeld = FixedUpdateHeld[coindex.i];
+ FixedUpdateHeld[coindex.i] = newHeldState;
+
+ if (newHeldState && FixedUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
+ FixedUpdateProcesses[coindex.i] = _InjectDelay(FixedUpdateProcesses[coindex.i],
+ FixedUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
+
+ return isHeld;
+ case Segment.LateUpdate:
+ isHeld = LateUpdateHeld[coindex.i];
+ LateUpdateHeld[coindex.i] = newHeldState;
+
+ if (newHeldState && LateUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
+ LateUpdateProcesses[coindex.i] = _InjectDelay(LateUpdateProcesses[coindex.i],
+ LateUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
+
+ return isHeld;
+ case Segment.SlowUpdate:
+ isHeld = SlowUpdateHeld[coindex.i];
+ SlowUpdateHeld[coindex.i] = newHeldState;
+
+ if (newHeldState && SlowUpdateProcesses[coindex.i].Current > GetSegmentTime(coindex.seg))
+ SlowUpdateProcesses[coindex.i] = _InjectDelay(SlowUpdateProcesses[coindex.i],
+ SlowUpdateProcesses[coindex.i].Current - GetSegmentTime(coindex.seg));
+
+ return isHeld;
+ default:
+ return false;
+ }
+ }
+
+ private IEnumerator<float> _InjectDelay(IEnumerator<float> proc, float delayTime)
+ {
+ yield return WaitForSecondsOnInstance(delayTime);
+
+ _tmpRef = proc;
+ ReplacementFunction = ReturnTmpRefForRepFunc;
+ yield return float.NaN;
+ }
+
+ private bool CoindexIsPaused(ProcessIndex coindex)
+ {
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ return UpdatePaused[coindex.i];
+ case Segment.FixedUpdate:
+ return FixedUpdatePaused[coindex.i];
+ case Segment.LateUpdate:
+ return LateUpdatePaused[coindex.i];
+ case Segment.SlowUpdate:
+ return SlowUpdatePaused[coindex.i];
+ default:
+ return false;
+ }
+ }
+
+ private bool CoindexIsHeld(ProcessIndex coindex)
+ {
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ return UpdateHeld[coindex.i];
+ case Segment.FixedUpdate:
+ return FixedUpdateHeld[coindex.i];
+ case Segment.LateUpdate:
+ return LateUpdateHeld[coindex.i];
+ case Segment.SlowUpdate:
+ return SlowUpdateHeld[coindex.i];
+ default:
+ return false;
+ }
+ }
+
+ private void CoindexReplace(ProcessIndex coindex, IEnumerator<float> replacement)
+ {
+ switch (coindex.seg)
+ {
+ case Segment.Update:
+ UpdateProcesses[coindex.i] = replacement;
+ return;
+ case Segment.FixedUpdate:
+ FixedUpdateProcesses[coindex.i] = replacement;
+ return;
+ case Segment.LateUpdate:
+ LateUpdateProcesses[coindex.i] = replacement;
+ return;
+ case Segment.SlowUpdate:
+ SlowUpdateProcesses[coindex.i] = replacement;
+ return;
+ }
+ }
+
+ /// <summary>
+ /// Use "yield return Timing.WaitForSeconds(time);" to wait for the specified number of seconds.
+ /// </summary>
+ /// <param name="waitTime">Number of seconds to wait.</param>
+ public static float WaitForSeconds(float waitTime)
+ {
+ if (float.IsNaN(waitTime)) waitTime = 0f;
+ return LocalTime + waitTime;
+ }
+
+ /// <summary>
+ /// Use "yield return timingInstance.WaitForSecondsOnInstance(time);" to wait for the specified number of seconds.
+ /// </summary>
+ /// <param name="waitTime">Number of seconds to wait.</param>
+ public float WaitForSecondsOnInstance(float waitTime)
+ {
+ if (float.IsNaN(waitTime)) waitTime = 0f;
+ return localTime + waitTime;
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.WaitUntilDone(otherCoroutine);" to pause the current
+ /// coroutine until otherCoroutine is done.
+ /// </summary>
+ /// <param name="otherCoroutine">The coroutine to pause for.</param>
+ public static float WaitUntilDone(CoroutineHandle otherCoroutine)
+ {
+ return WaitUntilDone(otherCoroutine, true);
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.WaitUntilDone(otherCoroutine, false);" to pause the current
+ /// coroutine until otherCoroutine is done, supressing warnings.
+ /// </summary>
+ /// <param name="otherCoroutine">The coroutine to pause for.</param>
+ /// <param name="warnOnIssue">Post a warning to the console if no hold action was actually performed.</param>
+ public static float WaitUntilDone(CoroutineHandle otherCoroutine, bool warnOnIssue)
+ {
+ Timing inst = GetInstance(otherCoroutine.Key);
+
+ if (inst != null && inst._handleToIndex.ContainsKey(otherCoroutine))
+ {
+ if (inst.CoindexIsNull(inst._handleToIndex[otherCoroutine]))
+ return 0f;
+
+ if (!inst._waitingTriggers.ContainsKey(otherCoroutine))
+ {
+ inst.CoindexReplace(inst._handleToIndex[otherCoroutine],
+ inst._StartWhenDone(otherCoroutine, inst.CoindexPeek(inst._handleToIndex[otherCoroutine])));
+ inst._waitingTriggers.Add(otherCoroutine, new HashSet<CoroutineHandle>());
+ }
+
+ if (inst.currentCoroutine == otherCoroutine)
+ {
+ Assert.IsFalse(warnOnIssue, "A coroutine cannot wait for itself.");
+ return WaitForOneFrame;
+ }
+ if (!inst.currentCoroutine.IsValid)
+ {
+ Assert.IsFalse(warnOnIssue, "The two coroutines are not running on the same MEC instance.");
+ return WaitForOneFrame;
+ }
+
+ inst._waitingTriggers[otherCoroutine].Add(inst.currentCoroutine);
+ if (!inst._allWaiting.Contains(inst.currentCoroutine))
+ inst._allWaiting.Add(inst.currentCoroutine);
+ inst.SetHeld(inst._handleToIndex[inst.currentCoroutine], true);
+ inst.SwapToLast(otherCoroutine, inst.currentCoroutine);
+
+ return float.NaN;
+ }
+
+ Assert.IsFalse(warnOnIssue, "WaitUntilDone cannot hold: The coroutine handle that was passed in is invalid.\n" + otherCoroutine);
+ return WaitForOneFrame;
+ }
+
+ private IEnumerator<float> _StartWhenDone(CoroutineHandle handle, IEnumerator<float> proc)
+ {
+ if (!_waitingTriggers.ContainsKey(handle)) yield break;
+
+ try
+ {
+ if (proc.Current > localTime)
+ yield return proc.Current;
+
+ while (proc.MoveNext())
+ yield return proc.Current;
+ }
+ finally
+ {
+ CloseWaitingProcess(handle);
+ }
+ }
+
+ private void SwapToLast(CoroutineHandle firstHandle, CoroutineHandle lastHandle)
+ {
+ if (firstHandle.Key != lastHandle.Key)
+ return;
+
+ ProcessIndex firstIndex = _handleToIndex[firstHandle];
+ ProcessIndex lastIndex = _handleToIndex[lastHandle];
+
+ if (firstIndex.seg != lastIndex.seg || firstIndex.i < lastIndex.i)
+ return;
+
+ IEnumerator<float> tempCoptr = CoindexPeek(firstIndex);
+ CoindexReplace(firstIndex, CoindexPeek(lastIndex));
+ CoindexReplace(lastIndex, tempCoptr);
+
+ _indexToHandle[firstIndex] = lastHandle;
+ _indexToHandle[lastIndex] = firstHandle;
+ _handleToIndex[firstHandle] = lastIndex;
+ _handleToIndex[lastHandle] = firstIndex;
+ bool tmpB = SetPause(firstIndex, CoindexIsPaused(lastIndex));
+ SetPause(lastIndex, tmpB);
+ tmpB = SetHeld(firstIndex, CoindexIsHeld(lastIndex));
+ SetHeld(lastIndex, tmpB);
+
+ if (_waitingTriggers.ContainsKey(lastHandle))
+ {
+ var trigsEnum = _waitingTriggers[lastHandle].GetEnumerator();
+ while (trigsEnum.MoveNext())
+ SwapToLast(lastHandle, trigsEnum.Current);
+ }
+
+ if (_allWaiting.Contains(firstHandle))
+ {
+ var keyEnum = _waitingTriggers.GetEnumerator();
+ while (keyEnum.MoveNext())
+ {
+ var valueEnum = keyEnum.Current.Value.GetEnumerator();
+ while (valueEnum.MoveNext())
+ if (valueEnum.Current == firstHandle)
+ SwapToLast(keyEnum.Current.Key, firstHandle);
+ }
+ }
+ }
+
+ private void CloseWaitingProcess(CoroutineHandle handle)
+ {
+ if (!_waitingTriggers.ContainsKey(handle)) return;
+
+ var tasksEnum = _waitingTriggers[handle].GetEnumerator();
+ _waitingTriggers.Remove(handle);
+
+ while (tasksEnum.MoveNext())
+ {
+ if (_handleToIndex.ContainsKey(tasksEnum.Current) && !HandleIsInWaitingList(tasksEnum.Current))
+ {
+ SetHeld(_handleToIndex[tasksEnum.Current], false);
+ _allWaiting.Remove(tasksEnum.Current);
+ }
+ }
+ }
+
+ private bool HandleIsInWaitingList(CoroutineHandle handle)
+ {
+ var triggersEnum = _waitingTriggers.GetEnumerator();
+ while (triggersEnum.MoveNext())
+ if (triggersEnum.Current.Value.Contains(handle))
+ return true;
+
+ return false;
+ }
+
+ private static IEnumerator<float> ReturnTmpRefForRepFunc(IEnumerator<float> coptr, CoroutineHandle handle)
+ {
+ return _tmpRef as IEnumerator<float>;
+ }
+
+#if !UNITY_2018_3_OR_NEWER
+ /// <summary>
+ /// Use the command "yield return Timing.WaitUntilDone(wwwObject);" to pause the current
+ /// coroutine until the wwwObject is done.
+ /// </summary>
+ /// <param name="wwwObject">The www object to pause for.</param>
+ public static float WaitUntilDone(WWW wwwObject)
+ {
+ if (wwwObject == null || wwwObject.isDone) return 0f;
+
+ _tmpRef = wwwObject;
+ ReplacementFunction = WaitUntilDoneWwwHelper;
+ return float.NaN;
+ }
+
+
+ private static IEnumerator<float> WaitUntilDoneWwwHelper(IEnumerator<float> coptr, CoroutineHandle handle)
+ {
+ return _StartWhenDone(_tmpRef as WWW, coptr);
+ }
+
+ private static IEnumerator<float> _StartWhenDone(WWW www, IEnumerator<float> pausedProc)
+ {
+ while (!www.isDone)
+ yield return WaitForOneFrame;
+
+ _tmpRef = pausedProc;
+ ReplacementFunction = ReturnTmpRefForRepFunc;
+ yield return float.NaN;
+ }
+#endif
+
+ /// <summary>
+ /// Use the command "yield return Timing.WaitUntilDone(operation);" to pause the current
+ /// coroutine until the operation is done.
+ /// </summary>
+ /// <param name="operation">The operation variable returned.</param>
+ public static float WaitUntilDone(AsyncOperation operation)
+ {
+ if (operation == null || operation.isDone) return float.NaN;
+
+ CoroutineHandle handle = CurrentCoroutine;
+ Timing inst = GetInstance(CurrentCoroutine.Key);
+ if (inst == null) return float.NaN;
+
+ _tmpRef = _StartWhenDone(operation, inst.CoindexPeek(inst._handleToIndex[handle]));
+ ReplacementFunction = ReturnTmpRefForRepFunc;
+ return float.NaN;
+ }
+
+ private static IEnumerator<float> _StartWhenDone(AsyncOperation operation, IEnumerator<float> pausedProc)
+ {
+ while (!operation.isDone)
+ yield return WaitForOneFrame;
+
+ _tmpRef = pausedProc;
+ ReplacementFunction = ReturnTmpRefForRepFunc;
+ yield return float.NaN;
+ }
+
+ /// <summary>
+ /// Use the command "yield return Timing.WaitUntilDone(operation);" to pause the current
+ /// coroutine until the operation is done.
+ /// </summary>
+ /// <param name="operation">The operation variable returned.</param>
+ public static float WaitUntilDone(CustomYieldInstruction operation)
+ {
+ if (operation == null || !operation.keepWaiting) return float.NaN;
+
+ CoroutineHandle handle = CurrentCoroutine;
+ Timing inst = GetInstance(CurrentCoroutine.Key);
+ if (inst == null) return float.NaN;
+
+ _tmpRef = _StartWhenDone(operation, inst.CoindexPeek(inst._handleToIndex[handle]));
+ ReplacementFunction = ReturnTmpRefForRepFunc;
+ return float.NaN;
+ }
+
+ private static IEnumerator<float> _StartWhenDone(CustomYieldInstruction operation, IEnumerator<float> pausedProc)
+ {
+ while (operation.keepWaiting)
+ yield return WaitForOneFrame;
+
+ _tmpRef = pausedProc;
+ ReplacementFunction = ReturnTmpRefForRepFunc;
+ yield return float.NaN;
+ }
+
+ /// <summary>
+ /// Keeps this coroutine from executing until UnlockCoroutine is called with a matching key.
+ /// </summary>
+ /// <param name="coroutine">The handle to the coroutine to be locked.</param>
+ /// <param name="key">The key to use. A new key can be generated by calling "new CoroutineHandle(0)".</param>
+ /// <returns>Whether the lock was successful.</returns>
+ public bool LockCoroutine(CoroutineHandle coroutine, CoroutineHandle key)
+ {
+ if (coroutine.Key != _instanceID || key == new CoroutineHandle() || key.Key != 0)
+ return false;
+
+ if (!_waitingTriggers.ContainsKey(key))
+ _waitingTriggers.Add(key, new HashSet<CoroutineHandle> { coroutine });
+ else
+ _waitingTriggers[key].Add(coroutine);
+
+ _allWaiting.Add(coroutine);
+
+ SetHeld(_handleToIndex[coroutine], true);
+
+ return true;
+ }
+
+ /// <summary>
+ /// Unlocks a coroutine that has been locked, so long as the key matches.
+ /// </summary>
+ /// <param name="coroutine">The handle to the coroutine to be unlocked.</param>
+ /// <param name="key">The key that the coroutine was previously locked with.</param>
+ /// <returns>Whether the coroutine was successfully unlocked.</returns>
+ public bool UnlockCoroutine(CoroutineHandle coroutine, CoroutineHandle key)
+ {
+ if (coroutine.Key != _instanceID || key == new CoroutineHandle() ||
+ !_handleToIndex.ContainsKey(coroutine) || !_waitingTriggers.ContainsKey(key))
+ return false;
+
+ if (_waitingTriggers[key].Count == 1)
+ _waitingTriggers.Remove(key);
+ else
+ _waitingTriggers[key].Remove(coroutine);
+
+ if (!HandleIsInWaitingList(coroutine))
+ {
+ SetHeld(_handleToIndex[coroutine], false);
+ _allWaiting.Remove(coroutine);
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Calls the specified action after a specified number of seconds.
+ /// </summary>
+ /// <param name="delay">The number of seconds to wait before calling the action.</param>
+ /// <param name="action">The action to call.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallDelayed(float delay, System.Action action)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, null));
+ }
+
+ /// <summary>
+ /// Calls the specified action after a specified number of seconds.
+ /// </summary>
+ /// <param name="delay">The number of seconds to wait before calling the action.</param>
+ /// <param name="action">The action to call.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallDelayedOnInstance(float delay, System.Action action)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, null));
+ }
+
+ /// <summary>
+ /// Calls the specified action after a specified number of seconds.
+ /// </summary>
+ /// <param name="delay">The number of seconds to wait before calling the action.</param>
+ /// <param name="action">The action to call.</param>
+ /// <param name="cancelWith">A GameObject that will be checked to make sure it hasn't been destroyed before calling the action.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallDelayed(float delay, System.Action action, GameObject cancelWith)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, cancelWith));
+ }
+
+ /// <summary>
+ /// Calls the specified action after a specified number of seconds.
+ /// </summary>
+ /// <param name="delay">The number of seconds to wait before calling the action.</param>
+ /// <param name="action">The action to call.</param>
+ /// <param name="cancelWith">A GameObject that will be checked to make sure it hasn't been destroyed before calling the action.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallDelayedOnInstance(float delay, System.Action action, GameObject cancelWith)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, cancelWith));
+ }
+
+ /// <summary>
+ /// Calls the specified action after a specified number of seconds.
+ /// </summary>
+ /// <param name="delay">The number of seconds to wait before calling the action.</param>
+ /// <param name="action">The action to call.</param>
+ /// <param name="segment">The timing segment that the call should be made in.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallDelayed(float delay, Segment segment, System.Action action)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, null), segment);
+ }
+
+ /// <summary>
+ /// Calls the specified action after a specified number of seconds.
+ /// </summary>
+ /// <param name="delay">The number of seconds to wait before calling the action.</param>
+ /// <param name="action">The action to call.</param>
+ /// <param name="segment">The timing segment that the call should be made in.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallDelayedOnInstance(float delay, Segment segment, System.Action action)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, null), segment);
+ }
+
+ /// <summary>
+ /// Calls the specified action after a specified number of seconds.
+ /// </summary>
+ /// <param name="delay">The number of seconds to wait before calling the action.</param>
+ /// <param name="action">The action to call.</param>
+ /// <param name="gameObject">A GameObject that will be checked to make sure it hasn't been destroyed
+ /// before calling the action.</param>
+ /// <param name="segment">The timing segment that the call should be made in.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallDelayed(float delay, Segment segment, System.Action action, GameObject gameObject)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, gameObject), segment);
+ }
+
+ /// <summary>
+ /// Calls the specified action after a specified number of seconds.
+ /// </summary>
+ /// <param name="delay">The number of seconds to wait before calling the action.</param>
+ /// <param name="action">The action to call.</param>
+ /// <param name="gameObject">A GameObject that will be tagged onto the coroutine and checked to make sure it hasn't been destroyed
+ /// before calling the action.</param>
+ /// <param name="segment">The timing segment that the call should be made in.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallDelayedOnInstance(float delay, Segment segment, System.Action action, GameObject gameObject)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, gameObject), segment);
+ }
+
+ private IEnumerator<float> _DelayedCall(float delay, System.Action action, GameObject cancelWith)
+ {
+ yield return WaitForSecondsOnInstance(delay);
+
+ if(ReferenceEquals(cancelWith, null) || cancelWith != null)
+ action();
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallPeriodically(float timeframe, float period, System.Action action, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, period, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallPeriodicallyOnInstance(float timeframe, float period, System.Action action, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, period, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="segment">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallPeriodically(float timeframe, float period, System.Action action, Segment segment, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, period, action, onDone), segment);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="segment">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallPeriodicallyOnInstance(float timeframe, float period, System.Action action, Segment segment, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, period, action, onDone), segment);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallContinuously(float timeframe, System.Action action, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, 0f, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallContinuouslyOnInstance(float timeframe, System.Action action, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, 0f, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallContinuously(float timeframe, System.Action action, Segment timing, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, 0f, action, onDone), timing);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallContinuouslyOnInstance(float timeframe, System.Action action, Segment timing, System.Action onDone = null)
+ {
+ return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, 0f, action, onDone), timing);
+ }
+
+ private IEnumerator<float> _CallContinuously(float timeframe, float period, System.Action action, System.Action onDone)
+ {
+ double startTime = localTime;
+ while (localTime <= startTime + timeframe)
+ {
+ yield return WaitForSecondsOnInstance(period);
+
+ action();
+ }
+
+ if (onDone != null)
+ onDone();
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallPeriodically<T>
+ (T reference, float timeframe, float period, System.Action<T> action, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() :
+ RunCoroutine(Instance._CallContinuously(reference, timeframe, period, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallPeriodicallyOnInstance<T>
+ (T reference, float timeframe, float period, System.Action<T> action, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() :
+ RunCoroutineOnInstance(_CallContinuously(reference, timeframe, period, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallPeriodically<T>(T reference, float timeframe, float period, System.Action<T> action,
+ Segment timing, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() :
+ RunCoroutine(Instance._CallContinuously(reference, timeframe, period, action, onDone), timing);
+ }
+
+ /// <summary>
+ /// Calls the supplied action at the given rate for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each period.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="period">The amount of time between calls.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallPeriodicallyOnInstance<T>(T reference, float timeframe, float period, System.Action<T> action,
+ Segment timing, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() :
+ RunCoroutineOnInstance(_CallContinuously(reference, timeframe, period, action, onDone), timing);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallContinuously<T>(T reference, float timeframe, System.Action<T> action, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() :
+ RunCoroutine(Instance._CallContinuously(reference, timeframe, 0f, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallContinuouslyOnInstance<T>(T reference, float timeframe, System.Action<T> action, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() :
+ RunCoroutineOnInstance(_CallContinuously(reference, timeframe, 0f, action, onDone), Segment.Update);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public static CoroutineHandle CallContinuously<T>(T reference, float timeframe, System.Action<T> action,
+ Segment timing, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() :
+ RunCoroutine(Instance._CallContinuously(reference, timeframe, 0f, action, onDone), timing);
+ }
+
+ /// <summary>
+ /// Calls the supplied action every frame for a given number of seconds.
+ /// </summary>
+ /// <param name="reference">A value that will be passed in to the supplied action each frame.</param>
+ /// <param name="timeframe">The number of seconds that this function should run.</param>
+ /// <param name="action">The action to call every frame.</param>
+ /// <param name="timing">The timing segment to run in.</param>
+ /// <param name="onDone">An optional action to call when this function finishes.</param>
+ /// <returns>The handle to the coroutine that is started by this function.</returns>
+ public CoroutineHandle CallContinuouslyOnInstance<T>(T reference, float timeframe, System.Action<T> action,
+ Segment timing, System.Action<T> onDone = null)
+ {
+ return action == null ? new CoroutineHandle() :
+ RunCoroutineOnInstance(_CallContinuously(reference, timeframe, 0f, action, onDone), timing);
+ }
+
+ private IEnumerator<float> _CallContinuously<T>(T reference, float timeframe, float period,
+ System.Action<T> action, System.Action<T> onDone = null)
+ {
+ double startTime = localTime;
+ while (localTime <= startTime + timeframe)
+ {
+ yield return WaitForSecondsOnInstance(period);
+
+ action(reference);
+ }
+
+ if (onDone != null)
+ onDone(reference);
+ }
+
+ private struct ProcessIndex : System.IEquatable<ProcessIndex>
+ {
+ public Segment seg;
+ public int i;
+
+ public bool Equals(ProcessIndex other)
+ {
+ return seg == other.seg && i == other.i;
+ }
+
+ public override bool Equals(object other)
+ {
+ if (other is ProcessIndex)
+ return Equals((ProcessIndex)other);
+ return false;
+ }
+
+ public static bool operator ==(ProcessIndex a, ProcessIndex b)
+ {
+ return a.seg == b.seg && a.i == b.i;
+ }
+
+ public static bool operator !=(ProcessIndex a, ProcessIndex b)
+ {
+ return a.seg != b.seg || a.i != b.i;
+ }
+
+ public override int GetHashCode()
+ {
+ return (((int)seg - 2) * (int.MaxValue / 3)) + i;
+ }
+ }
+
+ [System.Obsolete("Unity coroutine function, use RunCoroutine instead.", true)]
+ public new Coroutine StartCoroutine(System.Collections.IEnumerator routine) { return null; }
+
+ [System.Obsolete("Unity coroutine function, use RunCoroutine instead.", true)]
+ public new Coroutine StartCoroutine(string methodName, object value) { return null; }
+
+ [System.Obsolete("Unity coroutine function, use RunCoroutine instead.", true)]
+ public new Coroutine StartCoroutine(string methodName) { return null; }
+
+ [System.Obsolete("Unity coroutine function, use RunCoroutine instead.", true)]
+ public new Coroutine StartCoroutine_Auto(System.Collections.IEnumerator routine) { return null; }
+
+ [System.Obsolete("Unity coroutine function, use KillCoroutines instead.", true)]
+ public new void StopCoroutine(string methodName) { }
+
+ [System.Obsolete("Unity coroutine function, use KillCoroutines instead.", true)]
+ public new void StopCoroutine(System.Collections.IEnumerator routine) { }
+
+ [System.Obsolete("Unity coroutine function, use KillCoroutines instead.", true)]
+ public new void StopCoroutine(Coroutine routine) { }
+
+ [System.Obsolete("Unity coroutine function, use KillCoroutines instead.", true)]
+ public new void StopAllCoroutines() { }
+
+ [System.Obsolete("Use your own GameObject for this.", true)]
+ public new static void Destroy(Object obj) { }
+
+ [System.Obsolete("Use your own GameObject for this.", true)]
+ public new static void Destroy(Object obj, float f) { }
+
+ [System.Obsolete("Use your own GameObject for this.", true)]
+ public new static void DestroyObject(Object obj) { }
+
+ [System.Obsolete("Use your own GameObject for this.", true)]
+ public new static void DestroyObject(Object obj, float f) { }
+
+ [System.Obsolete("Use your own GameObject for this.", true)]
+ public new static void DestroyImmediate(Object obj) { }
+
+ [System.Obsolete("Use your own GameObject for this.", true)]
+ public new static void DestroyImmediate(Object obj, bool b) { }
+
+ [System.Obsolete("Use your own GameObject for this.", true)]
+ public new static void Instantiate(Object obj) { }
+
+ [System.Obsolete("Use your own GameObject for this.", true)]
+ public new static void Instantiate(Object original, Vector3 position, Quaternion rotation) { }
+
+ [System.Obsolete("Use your own GameObject for this.", true)]
+ public new static void Instantiate<T>(T original) where T : Object { }
+
+ [System.Obsolete("Just.. no.", true)]
+ public new static T FindObjectOfType<T>() where T : Object { return null; }
+
+ [System.Obsolete("Just.. no.", true)]
+ public new static Object FindObjectOfType(System.Type t) { return null; }
+
+ [System.Obsolete("Just.. no.", true)]
+ public new static T[] FindObjectsOfType<T>() where T : Object { return null; }
+
+ [System.Obsolete("Just.. no.", true)]
+ public new static Object[] FindObjectsOfType(System.Type t) { return null; }
+
+ [System.Obsolete("Just.. no.", true)]
+ public new static void print(object message) { }
+ }
+
+ /// <summary>
+ /// The timing segment that a coroutine is running in or should be run in.
+ /// </summary>
+ public enum Segment
+ {
+ /// <summary>
+ /// Sometimes returned as an error state
+ /// </summary>
+ Invalid = -1,
+ /// <summary>
+ /// This is the default timing segment
+ /// </summary>
+ Update,
+ /// <summary>
+ /// This is primarily used for physics calculations
+ /// </summary>
+ FixedUpdate,
+ /// <summary>
+ /// This is run immediately after update
+ /// </summary>
+ LateUpdate,
+ /// <summary>
+ /// This executes, by default, about as quickly as the eye can detect changes in a text field
+ /// </summary>
+ SlowUpdate
+ }
+
+ /// <summary>
+ /// How much debug info should be sent to the Unity profiler. NOTE: Setting this to anything above none shows up in the profiler as a
+ /// decrease in performance and a memory alloc. Those effects do not translate onto device.
+ /// </summary>
+ public enum DebugInfoType
+ {
+ /// <summary>
+ /// None coroutines will be separated in the Unity profiler
+ /// </summary>
+ None,
+ /// <summary>
+ /// The Unity profiler will identify each coroutine individually
+ /// </summary>
+ SeperateCoroutines,
+ /// <summary>
+ /// Coroutines will be separated and any tags or layers will be identified
+ /// </summary>
+ SeperateTags
+ }
+
+ /// <summary>
+ /// A handle for a MEC coroutine.
+ /// </summary>
+ public struct CoroutineHandle : System.IEquatable<CoroutineHandle>
+ {
+ private const byte ReservedSpace = 0x0F;
+ private readonly static int[] NextIndex = { ReservedSpace + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ private readonly int _id;
+
+ public byte Key { get { return (byte)(_id & ReservedSpace); } }
+
+ public CoroutineHandle(byte ind)
+ {
+ if (ind > ReservedSpace)
+ ind -= ReservedSpace;
+
+ _id = NextIndex[ind] + ind;
+ NextIndex[ind] += ReservedSpace + 1;
+ }
+
+ public bool Equals(CoroutineHandle other)
+ {
+ return _id == other._id;
+ }
+
+ public override bool Equals(object other)
+ {
+ if (other is CoroutineHandle)
+ return Equals((CoroutineHandle)other);
+ return false;
+ }
+
+ public static bool operator==(CoroutineHandle a, CoroutineHandle b)
+ {
+ return a._id == b._id;
+ }
+
+ public static bool operator!=(CoroutineHandle a, CoroutineHandle b)
+ {
+ return a._id != b._id;
+ }
+
+ public override int GetHashCode()
+ {
+ return _id;
+ }
+
+ /// <summary>
+ /// Is true if this handle may have been a valid handle at some point. (i.e. is not an uninitialized handle, error handle, or a key to a coroutine lock)
+ /// </summary>
+ public bool IsValid
+ {
+ get { return Key != 0; }
+ }
+ }
+
+ public static class MECExtensionMethods1
+ {
+ /// <summary>
+ /// Run a new coroutine in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(this IEnumerator<float> coroutine)
+ {
+ return Timing.RunCoroutine(coroutine);
+ }
+
+ /// <summary>
+ /// Run a new coroutine in the Update segment.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(this IEnumerator<float> coroutine, string tag)
+ {
+ return Timing.RunCoroutine(coroutine, tag);
+ }
+
+ /// <summary>
+ /// Run a new coroutine.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="segment">The segment that the coroutine should run in.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(this IEnumerator<float> coroutine, Segment segment)
+ {
+ return Timing.RunCoroutine(coroutine, segment);
+ }
+
+ /// <summary>
+ /// Run a new coroutine.
+ /// </summary>
+ /// <param name="coroutine">The new coroutine's handle.</param>
+ /// <param name="segment">The segment that the coroutine should run in.</param>
+ /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param>
+ /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns>
+ public static CoroutineHandle RunCoroutine(this IEnumerator<float> coroutine, Segment segment, string tag)
+ {
+ return Timing.RunCoroutine(coroutine, segment, tag);
+ }
+ }
+}
+
+public static class MECExtensionMethods2
+{
+ /// <summary>
+ /// Cancels this coroutine when the supplied game object is destroyed or made inactive.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="gameObject">The GameObject to test.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, GameObject gameObject)
+ {
+ while (MEC.Timing.MainThread != System.Threading.Thread.CurrentThread || (gameObject && gameObject.activeInHierarchy && coroutine.MoveNext()))
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Cancels this coroutine when the supplied game objects are destroyed or made inactive.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="gameObject1">The first GameObject to test.</param>
+ /// <param name="gameObject2">The second GameObject to test</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, GameObject gameObject1, GameObject gameObject2)
+ {
+ while (MEC.Timing.MainThread != System.Threading.Thread.CurrentThread || (gameObject1 && gameObject1.activeInHierarchy &&
+ gameObject2 && gameObject2.activeInHierarchy && coroutine.MoveNext()))
+ yield return coroutine.Current;
+ }
+
+ /// <summary>
+ /// Cancels this coroutine when the supplied game objects are destroyed or made inactive.
+ /// </summary>
+ /// <param name="coroutine">The coroutine handle to act upon.</param>
+ /// <param name="gameObject1">The first GameObject to test.</param>
+ /// <param name="gameObject2">The second GameObject to test</param>
+ /// <param name="gameObject3">The third GameObject to test.</param>
+ /// <returns>The modified coroutine handle.</returns>
+ public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine,
+ GameObject gameObject1, GameObject gameObject2, GameObject gameObject3)
+ {
+ while (MEC.Timing.MainThread != System.Threading.Thread.CurrentThread || (gameObject1 && gameObject1.activeInHierarchy &&
+ gameObject2 && gameObject2.activeInHierarchy && gameObject3 && gameObject3.activeInHierarchy && coroutine.MoveNext()))
+ yield return coroutine.Current;
+ }
+}
diff --git a/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs.meta b/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs.meta
new file mode 100644
index 0000000..21e6c1b
--- /dev/null
+++ b/WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2d2433f4570c1404da40af9ea0b12741
+timeCreated: 1510248004
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: a0f854455b10ba44d819f36586b0909b, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scenes/Test.unity b/WorldlineKeepers/Assets/Scenes/Test.unity
index b1c455b..e955672 100644
--- a/WorldlineKeepers/Assets/Scenes/Test.unity
+++ b/WorldlineKeepers/Assets/Scenes/Test.unity
@@ -10001,8 +10001,10 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 1552119910}
+ - component: {fileID: 1552119912}
- component: {fileID: 1552119909}
- component: {fileID: 1552119911}
+ - component: {fileID: 1552119913}
m_Layer: 0
m_Name: Main
m_TagString: Untagged
@@ -10049,6 +10051,30 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 807579a6a3913a7488bd4be81ce79a12, type: 3}
m_Name:
m_EditorClassIdentifier:
+--- !u!114 &1552119912
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1552119908}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: e1448edde341f4f44b6959c045b6600b, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+--- !u!114 &1552119913
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1552119908}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 0825a89e4815bc94eb58cd23aa6f4814, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
--- !u!1 &1566097397
GameObject:
m_ObjectHideFlags: 0
diff --git a/WorldlineKeepers/Assets/Scripts/Buffs/Buff.cs b/WorldlineKeepers/Assets/Scripts/Buffs/Buff.cs
index 8f65991..1c6ae5a 100644
--- a/WorldlineKeepers/Assets/Scripts/Buffs/Buff.cs
+++ b/WorldlineKeepers/Assets/Scripts/Buffs/Buff.cs
@@ -13,7 +13,7 @@ public abstract class Buff
public BuffMetadata metadata;
// buffЧ
- public BuffEfectorBase effector;
+ public BuffBehaviour effector;
public string uid
{
diff --git a/WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs b/WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs
index b90beb8..0a0559f 100644
--- a/WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs
+++ b/WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs
@@ -2,7 +2,7 @@ using System.Collections;
using System.Collections.Generic;
using UnityEngine;
-public class BuffEfectorBase
+public class BuffBehaviour
{
private CharacterBase m_Character;
diff --git a/WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs.meta b/WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs.meta
index a433744..a433744 100644
--- a/WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs.meta
+++ b/WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs.meta
diff --git a/WorldlineKeepers/Assets/Scripts/Common/Statemachine.cs b/WorldlineKeepers/Assets/Scripts/Common/Statemachine.cs
new file mode 100644
index 0000000..ffa33a2
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Common/Statemachine.cs
@@ -0,0 +1,254 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using MEC;
+
+namespace WK
+{
+
+ /// <summary>
+ /// ״̬
+ /// </summary>
+ public class StateMachine
+ {
+
+ public delegate void LoadStateComplete();
+
+ public abstract class State
+ {
+ public StateMachine owner;
+ public int stateID;
+ public abstract IEnumerator<float> OnStart();
+ public abstract IEnumerator<float> OnEnd();
+ public abstract void OnUpdate(float deltaTime);
+ }
+
+ public const int NULL_STATE_ID = -1;
+ public const float COROUINT_DELTIME = 0.01f;
+
+ private Dictionary<int/*stateID*/, State> allState = new Dictionary<int, State>();
+ private int curStateID = NULL_STATE_ID;
+ private int stateIDDistributor = 0;
+ // ״̬лǰΪfalse,ܽupdate
+ private bool isUpdateActive = false;
+
+ /// <summary>
+ /// ״̬״̬еID
+ /// </summary>
+ /// <param name="newState"></param>
+ /// <returns></returns>
+ public int RegisterState(State newState)
+ {
+ if (newState == null)
+ return NULL_STATE_ID;
+ if (stateIDDistributor + 1 >= int.MaxValue)
+ {
+ Debug.LogError("״̬״̬ʧܣ״̬ӵ״̬");
+ return NULL_STATE_ID;
+ }
+ ++stateIDDistributor;
+ if (!allState.ContainsKey(stateIDDistributor))
+ {
+ newState.owner = this;
+ newState.stateID = stateIDDistributor;
+ allState.Add(stateIDDistributor, newState);
+ return stateIDDistributor;
+ }
+ Debug.LogError("״̬״̬ʧܣ״̬Ѿ");
+ return NULL_STATE_ID;
+ }
+
+ public bool RemoveState(State state)
+ {
+ if (state != null)
+ {
+ return RemoveState(state.stateID);
+ }
+ Debug.LogError("״̬ɾ״̬ʧܣ״̬Ϊ");
+ return false;
+ }
+
+ public bool RemoveState(int stateID)
+ {
+ if (allState.ContainsKey(stateID))
+ {
+ allState.Remove(stateID);
+ return true;
+ }
+ Debug.LogError("״̬ɾ״̬ʧܣ״̬ڣstateID = " + stateID);
+ return false;
+ }
+
+ /// <summary>
+ /// ʼ״̬
+ /// </summary>
+ /// <param name="stateID"></param>
+ /// <returns></returns>
+ public bool Start(int stateID)
+ {
+ if (!HasBegin())
+ {
+ ForceGotoState(stateID);
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// ״̬
+ /// </summary>
+ /// <returns></returns>
+ public bool Stop()
+ {
+ if (HasBegin())
+ {
+ ForceGotoState(NULL_STATE_ID);
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// ״̬
+ /// </summary>
+ /// <param name="deltaTime"></param>
+ public void Update(float deltaTime)
+ {
+ if (HasBegin())
+ {
+ UpdateState(curStateID, deltaTime);
+ }
+ }
+
+ public bool GotoState(int stateID, bool skipStartFunc = false, bool bForce = false, LoadStateComplete callback = null)
+ {
+ if (HasBegin())
+ return ForceGotoState(stateID, skipStartFunc, bForce, callback);
+ return false;
+ }
+
+ public bool ForceGotoState(int nextStateID, bool skipStartFunc = false, bool bForce = false, LoadStateComplete callback = null)
+ {
+ if (curStateID != nextStateID || bForce)
+ {
+ Timing.Instance.RunCoroutineOnInstance(AyncForceGotoState(nextStateID, skipStartFunc, callback));
+ return true;
+ }
+ if (callback != null)
+ callback();
+ return false;
+ }
+
+ /// <summary>
+ /// 첽лij״̬
+ /// </summary>
+ /// <returns></returns>
+ private IEnumerator<float> AyncForceGotoState(int nextStateID, bool skipStartFunc = false, LoadStateComplete callback = null)
+ {
+ isUpdateActive = false;
+ CoroutineHandle handle = Timing.RunCoroutine(EndState(curStateID));
+ while (handle.IsValid)
+ {
+ yield return Timing.WaitForSeconds(COROUINT_DELTIME);
+ }
+ curStateID = nextStateID;
+ if (!skipStartFunc)
+ {
+ CoroutineHandle handle2 = Timing.RunCoroutine(StartState(curStateID));
+ while (handle2.IsValid)
+ {
+ yield return Timing.WaitForSeconds(COROUINT_DELTIME);
+ }
+ }
+ if (callback != null)
+ callback();
+ isUpdateActive = true;
+ }
+
+ public int GetCurStateID()
+ {
+ return curStateID;
+ }
+
+ public bool HasBegin()
+ {
+ if (curStateID != NULL_STATE_ID && allState.ContainsKey(curStateID))
+ return true;
+ return false;
+ }
+
+ public bool IsInState(int stateID)
+ {
+ if (HasBegin())
+ {
+ return curStateID == stateID;
+ }
+ return false;
+ }
+
+ public State GetState(int stateID)
+ {
+ if (allState.ContainsKey(stateID))
+ {
+ return allState[stateID];
+ }
+ return null;
+ }
+
+ public void Clean()
+ {
+ allState.Clear();
+ curStateID = NULL_STATE_ID;
+ stateIDDistributor = 0;
+ }
+
+ public void ResetCurState()
+ {
+ curStateID = NULL_STATE_ID;
+ }
+
+ private IEnumerator<float> StartState(int stateID)
+ {
+ if (HasBegin())
+ {
+ State state = GetState(stateID);
+ if (state != null)
+ {
+ CoroutineHandle handle = Timing.RunCoroutine(state.OnStart());
+ while (handle.IsValid)
+ {
+ yield return Timing.WaitForSeconds(COROUINT_DELTIME);
+ }
+ }
+ }
+ }
+
+ private IEnumerator<float> EndState(int stateID)
+ {
+ if (HasBegin())
+ {
+ State state = GetState(stateID);
+ if (state != null)
+ {
+ CoroutineHandle handle = Timing.RunCoroutine(state.OnEnd());
+ while (handle.IsValid)
+ {
+ yield return Timing.WaitForSeconds(COROUINT_DELTIME);
+ }
+ }
+ }
+ }
+
+ private void UpdateState(int stateID, float deltaTime)
+ {
+ if (HasBegin())
+ {
+ State state = GetState(stateID);
+ if (state != null)
+ state.OnUpdate(deltaTime);
+ }
+ }
+
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Common/Statemachine.cs.meta b/WorldlineKeepers/Assets/Scripts/Common/Statemachine.cs.meta
new file mode 100644
index 0000000..e2b8d49
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Common/Statemachine.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c43b283f086a24140b0e6e6e0e9efbef
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Data/DataManager.cs b/WorldlineKeepers/Assets/Scripts/Data/DataManager.cs
index a3d1257..3bb9ef2 100644
--- a/WorldlineKeepers/Assets/Scripts/Data/DataManager.cs
+++ b/WorldlineKeepers/Assets/Scripts/Data/DataManager.cs
@@ -1,3 +1,4 @@
+using LitJson;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
@@ -11,6 +12,7 @@ namespace WK.Data
private Dictionary<string/*uid*/, CharacterStatsMetadata> m_CharacterStatsMetadata = new Dictionary<string, CharacterStatsMetadata>();
private Dictionary<string/*uid*/, BuffMetadata> m_BuffMetadata = new Dictionary<string, BuffMetadata>();
+ private Dictionary<string/*uid*/, CharacterMetadata> m_CharacterMetadata = new Dictionary<string, CharacterMetadata>();
public CharacterStatsMetadata GetCharacterStats(string uid)
{
@@ -35,6 +37,7 @@ namespace WK.Data
public void Load()
{
LoadDefaultStats();
+ LoadDefaultCharacters();
}
private void LoadDefaultStats()
@@ -47,6 +50,16 @@ namespace WK.Data
}
}
+ private void LoadDefaultCharacters()
+ {
+ TextAsset text = ResourceManager.Instance.LoadAsset<TextAsset>(StaticDefine.RoninPath);
+ CharacterMetadata metadata = JsonMapper.ToObject<CharacterMetadata>(text.text);
+ if(metadata != null)
+ {
+ m_CharacterMetadata.Add(metadata.uid, metadata);
+ }
+ }
+
}
} \ No newline at end of file
diff --git a/WorldlineKeepers/Assets/Scripts/EntityBase.cs b/WorldlineKeepers/Assets/Scripts/EntityBase.cs
index 3470d3c..f894d20 100644
--- a/WorldlineKeepers/Assets/Scripts/EntityBase.cs
+++ b/WorldlineKeepers/Assets/Scripts/EntityBase.cs
@@ -6,7 +6,7 @@ public class EntityBase : MonoBehaviour
{
public SpriteRenderer m_Shadow;
- private SpriteRenderer m_SpriteRenderer;
+ protected SpriteRenderer m_SpriteRenderer;
protected virtual void Awake()
{
diff --git a/WorldlineKeepers/Assets/Scripts/Items/Inventory.cs b/WorldlineKeepers/Assets/Scripts/Items/Inventory.cs
new file mode 100644
index 0000000..f620a93
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/Inventory.cs
@@ -0,0 +1,15 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK.Items
+{
+
+ public class Inventory
+ {
+
+
+
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Items/Inventory.cs.meta b/WorldlineKeepers/Assets/Scripts/Items/Inventory.cs.meta
new file mode 100644
index 0000000..a6a021f
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/Inventory.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0fd1d1f499057e44097943c0eb053781
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Items/Item.cs b/WorldlineKeepers/Assets/Scripts/Items/Item.cs
new file mode 100644
index 0000000..bcffc5b
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/Item.cs
@@ -0,0 +1,21 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using WK.Data;
+using WK.Items;
+
+namespace Wk.Items
+{
+
+ public class Item
+ {
+ private ItemMetadata m_Metadata;
+ public ItemMetadata metadata { get { return m_Metadata; } }
+
+ private ItemBehaviour m_Behaviour;
+ public ItemBehaviour behaviour { get { return m_Behaviour; } }
+
+
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Items/Item.cs.meta b/WorldlineKeepers/Assets/Scripts/Items/Item.cs.meta
new file mode 100644
index 0000000..828b300
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/Item.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d7ae8ebc7348cf647a6cf90a67bd1711
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Items/ItemBehaviour.cs b/WorldlineKeepers/Assets/Scripts/Items/ItemBehaviour.cs
new file mode 100644
index 0000000..520946a
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/ItemBehaviour.cs
@@ -0,0 +1,27 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK.Items
+{
+
+ public class ItemBehaviour
+ {
+
+ public virtual void OnEquiped()
+ {
+
+ }
+
+ public virtual void OnUnEquiped()
+ {
+
+ }
+
+ public virtual void OnStack()
+ {
+
+ }
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Items/ItemBehaviour.cs.meta b/WorldlineKeepers/Assets/Scripts/Items/ItemBehaviour.cs.meta
new file mode 100644
index 0000000..1acab27
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/ItemBehaviour.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6ecedcd123438614db9ea58933287d13
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Items/ItemDaggerBehaviour.cs b/WorldlineKeepers/Assets/Scripts/Items/ItemDaggerBehaviour.cs
new file mode 100644
index 0000000..1e0dfe6
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/ItemDaggerBehaviour.cs
@@ -0,0 +1,15 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK.Items
+{
+
+ public class ItemDaggerBehaviour : ItemBehaviour
+ {
+
+
+
+ }
+
+} \ No newline at end of file
diff --git a/WorldlineKeepers/Assets/Scripts/Items/ItemDaggerBehaviour.cs.meta b/WorldlineKeepers/Assets/Scripts/Items/ItemDaggerBehaviour.cs.meta
new file mode 100644
index 0000000..409141f
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/ItemDaggerBehaviour.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 759db356bc563824882ce1b4ee8fd879
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Items/ItemHellbellBehaviour.cs b/WorldlineKeepers/Assets/Scripts/Items/ItemHellbellBehaviour.cs
new file mode 100644
index 0000000..1008eed
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/ItemHellbellBehaviour.cs
@@ -0,0 +1,15 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK.Items
+{
+
+ public class ItemHellbellBehaviour : ItemBehaviour
+ {
+
+
+
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Items/ItemHellbellBehaviour.cs.meta b/WorldlineKeepers/Assets/Scripts/Items/ItemHellbellBehaviour.cs.meta
new file mode 100644
index 0000000..341e7c0
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/ItemHellbellBehaviour.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1156ea03b49c6264692b0552676e606c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Items/ItemMetadata.cs b/WorldlineKeepers/Assets/Scripts/Items/ItemMetadata.cs
new file mode 100644
index 0000000..e77f494
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/ItemMetadata.cs
@@ -0,0 +1,23 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK.Data
+{
+
+ public class ItemMetadata
+ {
+
+ public string uid;
+
+ public string name_key;
+
+ public string desc_key;
+
+ public string icon_path;
+
+ public string extra_data;
+
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Items/ItemMetadata.cs.meta b/WorldlineKeepers/Assets/Scripts/Items/ItemMetadata.cs.meta
new file mode 100644
index 0000000..07ede60
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Items/ItemMetadata.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2f5b94a115aa35a4c84083a3743c2639
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/StaticDefine.cs b/WorldlineKeepers/Assets/Scripts/StaticDefine.cs
index 53219b5..3f62e8c 100644
--- a/WorldlineKeepers/Assets/Scripts/StaticDefine.cs
+++ b/WorldlineKeepers/Assets/Scripts/StaticDefine.cs
@@ -10,6 +10,8 @@ namespace WK
public static string StatsFilePath = "metadata/default_stats.csv";
public static string BuffFilePath = "metadata/default_buffs.csv";
+ public static string RoninPath = "characters/ronin/ronin.json";
+
}
} \ No newline at end of file
diff --git a/WorldlineKeepers/Assets/Scripts/Stats/CharacterStatsBase.cs b/WorldlineKeepers/Assets/Scripts/Stats/CharacterStatsBase.cs
index b4869cb..8dbb161 100644
--- a/WorldlineKeepers/Assets/Scripts/Stats/CharacterStatsBase.cs
+++ b/WorldlineKeepers/Assets/Scripts/Stats/CharacterStatsBase.cs
@@ -7,24 +7,24 @@ using WK.Data;
namespace WK
{
- [System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)]
+ [StructLayout(LayoutKind.Explicit)]
public struct CharacterStatsValue
{
- [System.Runtime.InteropServices.FieldOffset(0)]
+ [FieldOffset(0)]
public int i;
- [System.Runtime.InteropServices.FieldOffset(0)]
+ [FieldOffset(0)]
public float f;
- [System.Runtime.InteropServices.FieldOffset(0)]
+ [FieldOffset(0)]
public bool boolean;
- [System.Runtime.InteropServices.FieldOffset(0)]
+ [FieldOffset(0)]
public char c;
- [System.Runtime.InteropServices.FieldOffset(0)]
+ [FieldOffset(0)]
public Vector2 v2;
- [System.Runtime.InteropServices.FieldOffset(0)]
+ [FieldOffset(0)]
public Vector3 v3;
- [System.Runtime.InteropServices.FieldOffset(0)]
+ [FieldOffset(0)]
public Vector4 v4;
- [System.Runtime.InteropServices.FieldOffset(0)]
+ [FieldOffset(0)]
public Color color;
}
@@ -44,7 +44,15 @@ namespace WK
/// ǰֵ
/// </summary>
public CharacterStatsValue value;
-
+
+ public ref int intValue => ref value.i;
+ public ref bool boolValue => ref value.boolean;
+ public ref float floatValue => ref value.f;
+ public ref char chartValue => ref value.c;
+ public ref Vector2 Vector2Value => ref value.v2;
+ public ref Vector3 Vector3Value => ref value.v3;
+ public ref Vector4 Vector4Value => ref value.v4;
+
public string uid
{
get
diff --git a/WorldlineKeepers/Assets/Scripts/Stats/CharacterStatsMetadata.cs b/WorldlineKeepers/Assets/Scripts/Stats/CharacterStatsMetadata.cs
index c240ca1..dbb0942 100644
--- a/WorldlineKeepers/Assets/Scripts/Stats/CharacterStatsMetadata.cs
+++ b/WorldlineKeepers/Assets/Scripts/Stats/CharacterStatsMetadata.cs
@@ -16,6 +16,8 @@ namespace WK.Data
public string type;
+ public string behaviour;
+
//
public string extra_data;
}
diff --git a/WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs b/WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs
new file mode 100644
index 0000000..c6e9bba
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs
@@ -0,0 +1,40 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using WK;
+
+public class TestEvent : MonoBehaviour
+{
+ #region 序列化
+
+ #endregion
+
+ #region 公共字段
+
+ #endregion
+
+ #region 私有字段
+
+ #endregion
+
+ private void Awake()
+ {
+ // 私有字段赋值
+
+ // 公共字段赋值
+
+ // 初始化
+ }
+
+ private void OnEnable()
+ {
+ GlobalEventManager.Instance.Register("Health.BurnKill", OnEventCheck);
+ GlobalEventManager.Instance.Notify("Health.BurnKill");
+ }
+
+ private void OnEventCheck(params object[] p)
+ {
+ Debug.Log("msg");
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs.meta b/WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs.meta
new file mode 100644
index 0000000..965ecdd
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0825a89e4815bc94eb58cd23aa6f4814
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools.meta b/WorldlineKeepers/Assets/Scripts/Tools.meta
new file mode 100644
index 0000000..bc5c8b7
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0f4ad5525cbe4b942bba307305127136
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/GlobalEventManager.cs b/WorldlineKeepers/Assets/Scripts/Tools/GlobalEventManager.cs
new file mode 100644
index 0000000..47f3990
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/GlobalEventManager.cs
@@ -0,0 +1,97 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace WK
+{
+ /// <summary>
+ /// ȫ¼
+ /// </summary>
+ public class GlobalEventManager : Singleton<GlobalEventManager>
+ {
+
+ // callback
+ public delegate void EventCallback(params object[] objs);
+ public Dictionary<string, LinkedList<EventCallback>> AllEvents = new Dictionary<string, LinkedList<EventCallback>>();
+
+ public void Register(string eventName, EventCallback callback, bool addFirst = false)
+ {
+ if (callback == null)
+ {
+ Debug.LogError("Ϊ");
+ return;
+ }
+ LinkedList<EventCallback> list;
+ if (!AllEvents.TryGetValue(eventName, out list))
+ {
+ list = new LinkedList<EventCallback>(); // ôӳ
+ AllEvents.Add(eventName, list);
+ }
+ if (!list.Contains(callback))
+ {
+ if (addFirst && list.Count > 0)
+ {
+ list.AddFirst(callback);
+ }
+ else
+ {
+ list.AddLast(callback);
+ }
+ }
+ else
+ {
+ Debug.LogError("ظӼ, eventName=" + eventName);
+ }
+ }
+
+ public void UnRegister(string eventName, EventCallback callback)
+ {
+ if (callback == null)
+ {
+ Debug.LogError("Ϊ");
+ return;
+ }
+ LinkedList<EventCallback> list;
+ if (!AllEvents.TryGetValue(eventName, out list))
+ {
+ return;
+ }
+ list.Remove(callback);
+ if (list.Count == 0)
+ {
+ AllEvents.Remove(eventName);
+ // listǴӳõģ
+ }
+ }
+
+ public void UnRegisterEvent(string eventName)
+ {
+ if (AllEvents.ContainsKey(eventName))
+ {
+ AllEvents.Remove(eventName);
+ }
+ }
+
+ public void UnRegisterAll(string eventName)
+ {
+ AllEvents.Remove(eventName);
+ }
+
+ public void Notify(string eventName, params object[] objs)
+ {
+ LinkedList<EventCallback> list;
+ if (AllEvents.TryGetValue(eventName, out list) && list != null && list.Count > 0)
+ {
+ foreach (EventCallback callback in list)
+ {
+ if (callback != null)
+ {
+ callback.Invoke(objs);
+ }
+ }
+ }
+ }
+
+ }
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/GlobalEventManager.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/GlobalEventManager.cs.meta
new file mode 100644
index 0000000..0c2c8ec
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/GlobalEventManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7a9f38c8080be5e41ad5220346ba8c7f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/NotificationCenter.cs b/WorldlineKeepers/Assets/Scripts/Tools/NotificationCenter.cs
new file mode 100644
index 0000000..b3f299a
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/NotificationCenter.cs
@@ -0,0 +1,167 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK
+{
+
+ public class NotificationCenter
+ {
+ private Dictionary<string, Dictionary<object, List<Action<object, object>>>> _table = new Dictionary<string, Dictionary<object, List<Action<object, object>>>>();
+
+ private HashSet<List<Action<object, object>>> _invoking = new HashSet<List<Action<object, object>>>();
+
+ public static readonly NotificationCenter instance = new NotificationCenter();
+
+ private NotificationCenter()
+ {
+ }
+
+ public void AddObserver(Action<object, object> handler, string notificationName)
+ {
+ AddObserver(handler, notificationName, null);
+ }
+
+ public void AddObserver(Action<object, object> handler, string notificationName, object sender)
+ {
+ if (handler == null)
+ {
+ Debug.LogError("Can't add a null event handler for notification, " + notificationName);
+ return;
+ }
+ if (string.IsNullOrEmpty(notificationName))
+ {
+ Debug.LogError("Can't observe an unnamed notification");
+ return;
+ }
+ if (!_table.ContainsKey(notificationName))
+ {
+ _table.Add(notificationName, new Dictionary<object, List<Action<object, object>>>());
+ }
+ Dictionary<object, List<Action<object, object>>> dictionary = _table[notificationName];
+ object key = ((sender != null) ? sender : this);
+ if (!dictionary.ContainsKey(key))
+ {
+ dictionary.Add(key, new List<Action<object, object>>());
+ }
+ List<Action<object, object>> list = dictionary[key];
+ if (_invoking.Contains(list))
+ {
+ list = (dictionary[key] = new List<Action<object, object>>(list));
+ }
+ list.Add(handler);
+ }
+
+ public void RemoveObserver(Action<object, object> handler, string notificationName)
+ {
+ RemoveObserver(handler, notificationName, null);
+ }
+
+ public void RemoveObserver(Action<object, object> handler, string notificationName, object sender)
+ {
+ if (handler == null)
+ {
+ Debug.LogError("Can't remove a null event handler for notification, " + notificationName);
+ }
+ else if (string.IsNullOrEmpty(notificationName))
+ {
+ Debug.LogError("A notification name is required to stop observation");
+ }
+ else
+ {
+ if (!_table.ContainsKey(notificationName))
+ {
+ return;
+ }
+ Dictionary<object, List<Action<object, object>>> dictionary = _table[notificationName];
+ object key = ((sender != null) ? sender : this);
+ if (!dictionary.ContainsKey(key))
+ {
+ return;
+ }
+ List<Action<object, object>> list = dictionary[key];
+ int num = list.IndexOf(handler);
+ if (num != -1)
+ {
+ if (_invoking.Contains(list))
+ {
+ list = (dictionary[key] = new List<Action<object, object>>(list));
+ }
+ list.RemoveAt(num);
+ }
+ }
+ }
+
+ public void Clean()
+ {
+ string[] array = new string[_table.Keys.Count];
+ _table.Keys.CopyTo(array, 0);
+ for (int num = array.Length - 1; num >= 0; num--)
+ {
+ string key = array[num];
+ Dictionary<object, List<Action<object, object>>> dictionary = _table[key];
+ object[] array2 = new object[dictionary.Keys.Count];
+ dictionary.Keys.CopyTo(array2, 0);
+ for (int num2 = array2.Length - 1; num2 >= 0; num2--)
+ {
+ object key2 = array2[num2];
+ if (dictionary[key2].Count == 0)
+ {
+ dictionary.Remove(key2);
+ }
+ }
+ if (dictionary.Count == 0)
+ {
+ _table.Remove(key);
+ }
+ }
+ }
+
+ public void PostNotification(string notificationName)
+ {
+ PostNotification(notificationName, null);
+ }
+
+ public void PostNotification(string notificationName, object sender)
+ {
+ PostNotification(notificationName, sender, null);
+ }
+
+ public void PostNotification(string notificationName, object sender, object e)
+ {
+ if (string.IsNullOrEmpty(notificationName))
+ {
+ Debug.LogError("A notification name is required");
+ }
+ else
+ {
+ if (!_table.ContainsKey(notificationName))
+ {
+ return;
+ }
+ Dictionary<object, List<Action<object, object>>> dictionary = _table[notificationName];
+ if (sender != null && dictionary.ContainsKey(sender))
+ {
+ List<Action<object, object>> list = dictionary[sender];
+ _invoking.Add(list);
+ for (int i = 0; i < list.Count; i++)
+ {
+ list[i](sender, e);
+ }
+ _invoking.Remove(list);
+ }
+ if (dictionary.ContainsKey(this))
+ {
+ List<Action<object, object>> list2 = dictionary[this];
+ _invoking.Add(list2);
+ for (int j = 0; j < list2.Count; j++)
+ {
+ list2[j](sender, e);
+ }
+ _invoking.Remove(list2);
+ }
+ }
+ }
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Tools/NotificationCenter.cs.meta b/WorldlineKeepers/Assets/Scripts/Tools/NotificationCenter.cs.meta
new file mode 100644
index 0000000..13d54ee
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Tools/NotificationCenter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f222398a57afbf446b471ccf17bb9575
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs
index 7674523..7674523 100644
--- a/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs
+++ b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs
diff --git a/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs.meta b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs.meta
index 330a2d3..330a2d3 100644
--- a/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs.meta
+++ b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs.meta
diff --git a/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterMetadata.cs b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterMetadata.cs
new file mode 100644
index 0000000..81b80c0
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterMetadata.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK.Data
+{
+
+ public class CharacterMetadata
+ {
+
+ public string uid;
+
+ public string name_key;
+
+ public Dictionary<string, string> stats;
+
+ public string behaviour;
+
+ public string extra_data;
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterMetadata.cs.meta b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterMetadata.cs.meta
new file mode 100644
index 0000000..f39e3ec
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterMetadata.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ecafd17226029e748994c5814d59cc03
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/WorldlineKeepers/Assets/Scripts/Unit/Characters/PlayerController.cs b/WorldlineKeepers/Assets/Scripts/Unit/Characters/PlayerController.cs
index 66bf6df..2f19fb3 100644
--- a/WorldlineKeepers/Assets/Scripts/Unit/Characters/PlayerController.cs
+++ b/WorldlineKeepers/Assets/Scripts/Unit/Characters/PlayerController.cs
@@ -7,9 +7,15 @@ namespace WK
public class PlayerController
{
+ /// <summary>
+ /// ɫеǰֵ
+ /// </summary>
private CharacterInfo m_CharacterInfo;
public CharacterInfo info { get { return m_CharacterInfo; } }
+ /// <summary>
+ /// ɫΪ߼
+ /// </summary>
private CharacterBehaviour m_CharacterBehaviour;
public CharacterBehaviour behaviour { get { return m_CharacterBehaviour; } }
diff --git a/WorldlineKeepers/Assets/Scripts/Unit/Characters/Ronin/RoninBehaviour.cs b/WorldlineKeepers/Assets/Scripts/Unit/Characters/Ronin/RoninBehaviour.cs
index 4a348eb..1964323 100644
--- a/WorldlineKeepers/Assets/Scripts/Unit/Characters/Ronin/RoninBehaviour.cs
+++ b/WorldlineKeepers/Assets/Scripts/Unit/Characters/Ronin/RoninBehaviour.cs
@@ -13,7 +13,8 @@ public class RoninBehaviour : CharacterBehaviour
if (info.stats["max_health"] != null)
{
- int health = info.stats["max_health"].value.i;
+ int health = info.stats["max_health"].intValue;
+
}
}
diff --git a/WorldlineKeepers/Assets/Scripts/Unit/Enemies/SpiritScript.cs b/WorldlineKeepers/Assets/Scripts/Unit/Enemies/SpiritScript.cs
index 7ebae9c..dbcab58 100644
--- a/WorldlineKeepers/Assets/Scripts/Unit/Enemies/SpiritScript.cs
+++ b/WorldlineKeepers/Assets/Scripts/Unit/Enemies/SpiritScript.cs
@@ -17,7 +17,7 @@ public class SpiritScript : UnitBase
private static List<IQuadTreeObject> collisions = new List<IQuadTreeObject>();
- private SpriteRenderer m_SpriteRenderer;
+ //private SpriteRenderer m_SpriteRenderer;
private int m_CollisionCheckerCount = 0;
@@ -32,7 +32,7 @@ public class SpiritScript : UnitBase
speed = 2;
TestSpirits.spirits.Add(this);
}
-
+
protected override void Update()
{
base.Update();
diff --git a/WorldlineKeepers/Assets/Scripts/Unit/UnitManager.cs b/WorldlineKeepers/Assets/Scripts/Unit/UnitManager.cs
new file mode 100644
index 0000000..9ec97f3
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Unit/UnitManager.cs
@@ -0,0 +1,15 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace WK
+{
+
+ public class UnitManager
+ {
+
+
+
+ }
+
+}
diff --git a/WorldlineKeepers/Assets/Scripts/Unit/UnitManager.cs.meta b/WorldlineKeepers/Assets/Scripts/Unit/UnitManager.cs.meta
new file mode 100644
index 0000000..a1d3faf
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Unit/UnitManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6c5e1e3ffbd73844aa887ef5d5a829f0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: