You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
577 lines
22 KiB
577 lines
22 KiB
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member |
|
|
|
using System; |
|
using System.Linq; |
|
using UnityEngine; |
|
using Cysharp.Threading.Tasks.Internal; |
|
using System.Threading; |
|
|
|
#if UNITY_2019_3_OR_NEWER |
|
using UnityEngine.LowLevel; |
|
using PlayerLoopType = UnityEngine.PlayerLoop; |
|
#else |
|
using UnityEngine.Experimental.LowLevel; |
|
using PlayerLoopType = UnityEngine.Experimental.PlayerLoop; |
|
#endif |
|
|
|
#if UNITY_EDITOR |
|
using UnityEditor; |
|
#endif |
|
|
|
namespace Cysharp.Threading.Tasks |
|
{ |
|
public static class UniTaskLoopRunners |
|
{ |
|
public struct UniTaskLoopRunnerInitialization { }; |
|
public struct UniTaskLoopRunnerEarlyUpdate { }; |
|
public struct UniTaskLoopRunnerFixedUpdate { }; |
|
public struct UniTaskLoopRunnerPreUpdate { }; |
|
public struct UniTaskLoopRunnerUpdate { }; |
|
public struct UniTaskLoopRunnerPreLateUpdate { }; |
|
public struct UniTaskLoopRunnerPostLateUpdate { }; |
|
|
|
// Last |
|
|
|
public struct UniTaskLoopRunnerLastInitialization { }; |
|
public struct UniTaskLoopRunnerLastEarlyUpdate { }; |
|
public struct UniTaskLoopRunnerLastFixedUpdate { }; |
|
public struct UniTaskLoopRunnerLastPreUpdate { }; |
|
public struct UniTaskLoopRunnerLastUpdate { }; |
|
public struct UniTaskLoopRunnerLastPreLateUpdate { }; |
|
public struct UniTaskLoopRunnerLastPostLateUpdate { }; |
|
|
|
// Yield |
|
|
|
public struct UniTaskLoopRunnerYieldInitialization { }; |
|
public struct UniTaskLoopRunnerYieldEarlyUpdate { }; |
|
public struct UniTaskLoopRunnerYieldFixedUpdate { }; |
|
public struct UniTaskLoopRunnerYieldPreUpdate { }; |
|
public struct UniTaskLoopRunnerYieldUpdate { }; |
|
public struct UniTaskLoopRunnerYieldPreLateUpdate { }; |
|
public struct UniTaskLoopRunnerYieldPostLateUpdate { }; |
|
|
|
// Yield Last |
|
|
|
public struct UniTaskLoopRunnerLastYieldInitialization { }; |
|
public struct UniTaskLoopRunnerLastYieldEarlyUpdate { }; |
|
public struct UniTaskLoopRunnerLastYieldFixedUpdate { }; |
|
public struct UniTaskLoopRunnerLastYieldPreUpdate { }; |
|
public struct UniTaskLoopRunnerLastYieldUpdate { }; |
|
public struct UniTaskLoopRunnerLastYieldPreLateUpdate { }; |
|
public struct UniTaskLoopRunnerLastYieldPostLateUpdate { }; |
|
|
|
#if UNITY_2020_2_OR_NEWER |
|
public struct UniTaskLoopRunnerTimeUpdate { }; |
|
public struct UniTaskLoopRunnerLastTimeUpdate { }; |
|
public struct UniTaskLoopRunnerYieldTimeUpdate { }; |
|
public struct UniTaskLoopRunnerLastYieldTimeUpdate { }; |
|
#endif |
|
} |
|
|
|
public enum PlayerLoopTiming |
|
{ |
|
Initialization = 0, |
|
LastInitialization = 1, |
|
|
|
EarlyUpdate = 2, |
|
LastEarlyUpdate = 3, |
|
|
|
FixedUpdate = 4, |
|
LastFixedUpdate = 5, |
|
|
|
PreUpdate = 6, |
|
LastPreUpdate = 7, |
|
|
|
Update = 8, |
|
LastUpdate = 9, |
|
|
|
PreLateUpdate = 10, |
|
LastPreLateUpdate = 11, |
|
|
|
PostLateUpdate = 12, |
|
LastPostLateUpdate = 13, |
|
|
|
#if UNITY_2020_2_OR_NEWER |
|
// Unity 2020.2 added TimeUpdate https://docs.unity3d.com/2020.2/Documentation/ScriptReference/PlayerLoop.TimeUpdate.html |
|
TimeUpdate = 14, |
|
LastTimeUpdate = 15, |
|
#endif |
|
} |
|
|
|
[Flags] |
|
public enum InjectPlayerLoopTimings |
|
{ |
|
/// <summary> |
|
/// Preset: All loops(default). |
|
/// </summary> |
|
All = |
|
Initialization | LastInitialization | |
|
EarlyUpdate | LastEarlyUpdate | |
|
FixedUpdate | LastFixedUpdate | |
|
PreUpdate | LastPreUpdate | |
|
Update | LastUpdate | |
|
PreLateUpdate | LastPreLateUpdate | |
|
PostLateUpdate | LastPostLateUpdate |
|
#if UNITY_2020_2_OR_NEWER |
|
| TimeUpdate | LastTimeUpdate, |
|
#else |
|
, |
|
#endif |
|
|
|
/// <summary> |
|
/// Preset: All without last except LastPostLateUpdate. |
|
/// </summary> |
|
Standard = |
|
Initialization | |
|
EarlyUpdate | |
|
FixedUpdate | |
|
PreUpdate | |
|
Update | |
|
PreLateUpdate | |
|
PostLateUpdate | LastPostLateUpdate |
|
#if UNITY_2020_2_OR_NEWER |
|
| TimeUpdate |
|
#endif |
|
, |
|
|
|
/// <summary> |
|
/// Preset: Minimum pattern, Update | FixedUpdate | LastPostLateUpdate |
|
/// </summary> |
|
Minimum = |
|
Update | FixedUpdate | LastPostLateUpdate, |
|
|
|
// PlayerLoopTiming |
|
|
|
Initialization = 1, |
|
LastInitialization = 2, |
|
|
|
EarlyUpdate = 4, |
|
LastEarlyUpdate = 8, |
|
|
|
FixedUpdate = 16, |
|
LastFixedUpdate = 32, |
|
|
|
PreUpdate = 64, |
|
LastPreUpdate = 128, |
|
|
|
Update = 256, |
|
LastUpdate = 512, |
|
|
|
PreLateUpdate = 1024, |
|
LastPreLateUpdate = 2048, |
|
|
|
PostLateUpdate = 4096, |
|
LastPostLateUpdate = 8192 |
|
|
|
#if UNITY_2020_2_OR_NEWER |
|
, |
|
// Unity 2020.2 added TimeUpdate https://docs.unity3d.com/2020.2/Documentation/ScriptReference/PlayerLoop.TimeUpdate.html |
|
TimeUpdate = 16384, |
|
LastTimeUpdate = 32768 |
|
#endif |
|
} |
|
|
|
public interface IPlayerLoopItem |
|
{ |
|
bool MoveNext(); |
|
} |
|
|
|
public static class PlayerLoopHelper |
|
{ |
|
static readonly ContinuationQueue ThrowMarkerContinuationQueue = new ContinuationQueue(PlayerLoopTiming.Initialization); |
|
static readonly PlayerLoopRunner ThrowMarkerPlayerLoopRunner = new PlayerLoopRunner(PlayerLoopTiming.Initialization); |
|
|
|
public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContext; |
|
public static int MainThreadId => mainThreadId; |
|
internal static string ApplicationDataPath => applicationDataPath; |
|
|
|
public static bool IsMainThread => Thread.CurrentThread.ManagedThreadId == mainThreadId; |
|
|
|
static int mainThreadId; |
|
static string applicationDataPath; |
|
static SynchronizationContext unitySynchronizationContext; |
|
static ContinuationQueue[] yielders; |
|
static PlayerLoopRunner[] runners; |
|
internal static bool IsEditorApplicationQuitting { get; private set; } |
|
static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem loopSystem, |
|
bool injectOnFirst, |
|
Type loopRunnerYieldType, ContinuationQueue cq, |
|
Type loopRunnerType, PlayerLoopRunner runner) |
|
{ |
|
|
|
#if UNITY_EDITOR |
|
EditorApplication.playModeStateChanged += (state) => |
|
{ |
|
if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.ExitingEditMode) |
|
{ |
|
IsEditorApplicationQuitting = true; |
|
// run rest action before clear. |
|
if (runner != null) |
|
{ |
|
runner.Run(); |
|
runner.Clear(); |
|
} |
|
if (cq != null) |
|
{ |
|
cq.Run(); |
|
cq.Clear(); |
|
} |
|
IsEditorApplicationQuitting = false; |
|
} |
|
}; |
|
#endif |
|
|
|
var yieldLoop = new PlayerLoopSystem |
|
{ |
|
type = loopRunnerYieldType, |
|
updateDelegate = cq.Run |
|
}; |
|
|
|
var runnerLoop = new PlayerLoopSystem |
|
{ |
|
type = loopRunnerType, |
|
updateDelegate = runner.Run |
|
}; |
|
|
|
// Remove items from previous initializations. |
|
var source = RemoveRunner(loopSystem, loopRunnerYieldType, loopRunnerType); |
|
var dest = new PlayerLoopSystem[source.Length + 2]; |
|
|
|
Array.Copy(source, 0, dest, injectOnFirst ? 2 : 0, source.Length); |
|
if (injectOnFirst) |
|
{ |
|
dest[0] = yieldLoop; |
|
dest[1] = runnerLoop; |
|
} |
|
else |
|
{ |
|
dest[dest.Length - 2] = yieldLoop; |
|
dest[dest.Length - 1] = runnerLoop; |
|
} |
|
|
|
return dest; |
|
} |
|
|
|
static PlayerLoopSystem[] RemoveRunner(PlayerLoopSystem loopSystem, Type loopRunnerYieldType, Type loopRunnerType) |
|
{ |
|
return loopSystem.subSystemList |
|
.Where(ls => ls.type != loopRunnerYieldType && ls.type != loopRunnerType) |
|
.ToArray(); |
|
} |
|
|
|
static PlayerLoopSystem[] InsertUniTaskSynchronizationContext(PlayerLoopSystem loopSystem) |
|
{ |
|
var loop = new PlayerLoopSystem |
|
{ |
|
type = typeof(UniTaskSynchronizationContext), |
|
updateDelegate = UniTaskSynchronizationContext.Run |
|
}; |
|
|
|
// Remove items from previous initializations. |
|
var source = loopSystem.subSystemList |
|
.Where(ls => ls.type != typeof(UniTaskSynchronizationContext)) |
|
.ToArray(); |
|
|
|
var dest = new System.Collections.Generic.List<PlayerLoopSystem>(source); |
|
|
|
var index = dest.FindIndex(x => x.type.Name == "ScriptRunDelayedTasks"); |
|
if (index == -1) |
|
{ |
|
index = dest.FindIndex(x => x.type.Name == "UniTaskLoopRunnerUpdate"); |
|
} |
|
|
|
dest.Insert(index + 1, loop); |
|
|
|
return dest.ToArray(); |
|
} |
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] |
|
static void Init() |
|
{ |
|
// capture default(unity) sync-context. |
|
unitySynchronizationContext = SynchronizationContext.Current; |
|
mainThreadId = Thread.CurrentThread.ManagedThreadId; |
|
try |
|
{ |
|
applicationDataPath = Application.dataPath; |
|
} |
|
catch { } |
|
|
|
#if UNITY_EDITOR && UNITY_2019_3_OR_NEWER |
|
// When domain reload is disabled, re-initialization is required when entering play mode; |
|
// otherwise, pending tasks will leak between play mode sessions. |
|
var domainReloadDisabled = UnityEditor.EditorSettings.enterPlayModeOptionsEnabled && |
|
UnityEditor.EditorSettings.enterPlayModeOptions.HasFlag(UnityEditor.EnterPlayModeOptions.DisableDomainReload); |
|
if (!domainReloadDisabled && runners != null) return; |
|
#else |
|
if (runners != null) return; // already initialized |
|
#endif |
|
|
|
var playerLoop = |
|
#if UNITY_2019_3_OR_NEWER |
|
PlayerLoop.GetCurrentPlayerLoop(); |
|
#else |
|
PlayerLoop.GetDefaultPlayerLoop(); |
|
#endif |
|
|
|
Initialize(ref playerLoop); |
|
} |
|
|
|
|
|
#if UNITY_EDITOR |
|
|
|
[InitializeOnLoadMethod] |
|
static void InitOnEditor() |
|
{ |
|
// Execute the play mode init method |
|
Init(); |
|
|
|
// register an Editor update delegate, used to forcing playerLoop update |
|
EditorApplication.update += ForceEditorPlayerLoopUpdate; |
|
} |
|
|
|
private static void ForceEditorPlayerLoopUpdate() |
|
{ |
|
if (EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isCompiling || EditorApplication.isUpdating) |
|
{ |
|
// Not in Edit mode, don't interfere |
|
return; |
|
} |
|
|
|
// EditorApplication.QueuePlayerLoopUpdate causes performance issue, don't call directly. |
|
// EditorApplication.QueuePlayerLoopUpdate(); |
|
|
|
if (yielders != null) |
|
{ |
|
foreach (var item in yielders) |
|
{ |
|
if (item != null) item.Run(); |
|
} |
|
} |
|
|
|
if (runners != null) |
|
{ |
|
foreach (var item in runners) |
|
{ |
|
if (item != null) item.Run(); |
|
} |
|
} |
|
|
|
UniTaskSynchronizationContext.Run(); |
|
} |
|
|
|
#endif |
|
|
|
private static int FindLoopSystemIndex(PlayerLoopSystem[] playerLoopList, Type systemType) |
|
{ |
|
for (int i = 0; i < playerLoopList.Length; i++) |
|
{ |
|
if (playerLoopList[i].type == systemType) |
|
{ |
|
return i; |
|
} |
|
} |
|
|
|
throw new Exception("Target PlayerLoopSystem does not found. Type:" + systemType.FullName); |
|
} |
|
|
|
static void InsertLoop(PlayerLoopSystem[] copyList, InjectPlayerLoopTimings injectTimings, Type loopType, InjectPlayerLoopTimings targetTimings, |
|
int index, bool injectOnFirst, Type loopRunnerYieldType, Type loopRunnerType, PlayerLoopTiming playerLoopTiming) |
|
{ |
|
var i = FindLoopSystemIndex(copyList, loopType); |
|
if ((injectTimings & targetTimings) == targetTimings) |
|
{ |
|
copyList[i].subSystemList = InsertRunner(copyList[i], injectOnFirst, |
|
loopRunnerYieldType, yielders[index] = new ContinuationQueue(playerLoopTiming), |
|
loopRunnerType, runners[index] = new PlayerLoopRunner(playerLoopTiming)); |
|
} |
|
else |
|
{ |
|
copyList[i].subSystemList = RemoveRunner(copyList[i], loopRunnerYieldType, loopRunnerType); |
|
} |
|
} |
|
|
|
public static void Initialize(ref PlayerLoopSystem playerLoop, InjectPlayerLoopTimings injectTimings = InjectPlayerLoopTimings.All) |
|
{ |
|
#if UNITY_2020_2_OR_NEWER |
|
yielders = new ContinuationQueue[16]; |
|
runners = new PlayerLoopRunner[16]; |
|
#else |
|
yielders = new ContinuationQueue[14]; |
|
runners = new PlayerLoopRunner[14]; |
|
#endif |
|
|
|
var copyList = playerLoop.subSystemList.ToArray(); |
|
|
|
// Initialization |
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Initialization), |
|
InjectPlayerLoopTimings.Initialization, 0, true, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), PlayerLoopTiming.Initialization); |
|
|
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Initialization), |
|
InjectPlayerLoopTimings.LastInitialization, 1, false, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), PlayerLoopTiming.LastInitialization); |
|
|
|
// EarlyUpdate |
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.EarlyUpdate), |
|
InjectPlayerLoopTimings.EarlyUpdate, 2, true, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), PlayerLoopTiming.EarlyUpdate); |
|
|
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.EarlyUpdate), |
|
InjectPlayerLoopTimings.LastEarlyUpdate, 3, false, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastEarlyUpdate), PlayerLoopTiming.LastEarlyUpdate); |
|
|
|
// FixedUpdate |
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.FixedUpdate), |
|
InjectPlayerLoopTimings.FixedUpdate, 4, true, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), PlayerLoopTiming.FixedUpdate); |
|
|
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.FixedUpdate), |
|
InjectPlayerLoopTimings.LastFixedUpdate, 5, false, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastFixedUpdate), PlayerLoopTiming.LastFixedUpdate); |
|
|
|
// PreUpdate |
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreUpdate), |
|
InjectPlayerLoopTimings.PreUpdate, 6, true, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), PlayerLoopTiming.PreUpdate); |
|
|
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreUpdate), |
|
InjectPlayerLoopTimings.LastPreUpdate, 7, false, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreUpdate), PlayerLoopTiming.LastPreUpdate); |
|
|
|
// Update |
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Update), |
|
InjectPlayerLoopTimings.Update, 8, true, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), PlayerLoopTiming.Update); |
|
|
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Update), |
|
InjectPlayerLoopTimings.LastUpdate, 9, false, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastUpdate), PlayerLoopTiming.LastUpdate); |
|
|
|
// PreLateUpdate |
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreLateUpdate), |
|
InjectPlayerLoopTimings.PreLateUpdate, 10, true, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), PlayerLoopTiming.PreLateUpdate); |
|
|
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreLateUpdate), |
|
InjectPlayerLoopTimings.LastPreLateUpdate, 11, false, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreLateUpdate), PlayerLoopTiming.LastPreLateUpdate); |
|
|
|
// PostLateUpdate |
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PostLateUpdate), |
|
InjectPlayerLoopTimings.PostLateUpdate, 12, true, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), PlayerLoopTiming.PostLateUpdate); |
|
|
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PostLateUpdate), |
|
InjectPlayerLoopTimings.LastPostLateUpdate, 13, false, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), PlayerLoopTiming.LastPostLateUpdate); |
|
|
|
#if UNITY_2020_2_OR_NEWER |
|
// TimeUpdate |
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.TimeUpdate), |
|
InjectPlayerLoopTimings.TimeUpdate, 14, true, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldTimeUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerTimeUpdate), PlayerLoopTiming.TimeUpdate); |
|
|
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.TimeUpdate), |
|
InjectPlayerLoopTimings.LastTimeUpdate, 15, false, |
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldTimeUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastTimeUpdate), PlayerLoopTiming.LastTimeUpdate); |
|
#endif |
|
|
|
// Insert UniTaskSynchronizationContext to Update loop |
|
var i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.Update)); |
|
copyList[i].subSystemList = InsertUniTaskSynchronizationContext(copyList[i]); |
|
|
|
playerLoop.subSystemList = copyList; |
|
PlayerLoop.SetPlayerLoop(playerLoop); |
|
} |
|
|
|
public static void AddAction(PlayerLoopTiming timing, IPlayerLoopItem action) |
|
{ |
|
var runner = runners[(int)timing]; |
|
if (runner == null) |
|
{ |
|
ThrowInvalidLoopTiming(timing); |
|
} |
|
runner.AddAction(action); |
|
} |
|
|
|
static void ThrowInvalidLoopTiming(PlayerLoopTiming playerLoopTiming) |
|
{ |
|
throw new InvalidOperationException("Target playerLoopTiming is not injected. Please check PlayerLoopHelper.Initialize. PlayerLoopTiming:" + playerLoopTiming); |
|
} |
|
|
|
public static void AddContinuation(PlayerLoopTiming timing, Action continuation) |
|
{ |
|
var q = yielders[(int)timing]; |
|
if (q == null) |
|
{ |
|
ThrowInvalidLoopTiming(timing); |
|
} |
|
q.Enqueue(continuation); |
|
} |
|
|
|
// Diagnostics helper |
|
|
|
#if UNITY_2019_3_OR_NEWER |
|
|
|
public static void DumpCurrentPlayerLoop() |
|
{ |
|
var playerLoop = UnityEngine.LowLevel.PlayerLoop.GetCurrentPlayerLoop(); |
|
|
|
var sb = new System.Text.StringBuilder(); |
|
sb.AppendLine($"PlayerLoop List"); |
|
foreach (var header in playerLoop.subSystemList) |
|
{ |
|
sb.AppendFormat("------{0}------", header.type.Name); |
|
sb.AppendLine(); |
|
|
|
if (header.subSystemList is null) |
|
{ |
|
sb.AppendFormat("{0} has no subsystems!", header.ToString()); |
|
sb.AppendLine(); |
|
continue; |
|
} |
|
|
|
foreach (var subSystem in header.subSystemList) |
|
{ |
|
sb.AppendFormat("{0}", subSystem.type.Name); |
|
sb.AppendLine(); |
|
|
|
if (subSystem.subSystemList != null) |
|
{ |
|
UnityEngine.Debug.LogWarning("More Subsystem:" + subSystem.subSystemList.Length); |
|
} |
|
} |
|
} |
|
|
|
UnityEngine.Debug.Log(sb.ToString()); |
|
} |
|
|
|
public static bool IsInjectedUniTaskPlayerLoop() |
|
{ |
|
var playerLoop = UnityEngine.LowLevel.PlayerLoop.GetCurrentPlayerLoop(); |
|
|
|
foreach (var header in playerLoop.subSystemList) |
|
{ |
|
if (header.subSystemList is null) |
|
{ |
|
continue; |
|
} |
|
|
|
foreach (var subSystem in header.subSystemList) |
|
{ |
|
if (subSystem.type == typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization)) |
|
{ |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
#endif |
|
|
|
} |
|
} |
|
|
|
|