From 6fb204d494b897907d655b5752196983a82ceba2 Mon Sep 17 00:00:00 2001 From: chai <215380520@qq.com> Date: Sat, 13 May 2023 15:20:20 +0800 Subject: *misc --- .../Assets/Bundle/characters/ronin/ronin.json | 19 +- .../Assets/Bundle/metadata/default_items.csv | 2 + .../Assets/Bundle/metadata/default_items.csv.meta | 7 + WorldlineKeepers/Assets/Plugins.meta | 8 + .../Assets/Plugins/Trinary Software.meta | 9 + .../Assets/Plugins/Trinary Software/Editor.meta | 9 + .../Plugins/Trinary Software/Editor/MecIcon.png | Bin 0 -> 36388 bytes .../Trinary Software/Editor/MecIcon.png.meta | 57 + .../Plugins/Trinary Software/Quick Start Guide.pdf | Bin 0 -> 690071 bytes .../Trinary Software/Quick Start Guide.pdf.meta | 8 + .../Assets/Plugins/Trinary Software/Timing.cs | 2738 ++++++++++++++++++++ .../Assets/Plugins/Trinary Software/Timing.cs.meta | 12 + WorldlineKeepers/Assets/Scenes/Test.unity | 26 + WorldlineKeepers/Assets/Scripts/Buffs/Buff.cs | 2 +- .../Assets/Scripts/Buffs/BuffBehaviour.cs | 32 + .../Assets/Scripts/Buffs/BuffBehaviour.cs.meta | 11 + .../Assets/Scripts/Buffs/BuffEfectorBase.cs | 32 - .../Assets/Scripts/Buffs/BuffEfectorBase.cs.meta | 11 - .../Assets/Scripts/Common/Statemachine.cs | 254 ++ .../Assets/Scripts/Common/Statemachine.cs.meta | 11 + .../Assets/Scripts/Data/DataManager.cs | 13 + WorldlineKeepers/Assets/Scripts/EntityBase.cs | 2 +- WorldlineKeepers/Assets/Scripts/Items/Inventory.cs | 15 + .../Assets/Scripts/Items/Inventory.cs.meta | 11 + WorldlineKeepers/Assets/Scripts/Items/Item.cs | 21 + WorldlineKeepers/Assets/Scripts/Items/Item.cs.meta | 11 + .../Assets/Scripts/Items/ItemBehaviour.cs | 27 + .../Assets/Scripts/Items/ItemBehaviour.cs.meta | 11 + .../Assets/Scripts/Items/ItemDaggerBehaviour.cs | 15 + .../Scripts/Items/ItemDaggerBehaviour.cs.meta | 11 + .../Assets/Scripts/Items/ItemHellbellBehaviour.cs | 15 + .../Scripts/Items/ItemHellbellBehaviour.cs.meta | 11 + .../Assets/Scripts/Items/ItemMetadata.cs | 23 + .../Assets/Scripts/Items/ItemMetadata.cs.meta | 11 + WorldlineKeepers/Assets/Scripts/StaticDefine.cs | 2 + .../Assets/Scripts/Stats/CharacterStatsBase.cs | 28 +- .../Assets/Scripts/Stats/CharacterStatsMetadata.cs | 2 + WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs | 40 + .../Assets/Scripts/Tests/TestEvent.cs.meta | 11 + WorldlineKeepers/Assets/Scripts/Tools.meta | 8 + .../Assets/Scripts/Tools/GlobalEventManager.cs | 97 + .../Scripts/Tools/GlobalEventManager.cs.meta | 11 + .../Assets/Scripts/Tools/NotificationCenter.cs | 167 ++ .../Scripts/Tools/NotificationCenter.cs.meta | 11 + .../Scripts/Unit/Characters/CharacterBehaviour.cs | 32 + .../Unit/Characters/CharacterBehaviour.cs.meta | 11 + .../Scripts/Unit/Characters/CharacterController.cs | 32 - .../Unit/Characters/CharacterController.cs.meta | 11 - .../Scripts/Unit/Characters/CharacterMetadata.cs | 23 + .../Unit/Characters/CharacterMetadata.cs.meta | 11 + .../Scripts/Unit/Characters/PlayerController.cs | 6 + .../Unit/Characters/Ronin/RoninBehaviour.cs | 3 +- .../Assets/Scripts/Unit/Enemies/SpiritScript.cs | 4 +- .../Assets/Scripts/Unit/UnitManager.cs | 15 + .../Assets/Scripts/Unit/UnitManager.cs.meta | 11 + 55 files changed, 3872 insertions(+), 109 deletions(-) create mode 100644 WorldlineKeepers/Assets/Bundle/metadata/default_items.csv create mode 100644 WorldlineKeepers/Assets/Bundle/metadata/default_items.csv.meta create mode 100644 WorldlineKeepers/Assets/Plugins.meta create mode 100644 WorldlineKeepers/Assets/Plugins/Trinary Software.meta create mode 100644 WorldlineKeepers/Assets/Plugins/Trinary Software/Editor.meta create mode 100644 WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png create mode 100644 WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png.meta create mode 100644 WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf create mode 100644 WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf.meta create mode 100644 WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs create mode 100644 WorldlineKeepers/Assets/Plugins/Trinary Software/Timing.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs.meta delete mode 100644 WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs delete mode 100644 WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Common/Statemachine.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Common/Statemachine.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Items/Inventory.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Items/Inventory.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Items/Item.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Items/Item.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Items/ItemBehaviour.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Items/ItemBehaviour.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Items/ItemDaggerBehaviour.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Items/ItemDaggerBehaviour.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Items/ItemHellbellBehaviour.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Items/ItemHellbellBehaviour.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Items/ItemMetadata.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Items/ItemMetadata.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Tests/TestEvent.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Tools.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Tools/GlobalEventManager.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Tools/GlobalEventManager.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Tools/NotificationCenter.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Tools/NotificationCenter.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs.meta delete mode 100644 WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs delete mode 100644 WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterMetadata.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterMetadata.cs.meta create mode 100644 WorldlineKeepers/Assets/Scripts/Unit/UnitManager.cs create mode 100644 WorldlineKeepers/Assets/Scripts/Unit/UnitManager.cs.meta (limited to 'WorldlineKeepers/Assets') 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 Binary files /dev/null and b/WorldlineKeepers/Assets/Plugins/Trinary Software/Editor/MecIcon.png 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 Binary files /dev/null and b/WorldlineKeepers/Assets/Plugins/Trinary Software/Quick Start Guide.pdf 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 + { + /// + /// The time between calls to SlowUpdate. + /// + [Tooltip("How quickly the SlowUpdate segment ticks.")] + public float TimeBetweenSlowUpdateCalls = 1f / 7f; + /// + /// 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. + /// + [Tooltip("How much data should be sent to the profiler window when it's open.")] + public DebugInfoType ProfilerDebugAmount; + /// + /// The number of coroutines that are being run in the Update segment. + /// + [Tooltip("A count of the number of Update coroutines that are currently running."), Space(12)] + public int UpdateCoroutines; + /// + /// The number of coroutines that are being run in the FixedUpdate segment. + /// + [Tooltip("A count of the number of FixedUpdate coroutines that are currently running.")] + public int FixedUpdateCoroutines; + /// + /// The number of coroutines that are being run in the LateUpdate segment. + /// + [Tooltip("A count of the number of LateUpdate coroutines that are currently running.")] + public int LateUpdateCoroutines; + /// + /// The number of coroutines that are being run in the SlowUpdate segment. + /// + [Tooltip("A count of the number of SlowUpdate coroutines that are currently running.")] + public int SlowUpdateCoroutines; + /// + /// The time in seconds that the current segment has been running. + /// + [System.NonSerialized] + public float localTime; + /// + /// The time in seconds that the current segment has been running. + /// + public static float LocalTime { get { return Instance.localTime; } } + /// + /// The amount of time in fractional seconds that elapsed between this frame and the last frame. + /// + [System.NonSerialized] + public float deltaTime; + /// + /// The amount of time in fractional seconds that elapsed between this frame and the last frame. + /// + public static float DeltaTime { get { return Instance.deltaTime; } } + /// + /// Used for advanced coroutine control. + /// + public static System.Func, CoroutineHandle, IEnumerator> ReplacementFunction; + /// + /// This event fires just before each segment is run. + /// + public static event System.Action OnPreExecute; + /// + /// You can use "yield return Timing.WaitForOneFrame;" inside a coroutine function to go to the next frame. + /// + public const float WaitForOneFrame = float.NegativeInfinity; + /// + /// The main thread that (almost) everything in unity runs in. + /// + public static System.Threading.Thread MainThread { get; private set; } + /// + /// The handle of the current coroutine that is running. + /// + 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); + } + } + /// + /// The handle of the current coroutine that is running. + /// + 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> _waitingTriggers = new Dictionary>(); + private readonly HashSet _allWaiting = new HashSet(); + private readonly Dictionary _handleToIndex = new Dictionary(); + private readonly Dictionary _indexToHandle = new Dictionary(); + private readonly Dictionary _processTags = new Dictionary(); + private readonly Dictionary> _taggedProcesses = new Dictionary>(); + + private IEnumerator[] UpdateProcesses = new IEnumerator[InitialBufferSizeLarge]; + private IEnumerator[] LateUpdateProcesses = new IEnumerator[InitialBufferSizeSmall]; + private IEnumerator[] FixedUpdateProcesses = new IEnumerator[InitialBufferSizeMedium]; + private IEnumerator[] SlowUpdateProcesses = new IEnumerator[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() ?? instanceHome.AddComponent(); + + _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; + } + + /// + /// Run a new coroutine in the Update segment. + /// + /// The new coroutine's handle. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public static CoroutineHandle RunCoroutine(IEnumerator coroutine) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, Segment.Update, null, new CoroutineHandle(Instance._instanceID), true); + } + + /// + /// Run a new coroutine in the Update segment. + /// + /// The new coroutine's handle. + /// An optional tag to attach to the coroutine which can later be used for Kill operations. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public static CoroutineHandle RunCoroutine(IEnumerator coroutine, string tag) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, Segment.Update, tag, new CoroutineHandle(Instance._instanceID), true); + } + + /// + /// Run a new coroutine. + /// + /// The new coroutine's handle. + /// The segment that the coroutine should run in. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public static CoroutineHandle RunCoroutine(IEnumerator coroutine, Segment segment) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, segment, null, new CoroutineHandle(Instance._instanceID), true); + } + + /// + /// Run a new coroutine. + /// + /// The new coroutine's handle. + /// The segment that the coroutine should run in. + /// An optional tag to attach to the coroutine which can later be used for Kill operations. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public static CoroutineHandle RunCoroutine(IEnumerator coroutine, Segment segment, string tag) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, segment, tag, new CoroutineHandle(Instance._instanceID), true); + } + + /// + /// Run a new coroutine on this Timing instance in the Update segment. + /// + /// The new coroutine's handle. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public CoroutineHandle RunCoroutineOnInstance(IEnumerator coroutine) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, Segment.Update, null, new CoroutineHandle(_instanceID), true); + } + + /// + /// Run a new coroutine on this Timing instance in the Update segment. + /// + /// The new coroutine's handle. + /// An optional tag to attach to the coroutine which can later be used for Kill operations. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public CoroutineHandle RunCoroutineOnInstance(IEnumerator coroutine, string tag) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, Segment.Update, tag, new CoroutineHandle(_instanceID), true); + } + + /// + /// Run a new coroutine on this Timing instance. + /// + /// The new coroutine's handle. + /// The segment that the coroutine should run in. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public CoroutineHandle RunCoroutineOnInstance(IEnumerator coroutine, Segment segment) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, segment, null, new CoroutineHandle(_instanceID), true); + } + + /// + /// Run a new coroutine on this Timing instance. + /// + /// The new coroutine's handle. + /// The segment that the coroutine should run in. + /// An optional tag to attach to the coroutine which can later be used for Kill operations. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public CoroutineHandle RunCoroutineOnInstance(IEnumerator coroutine, Segment segment, string tag) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, segment, tag, new CoroutineHandle(_instanceID), true); + } + + + private CoroutineHandle RunCoroutineInternal(IEnumerator 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[] oldProcArray = UpdateProcesses; + bool[] oldPausedArray = UpdatePaused; + bool[] oldHeldArray = UpdateHeld; + + UpdateProcesses = new IEnumerator[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[] oldProcArray = FixedUpdateProcesses; + bool[] oldPausedArray = FixedUpdatePaused; + bool[] oldHeldArray = FixedUpdateHeld; + + FixedUpdateProcesses = new IEnumerator[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[] oldProcArray = LateUpdateProcesses; + bool[] oldPausedArray = LateUpdatePaused; + bool[] oldHeldArray = LateUpdateHeld; + + LateUpdateProcesses = new IEnumerator[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[] oldProcArray = SlowUpdateProcesses; + bool[] oldPausedArray = SlowUpdatePaused; + bool[] oldHeldArray = SlowUpdateHeld; + + SlowUpdateProcesses = new IEnumerator[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; + } + + /// + /// 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. + /// + /// The number of coroutines that were killed. + public static int KillCoroutines() + { + return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(); + } + + /// + /// 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. + /// + /// The number of coroutines that were killed. + public int KillCoroutinesOnInstance() + { + int retVal = _nextUpdateProcessSlot + _nextLateUpdateProcessSlot + _nextFixedUpdateProcessSlot + _nextSlowUpdateProcessSlot; + + UpdateProcesses = new IEnumerator[InitialBufferSizeLarge]; + UpdatePaused = new bool[InitialBufferSizeLarge]; + UpdateHeld = new bool[InitialBufferSizeLarge]; + UpdateCoroutines = 0; + _nextUpdateProcessSlot = 0; + + LateUpdateProcesses = new IEnumerator[InitialBufferSizeSmall]; + LateUpdatePaused = new bool[InitialBufferSizeSmall]; + LateUpdateHeld = new bool[InitialBufferSizeSmall]; + LateUpdateCoroutines = 0; + _nextLateUpdateProcessSlot = 0; + + FixedUpdateProcesses = new IEnumerator[InitialBufferSizeMedium]; + FixedUpdatePaused = new bool[InitialBufferSizeMedium]; + FixedUpdateHeld = new bool[InitialBufferSizeMedium]; + FixedUpdateCoroutines = 0; + _nextFixedUpdateProcessSlot = 0; + + SlowUpdateProcesses = new IEnumerator[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; + } + + /// + /// Kills the instances of the coroutine handle if it exists. + /// + /// The handle of the coroutine to kill. + /// The number of coroutines that were found and killed (0 or 1). + public static int KillCoroutines(CoroutineHandle handle) + { + return ActiveInstances[handle.Key] != null ? GetInstance(handle.Key).KillCoroutinesOnInstance(handle) : 0; + } + + /// + /// Kills the instance of the coroutine handle on this Timing instance if it exists. + /// + /// The handle of the coroutine to kill. + /// The number of coroutines that were found and killed (0 or 1). + 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; + } + + /// + /// Kills all coroutines that have the given tag. + /// + /// All coroutines with this tag will be killed. + /// The number of coroutines that were found and killed. + public static int KillCoroutines(string tag) + { + return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(tag); + } + + /// + /// Kills all coroutines that have the given tag. + /// + /// All coroutines with this tag will be killed. + /// The number of coroutines that were found and killed. + 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; + } + + /// + /// This will pause all coroutines running on the current MEC instance until ResumeCoroutines is called. + /// + /// The number of coroutines that were paused. + public static int PauseCoroutines() + { + return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(); + } + + /// + /// This will pause all coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called. + /// + /// The number of coroutines that were paused. + 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; + } + + /// + /// This will pause any matching coroutines until ResumeCoroutines is called. + /// + /// The handle of the coroutine to pause. + /// The number of coroutines that were paused (0 or 1). + public static int PauseCoroutines(CoroutineHandle handle) + { + return ActiveInstances[handle.Key] != null ? GetInstance(handle.Key).PauseCoroutinesOnInstance(handle) : 0; + } + + /// + /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called. + /// + /// The handle of the coroutine to pause. + /// The number of coroutines that were paused (0 or 1). + public int PauseCoroutinesOnInstance(CoroutineHandle handle) + { + return _handleToIndex.ContainsKey(handle) && !CoindexIsNull(_handleToIndex[handle]) && !SetPause(_handleToIndex[handle], true) ? 1 : 0; + } + + /// + /// This will pause any matching coroutines running on the current MEC instance until ResumeCoroutines is called. + /// + /// Any coroutines with a matching tag will be paused. + /// The number of coroutines that were paused. + public static int PauseCoroutines(string tag) + { + return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(tag); + } + + /// + /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called. + /// + /// Any coroutines with a matching tag will be paused. + /// The number of coroutines that were paused. + 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; + } + + /// + /// This resumes all coroutines on the current MEC instance if they are currently paused, otherwise it has + /// no effect. + /// + /// The number of coroutines that were resumed. + public static int ResumeCoroutines() + { + return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(); + } + + /// + /// This resumes all coroutines on this MEC instance if they are currently paused, otherwise it has no effect. + /// + /// The number of coroutines that were resumed. + 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; + } + + /// + /// This will resume any matching coroutines. + /// + /// The handle of the coroutine to resume. + /// The number of coroutines that were resumed (0 or 1). + public static int ResumeCoroutines(CoroutineHandle handle) + { + return ActiveInstances[handle.Key] != null ? GetInstance(handle.Key).ResumeCoroutinesOnInstance(handle) : 0; + } + + /// + /// This will resume any matching coroutines running on this MEC instance. + /// + /// The handle of the coroutine to resume. + /// The number of coroutines that were resumed (0 or 1). + public int ResumeCoroutinesOnInstance(CoroutineHandle handle) + { + return _handleToIndex.ContainsKey(handle) && + !CoindexIsNull(_handleToIndex[handle]) && SetPause(_handleToIndex[handle], false) ? 1 : 0; + } + + /// + /// This resumes any matching coroutines on the current MEC instance if they are currently paused, otherwise it has + /// no effect. + /// + /// Any coroutines previously paused with a matching tag will be resumend. + /// The number of coroutines that were resumed. + public static int ResumeCoroutines(string tag) + { + return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(tag); + } + + /// + /// This resumes any matching coroutines on this MEC instance if they are currently paused, otherwise it has no effect. + /// + /// Any coroutines previously paused with a matching tag will be resumend. + /// The number of coroutines that were resumed. + 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; + } + } + + /// + /// Retrieves the MEC manager that corresponds to the supplied instance id. + /// + /// The instance ID. + /// The manager, or null if not found. + 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 { 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); + } + } + + /// Whether it was already null. + 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 CoindexExtract(ProcessIndex coindex) + { + IEnumerator 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 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 _InjectDelay(IEnumerator 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 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; + } + } + + /// + /// Use "yield return Timing.WaitForSeconds(time);" to wait for the specified number of seconds. + /// + /// Number of seconds to wait. + public static float WaitForSeconds(float waitTime) + { + if (float.IsNaN(waitTime)) waitTime = 0f; + return LocalTime + waitTime; + } + + /// + /// Use "yield return timingInstance.WaitForSecondsOnInstance(time);" to wait for the specified number of seconds. + /// + /// Number of seconds to wait. + public float WaitForSecondsOnInstance(float waitTime) + { + if (float.IsNaN(waitTime)) waitTime = 0f; + return localTime + waitTime; + } + + /// + /// Use the command "yield return Timing.WaitUntilDone(otherCoroutine);" to pause the current + /// coroutine until otherCoroutine is done. + /// + /// The coroutine to pause for. + public static float WaitUntilDone(CoroutineHandle otherCoroutine) + { + return WaitUntilDone(otherCoroutine, true); + } + + /// + /// Use the command "yield return Timing.WaitUntilDone(otherCoroutine, false);" to pause the current + /// coroutine until otherCoroutine is done, supressing warnings. + /// + /// The coroutine to pause for. + /// Post a warning to the console if no hold action was actually performed. + 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()); + } + + 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 _StartWhenDone(CoroutineHandle handle, IEnumerator 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 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 ReturnTmpRefForRepFunc(IEnumerator coptr, CoroutineHandle handle) + { + return _tmpRef as IEnumerator; + } + +#if !UNITY_2018_3_OR_NEWER + /// + /// Use the command "yield return Timing.WaitUntilDone(wwwObject);" to pause the current + /// coroutine until the wwwObject is done. + /// + /// The www object to pause for. + public static float WaitUntilDone(WWW wwwObject) + { + if (wwwObject == null || wwwObject.isDone) return 0f; + + _tmpRef = wwwObject; + ReplacementFunction = WaitUntilDoneWwwHelper; + return float.NaN; + } + + + private static IEnumerator WaitUntilDoneWwwHelper(IEnumerator coptr, CoroutineHandle handle) + { + return _StartWhenDone(_tmpRef as WWW, coptr); + } + + private static IEnumerator _StartWhenDone(WWW www, IEnumerator pausedProc) + { + while (!www.isDone) + yield return WaitForOneFrame; + + _tmpRef = pausedProc; + ReplacementFunction = ReturnTmpRefForRepFunc; + yield return float.NaN; + } +#endif + + /// + /// Use the command "yield return Timing.WaitUntilDone(operation);" to pause the current + /// coroutine until the operation is done. + /// + /// The operation variable returned. + 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 _StartWhenDone(AsyncOperation operation, IEnumerator pausedProc) + { + while (!operation.isDone) + yield return WaitForOneFrame; + + _tmpRef = pausedProc; + ReplacementFunction = ReturnTmpRefForRepFunc; + yield return float.NaN; + } + + /// + /// Use the command "yield return Timing.WaitUntilDone(operation);" to pause the current + /// coroutine until the operation is done. + /// + /// The operation variable returned. + 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 _StartWhenDone(CustomYieldInstruction operation, IEnumerator pausedProc) + { + while (operation.keepWaiting) + yield return WaitForOneFrame; + + _tmpRef = pausedProc; + ReplacementFunction = ReturnTmpRefForRepFunc; + yield return float.NaN; + } + + /// + /// Keeps this coroutine from executing until UnlockCoroutine is called with a matching key. + /// + /// The handle to the coroutine to be locked. + /// The key to use. A new key can be generated by calling "new CoroutineHandle(0)". + /// Whether the lock was successful. + 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 { coroutine }); + else + _waitingTriggers[key].Add(coroutine); + + _allWaiting.Add(coroutine); + + SetHeld(_handleToIndex[coroutine], true); + + return true; + } + + /// + /// Unlocks a coroutine that has been locked, so long as the key matches. + /// + /// The handle to the coroutine to be unlocked. + /// The key that the coroutine was previously locked with. + /// Whether the coroutine was successfully unlocked. + 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; + } + + /// + /// Calls the specified action after a specified number of seconds. + /// + /// The number of seconds to wait before calling the action. + /// The action to call. + /// The handle to the coroutine that is started by this function. + public static CoroutineHandle CallDelayed(float delay, System.Action action) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, null)); + } + + /// + /// Calls the specified action after a specified number of seconds. + /// + /// The number of seconds to wait before calling the action. + /// The action to call. + /// The handle to the coroutine that is started by this function. + public CoroutineHandle CallDelayedOnInstance(float delay, System.Action action) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, null)); + } + + /// + /// Calls the specified action after a specified number of seconds. + /// + /// The number of seconds to wait before calling the action. + /// The action to call. + /// A GameObject that will be checked to make sure it hasn't been destroyed before calling the action. + /// The handle to the coroutine that is started by this function. + public static CoroutineHandle CallDelayed(float delay, System.Action action, GameObject cancelWith) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, cancelWith)); + } + + /// + /// Calls the specified action after a specified number of seconds. + /// + /// The number of seconds to wait before calling the action. + /// The action to call. + /// A GameObject that will be checked to make sure it hasn't been destroyed before calling the action. + /// The handle to the coroutine that is started by this function. + public CoroutineHandle CallDelayedOnInstance(float delay, System.Action action, GameObject cancelWith) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, cancelWith)); + } + + /// + /// Calls the specified action after a specified number of seconds. + /// + /// The number of seconds to wait before calling the action. + /// The action to call. + /// The timing segment that the call should be made in. + /// The handle to the coroutine that is started by this function. + public static CoroutineHandle CallDelayed(float delay, Segment segment, System.Action action) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action, null), segment); + } + + /// + /// Calls the specified action after a specified number of seconds. + /// + /// The number of seconds to wait before calling the action. + /// The action to call. + /// The timing segment that the call should be made in. + /// The handle to the coroutine that is started by this function. + public CoroutineHandle CallDelayedOnInstance(float delay, Segment segment, System.Action action) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action, null), segment); + } + + /// + /// Calls the specified action after a specified number of seconds. + /// + /// The number of seconds to wait before calling the action. + /// The action to call. + /// A GameObject that will be checked to make sure it hasn't been destroyed + /// before calling the action. + /// The timing segment that the call should be made in. + /// The handle to the coroutine that is started by this function. + 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); + } + + /// + /// Calls the specified action after a specified number of seconds. + /// + /// The number of seconds to wait before calling the action. + /// The action to call. + /// A GameObject that will be tagged onto the coroutine and checked to make sure it hasn't been destroyed + /// before calling the action. + /// The timing segment that the call should be made in. + /// The handle to the coroutine that is started by this function. + 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 _DelayedCall(float delay, System.Action action, GameObject cancelWith) + { + yield return WaitForSecondsOnInstance(delay); + + if(ReferenceEquals(cancelWith, null) || cancelWith != null) + action(); + } + + /// + /// Calls the supplied action at the given rate for a given number of seconds. + /// + /// The number of seconds that this function should run. + /// The amount of time between calls. + /// The action to call every frame. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + 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); + } + + /// + /// Calls the supplied action at the given rate for a given number of seconds. + /// + /// The number of seconds that this function should run. + /// The amount of time between calls. + /// The action to call every frame. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + 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); + } + + /// + /// Calls the supplied action at the given rate for a given number of seconds. + /// + /// The number of seconds that this function should run. + /// The amount of time between calls. + /// The action to call every frame. + /// The timing segment to run in. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + 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); + } + + /// + /// Calls the supplied action at the given rate for a given number of seconds. + /// + /// The number of seconds that this function should run. + /// The amount of time between calls. + /// The action to call every frame. + /// The timing segment to run in. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + 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); + } + + /// + /// Calls the supplied action at the given rate for a given number of seconds. + /// + /// The number of seconds that this function should run. + /// The action to call every frame. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + 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); + } + + /// + /// Calls the supplied action at the given rate for a given number of seconds. + /// + /// The number of seconds that this function should run. + /// The action to call every frame. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + 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); + } + + /// + /// Calls the supplied action every frame for a given number of seconds. + /// + /// The number of seconds that this function should run. + /// The action to call every frame. + /// The timing segment to run in. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + 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); + } + + /// + /// Calls the supplied action every frame for a given number of seconds. + /// + /// The number of seconds that this function should run. + /// The action to call every frame. + /// The timing segment to run in. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + 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 _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(); + } + + /// + /// Calls the supplied action at the given rate for a given number of seconds. + /// + /// A value that will be passed in to the supplied action each period. + /// The number of seconds that this function should run. + /// The amount of time between calls. + /// The action to call every frame. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + public static CoroutineHandle CallPeriodically + (T reference, float timeframe, float period, System.Action action, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : + RunCoroutine(Instance._CallContinuously(reference, timeframe, period, action, onDone), Segment.Update); + } + + /// + /// Calls the supplied action at the given rate for a given number of seconds. + /// + /// A value that will be passed in to the supplied action each period. + /// The number of seconds that this function should run. + /// The amount of time between calls. + /// The action to call every frame. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + public CoroutineHandle CallPeriodicallyOnInstance + (T reference, float timeframe, float period, System.Action action, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : + RunCoroutineOnInstance(_CallContinuously(reference, timeframe, period, action, onDone), Segment.Update); + } + + /// + /// Calls the supplied action at the given rate for a given number of seconds. + /// + /// A value that will be passed in to the supplied action each period. + /// The number of seconds that this function should run. + /// The amount of time between calls. + /// The action to call every frame. + /// The timing segment to run in. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + public static CoroutineHandle CallPeriodically(T reference, float timeframe, float period, System.Action action, + Segment timing, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : + RunCoroutine(Instance._CallContinuously(reference, timeframe, period, action, onDone), timing); + } + + /// + /// Calls the supplied action at the given rate for a given number of seconds. + /// + /// A value that will be passed in to the supplied action each period. + /// The number of seconds that this function should run. + /// The amount of time between calls. + /// The action to call every frame. + /// The timing segment to run in. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + public CoroutineHandle CallPeriodicallyOnInstance(T reference, float timeframe, float period, System.Action action, + Segment timing, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : + RunCoroutineOnInstance(_CallContinuously(reference, timeframe, period, action, onDone), timing); + } + + /// + /// Calls the supplied action every frame for a given number of seconds. + /// + /// A value that will be passed in to the supplied action each frame. + /// The number of seconds that this function should run. + /// The action to call every frame. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + public static CoroutineHandle CallContinuously(T reference, float timeframe, System.Action action, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : + RunCoroutine(Instance._CallContinuously(reference, timeframe, 0f, action, onDone), Segment.Update); + } + + /// + /// Calls the supplied action every frame for a given number of seconds. + /// + /// A value that will be passed in to the supplied action each frame. + /// The number of seconds that this function should run. + /// The action to call every frame. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + public CoroutineHandle CallContinuouslyOnInstance(T reference, float timeframe, System.Action action, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : + RunCoroutineOnInstance(_CallContinuously(reference, timeframe, 0f, action, onDone), Segment.Update); + } + + /// + /// Calls the supplied action every frame for a given number of seconds. + /// + /// A value that will be passed in to the supplied action each frame. + /// The number of seconds that this function should run. + /// The action to call every frame. + /// The timing segment to run in. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + public static CoroutineHandle CallContinuously(T reference, float timeframe, System.Action action, + Segment timing, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : + RunCoroutine(Instance._CallContinuously(reference, timeframe, 0f, action, onDone), timing); + } + + /// + /// Calls the supplied action every frame for a given number of seconds. + /// + /// A value that will be passed in to the supplied action each frame. + /// The number of seconds that this function should run. + /// The action to call every frame. + /// The timing segment to run in. + /// An optional action to call when this function finishes. + /// The handle to the coroutine that is started by this function. + public CoroutineHandle CallContinuouslyOnInstance(T reference, float timeframe, System.Action action, + Segment timing, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : + RunCoroutineOnInstance(_CallContinuously(reference, timeframe, 0f, action, onDone), timing); + } + + private IEnumerator _CallContinuously(T reference, float timeframe, float period, + System.Action action, System.Action 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 + { + 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 original) where T : Object { } + + [System.Obsolete("Just.. no.", true)] + public new static T FindObjectOfType() 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() 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) { } + } + + /// + /// The timing segment that a coroutine is running in or should be run in. + /// + public enum Segment + { + /// + /// Sometimes returned as an error state + /// + Invalid = -1, + /// + /// This is the default timing segment + /// + Update, + /// + /// This is primarily used for physics calculations + /// + FixedUpdate, + /// + /// This is run immediately after update + /// + LateUpdate, + /// + /// This executes, by default, about as quickly as the eye can detect changes in a text field + /// + SlowUpdate + } + + /// + /// 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. + /// + public enum DebugInfoType + { + /// + /// None coroutines will be separated in the Unity profiler + /// + None, + /// + /// The Unity profiler will identify each coroutine individually + /// + SeperateCoroutines, + /// + /// Coroutines will be separated and any tags or layers will be identified + /// + SeperateTags + } + + /// + /// A handle for a MEC coroutine. + /// + public struct CoroutineHandle : System.IEquatable + { + 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; + } + + /// + /// 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) + /// + public bool IsValid + { + get { return Key != 0; } + } + } + + public static class MECExtensionMethods1 + { + /// + /// Run a new coroutine in the Update segment. + /// + /// The new coroutine's handle. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public static CoroutineHandle RunCoroutine(this IEnumerator coroutine) + { + return Timing.RunCoroutine(coroutine); + } + + /// + /// Run a new coroutine in the Update segment. + /// + /// The new coroutine's handle. + /// An optional tag to attach to the coroutine which can later be used to identify this coroutine. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public static CoroutineHandle RunCoroutine(this IEnumerator coroutine, string tag) + { + return Timing.RunCoroutine(coroutine, tag); + } + + /// + /// Run a new coroutine. + /// + /// The new coroutine's handle. + /// The segment that the coroutine should run in. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public static CoroutineHandle RunCoroutine(this IEnumerator coroutine, Segment segment) + { + return Timing.RunCoroutine(coroutine, segment); + } + + /// + /// Run a new coroutine. + /// + /// The new coroutine's handle. + /// The segment that the coroutine should run in. + /// An optional tag to attach to the coroutine which can later be used to identify this coroutine. + /// The coroutine's handle, which can be used for Wait and Kill operations. + public static CoroutineHandle RunCoroutine(this IEnumerator coroutine, Segment segment, string tag) + { + return Timing.RunCoroutine(coroutine, segment, tag); + } + } +} + +public static class MECExtensionMethods2 +{ + /// + /// Cancels this coroutine when the supplied game object is destroyed or made inactive. + /// + /// The coroutine handle to act upon. + /// The GameObject to test. + /// The modified coroutine handle. + public static IEnumerator CancelWith(this IEnumerator coroutine, GameObject gameObject) + { + while (MEC.Timing.MainThread != System.Threading.Thread.CurrentThread || (gameObject && gameObject.activeInHierarchy && coroutine.MoveNext())) + yield return coroutine.Current; + } + + /// + /// Cancels this coroutine when the supplied game objects are destroyed or made inactive. + /// + /// The coroutine handle to act upon. + /// The first GameObject to test. + /// The second GameObject to test + /// The modified coroutine handle. + public static IEnumerator CancelWith(this IEnumerator 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; + } + + /// + /// Cancels this coroutine when the supplied game objects are destroyed or made inactive. + /// + /// The coroutine handle to act upon. + /// The first GameObject to test. + /// The second GameObject to test + /// The third GameObject to test. + /// The modified coroutine handle. + public static IEnumerator CancelWith(this IEnumerator 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/BuffBehaviour.cs b/WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs new file mode 100644 index 0000000..0a0559f --- /dev/null +++ b/WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs @@ -0,0 +1,32 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class BuffBehaviour +{ + private CharacterBase m_Character; + + /// + /// buff生成时候 + /// + public virtual void OnCreate() + { + + } + + /// + /// 更新 + /// + public virtual void OnUpdate() + { + + } + + /// + /// 角色死亡 + /// + public virtual void OnCharacterDeath() + { + } + +} diff --git a/WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs.meta b/WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs.meta new file mode 100644 index 0000000..a433744 --- /dev/null +++ b/WorldlineKeepers/Assets/Scripts/Buffs/BuffBehaviour.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5dabb53754f969c4194ad10b2b9fc154 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs b/WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs deleted file mode 100644 index b90beb8..0000000 --- a/WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class BuffEfectorBase -{ - private CharacterBase m_Character; - - /// - /// buff生成时候 - /// - public virtual void OnCreate() - { - - } - - /// - /// 更新 - /// - public virtual void OnUpdate() - { - - } - - /// - /// 角色死亡 - /// - public virtual void OnCharacterDeath() - { - } - -} diff --git a/WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs.meta b/WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs.meta deleted file mode 100644 index a433744..0000000 --- a/WorldlineKeepers/Assets/Scripts/Buffs/BuffEfectorBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5dabb53754f969c4194ad10b2b9fc154 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: 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 +{ + + /// + /// ״̬ + /// + public class StateMachine + { + + public delegate void LoadStateComplete(); + + public abstract class State + { + public StateMachine owner; + public int stateID; + public abstract IEnumerator OnStart(); + public abstract IEnumerator OnEnd(); + public abstract void OnUpdate(float deltaTime); + } + + public const int NULL_STATE_ID = -1; + public const float COROUINT_DELTIME = 0.01f; + + private Dictionary allState = new Dictionary(); + private int curStateID = NULL_STATE_ID; + private int stateIDDistributor = 0; + // ״̬лǰΪfalse,ܽupdate + private bool isUpdateActive = false; + + /// + /// ״̬״̬еID + /// + /// + /// + 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; + } + + /// + /// ʼ״̬ + /// + /// + /// + public bool Start(int stateID) + { + if (!HasBegin()) + { + ForceGotoState(stateID); + return true; + } + return false; + } + + /// + /// ״̬ + /// + /// + public bool Stop() + { + if (HasBegin()) + { + ForceGotoState(NULL_STATE_ID); + return true; + } + return false; + } + + /// + /// ״̬ + /// + /// + 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; + } + + /// + /// 첽лij״̬ + /// + /// + private IEnumerator 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 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 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 m_CharacterStatsMetadata = new Dictionary(); private Dictionary m_BuffMetadata = new Dictionary(); + private Dictionary m_CharacterMetadata = new Dictionary(); 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(StaticDefine.RoninPath); + CharacterMetadata metadata = JsonMapper.ToObject(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 /// ǰֵ /// 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 +{ + /// + /// ȫ¼ + /// + public class GlobalEventManager : Singleton + { + + // callback + public delegate void EventCallback(params object[] objs); + public Dictionary> AllEvents = new Dictionary>(); + + public void Register(string eventName, EventCallback callback, bool addFirst = false) + { + if (callback == null) + { + Debug.LogError("Ϊ"); + return; + } + LinkedList list; + if (!AllEvents.TryGetValue(eventName, out list)) + { + list = new LinkedList(); // ôӳ + 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 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 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>>> _table = new Dictionary>>>(); + + private HashSet>> _invoking = new HashSet>>(); + + public static readonly NotificationCenter instance = new NotificationCenter(); + + private NotificationCenter() + { + } + + public void AddObserver(Action handler, string notificationName) + { + AddObserver(handler, notificationName, null); + } + + public void AddObserver(Action 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>>()); + } + Dictionary>> dictionary = _table[notificationName]; + object key = ((sender != null) ? sender : this); + if (!dictionary.ContainsKey(key)) + { + dictionary.Add(key, new List>()); + } + List> list = dictionary[key]; + if (_invoking.Contains(list)) + { + list = (dictionary[key] = new List>(list)); + } + list.Add(handler); + } + + public void RemoveObserver(Action handler, string notificationName) + { + RemoveObserver(handler, notificationName, null); + } + + public void RemoveObserver(Action 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>> dictionary = _table[notificationName]; + object key = ((sender != null) ? sender : this); + if (!dictionary.ContainsKey(key)) + { + return; + } + List> list = dictionary[key]; + int num = list.IndexOf(handler); + if (num != -1) + { + if (_invoking.Contains(list)) + { + list = (dictionary[key] = new List>(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>> 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>> dictionary = _table[notificationName]; + if (sender != null && dictionary.ContainsKey(sender)) + { + List> 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> 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/CharacterBehaviour.cs b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs new file mode 100644 index 0000000..7674523 --- /dev/null +++ b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs @@ -0,0 +1,32 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace WK +{ + + /// + /// ɫ淨Ϊǽɫ淨ġҪ̳ʵ + /// + public abstract class CharacterBehaviour + { + private PlayerController m_Controller; + public PlayerController controller { get { return m_Controller; } } + + public CharacterInfo info { get { return m_Controller.info; } } + + public virtual void OnCreate() + { + } + + public virtual void OnGlobalUpdate() + { + } + + public virtual void OnStageUpdate() + { + } + + } + +} \ No newline at end of file diff --git a/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs.meta b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs.meta new file mode 100644 index 0000000..330a2d3 --- /dev/null +++ b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterBehaviour.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 65afd074deb4dbc468bd8d8940712002 +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/CharacterController.cs deleted file mode 100644 index 7674523..0000000 --- a/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -namespace WK -{ - - /// - /// ɫ淨Ϊǽɫ淨ġҪ̳ʵ - /// - public abstract class CharacterBehaviour - { - private PlayerController m_Controller; - public PlayerController controller { get { return m_Controller; } } - - public CharacterInfo info { get { return m_Controller.info; } } - - public virtual void OnCreate() - { - } - - public virtual void OnGlobalUpdate() - { - } - - public virtual void OnStageUpdate() - { - } - - } - -} \ No newline at end of file diff --git a/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs.meta b/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs.meta deleted file mode 100644 index 330a2d3..0000000 --- a/WorldlineKeepers/Assets/Scripts/Unit/Characters/CharacterController.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 65afd074deb4dbc468bd8d8940712002 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: 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 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 { + /// + /// ɫеǰֵ + /// private CharacterInfo m_CharacterInfo; public CharacterInfo info { get { return m_CharacterInfo; } } + /// + /// ɫΪ߼ + /// 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 collisions = new List(); - 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: -- cgit v1.1-26-g67d0