Last active
January 6, 2024 08:53
-
-
Save ruccho/122eddafaf70a391c8a4d564c903f35e to your computer and use it in GitHub Desktop.
PlayerLoopに任意の処理を挿入するヘルパークラスと使用サンプル
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.LowLevel; | |
using UnityEngine.PlayerLoop; | |
public class InsertPlayerLoopSample | |
{ | |
public struct SampleCustomUpdate{} | |
[RuntimeInitializeOnLoadMethod] | |
private static void RegisterCustomPlayerLoop() | |
{ | |
using (var modifier = new PlayerLoopModifier()) | |
{ | |
modifier.InsertAfter<Update.ScriptRunBehaviourUpdate>(new PlayerLoopSystem() | |
{ | |
updateDelegate = OnSampleCustomUpdate, | |
type = typeof(SampleCustomUpdate) | |
}); | |
} | |
} | |
private static void OnSampleCustomUpdate() | |
{ | |
Debug.Log("OnSampleCustomUpdate"); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEngine.LowLevel; | |
/// <summary> | |
/// PlayerLoopのコピーに変更を行い、Dispose()のタイミングで有効化します。 | |
/// usingと併せて使うのがおすすめ。 | |
/// </summary> | |
public struct PlayerLoopModifier : IDisposable | |
{ | |
private PlayerLoopSystem root; | |
private PlayerLoopModifier(in PlayerLoopSystem root) | |
{ | |
this.root = root; | |
} | |
public static PlayerLoopModifier Create() | |
{ | |
return new PlayerLoopModifier(PlayerLoop.GetCurrentPlayerLoop()); | |
} | |
/// <summary> | |
/// 任意のPlayerLoopSystemの直後に新しくPlayerLoopSystemを挿入する。 | |
/// </summary> | |
/// <param name="subSystem">追加するPlayerLoopSystem。</param> | |
/// <typeparam name="T">Tで指定されたtypeのPlayerLoopSystemの直後に追加します。</typeparam> | |
/// <returns>追加が成功したかどうか。</returns> | |
public bool InsertAfter<T>(in PlayerLoopSystem subSystem) where T : struct | |
{ | |
return InsertAfter<T>(subSystem, ref root); | |
} | |
/// <summary> | |
/// 任意のPlayerLoopSystemの直前に新しくPlayerLoopSystemを挿入する。 | |
/// </summary> | |
/// <param name="subSystem">追加するPlayerLoopSystem。</param> | |
/// <typeparam name="T">Tで指定されたtypeのPlayerLoopSystemの直前に追加します。</typeparam> | |
/// <returns>追加が成功したかどうか。</returns> | |
public bool InsertBefore<T>(in PlayerLoopSystem subSystem) where T : struct | |
{ | |
return InsertBefore<T>(subSystem, ref root); | |
} | |
/// <summary> | |
/// 任意のPlayerLoopSystemの子に新しくPlayerLoopSystemを挿入する。 | |
/// </summary> | |
/// <param name="subSystem">追加するPlayerLoopSystem。</param> | |
/// <typeparam name="T">Tで指定されたtypeのPlayerLoopSystemの子に追加します。</typeparam> | |
/// <returns>追加が成功したかどうか。</returns> | |
public bool InsertIn<T>(in PlayerLoopSystem subSystem) where T : struct | |
{ | |
return InsertIn<T>(subSystem, ref root); | |
} | |
public void Dispose() | |
{ | |
PlayerLoop.SetPlayerLoop(root); | |
} | |
private static bool InsertAfter<T>(in PlayerLoopSystem subSystem, ref PlayerLoopSystem parentSystem) | |
where T : struct | |
{ | |
var subSystems = parentSystem.subSystemList?.ToList(); | |
if (subSystems == default) return false; | |
bool found = false; | |
for (int i = 0; i < subSystems.Count; i++) | |
{ | |
var s = subSystems[i]; | |
if (s.type == typeof(T)) | |
{ | |
found = true; | |
subSystems.Insert(i + 1, subSystem); | |
break; | |
} | |
} | |
if (!found) | |
{ | |
for (int i = 0; i < subSystems.Count; i++) | |
{ | |
var s = subSystems[i]; | |
if (InsertAfter<T>(subSystem, ref s)) | |
{ | |
found = true; | |
subSystems[i] = s; | |
break; | |
} | |
} | |
} | |
if (found) | |
parentSystem.subSystemList = subSystems.ToArray(); | |
return found; | |
} | |
private static bool InsertBefore<T>(in PlayerLoopSystem subSystem, ref PlayerLoopSystem parentSystem) | |
where T : struct | |
{ | |
var subSystems = parentSystem.subSystemList?.ToList(); | |
if (subSystems == default) return false; | |
bool found = false; | |
for (int i = 0; i < subSystems.Count; i++) | |
{ | |
var s = subSystems[i]; | |
if (s.type == typeof(T)) | |
{ | |
found = true; | |
subSystems.Insert(i, subSystem); | |
break; | |
} | |
} | |
if (!found) | |
{ | |
for (int i = 0; i < subSystems.Count; i++) | |
{ | |
var s = subSystems[i]; | |
if (InsertBefore<T>(subSystem, ref s)) | |
{ | |
found = true; | |
subSystems[i] = s; | |
break; | |
} | |
} | |
} | |
if (found) | |
parentSystem.subSystemList = subSystems.ToArray(); | |
return found; | |
} | |
private static bool InsertIn<T>(in PlayerLoopSystem subSystem, ref PlayerLoopSystem parentSystem) | |
where T : struct | |
{ | |
var subSystems = parentSystem.subSystemList?.ToList(); | |
if (subSystems == default) subSystems = new List<PlayerLoopSystem>(); | |
bool found = false; | |
if (parentSystem.type == typeof(T)) | |
{ | |
subSystems.Insert(0, subSystem); | |
found = true; | |
} | |
else | |
{ | |
for (int i = 0; i < subSystems.Count; i++) | |
{ | |
var s = subSystems[i]; | |
if (InsertIn<T>(subSystem, ref s)) | |
{ | |
found = true; | |
subSystems[i] = s; | |
break; | |
} | |
} | |
} | |
if (found) | |
parentSystem.subSystemList = subSystems.ToArray(); | |
return found; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment