// MODIFIED AddSystemToPlayerLoopList from Unity.Entities.ScriptBehaviourUpdateOrder (ECS) // // => adds an update function to the Unity internal update type. // => Unity has different update loops: // https://medium.com/@thebeardphantom/unity-2018-and-playerloop-5c46a12a677 // EarlyUpdate // FixedUpdate // PreUpdate // Update // PreLateUpdate // PostLateUpdate // // function: the custom update function to add // IMPORTANT: according to a comment in Unity.Entities.ScriptBehaviourUpdateOrder, // the UpdateFunction can not be virtual because // Mono 4.6 has problems invoking virtual methods // as delegates from native! // ownerType: the .type to fill in so it's obvious who the new function // belongs to. seems to be mostly for debugging. pass any. // addMode: prepend or append to update list internal static bool AddToPlayerLoop(PlayerLoopSystem.UpdateFunction function, Type ownerType, ref PlayerLoopSystem playerLoop, Type playerLoopSystemType, AddMode addMode) { // did we find the type? e.g. EarlyUpdate/PreLateUpdate/etc. if (playerLoop.type == playerLoopSystemType) { // debugging //Debug.Log($"Found playerLoop of type {playerLoop.type} with {playerLoop.subSystemList.Length} Functions:"); //foreach (PlayerLoopSystem sys in playerLoop.subSystemList) // Debug.Log($" ->{sys.type}"); // resize & expand subSystemList to fit one more entry int oldListLength = (playerLoop.subSystemList != null) ? playerLoop.subSystemList.Length : 0; Array.Resize(ref playerLoop.subSystemList, oldListLength + 1); // prepend our custom loop to the beginning if (addMode == AddMode.Beginning) { // shift to the right, write into first array element Array.Copy(playerLoop.subSystemList, 0, playerLoop.subSystemList, 1, playerLoop.subSystemList.Length - 1); playerLoop.subSystemList[0].type = ownerType; playerLoop.subSystemList[0].updateDelegate = function; } // append our custom loop to the end else if (addMode == AddMode.End) { // simply write into last array element playerLoop.subSystemList[oldListLength].type = ownerType; playerLoop.subSystemList[oldListLength].updateDelegate = function; } // debugging //Debug.Log($"New playerLoop of type {playerLoop.type} with {playerLoop.subSystemList.Length} Functions:"); //foreach (PlayerLoopSystem sys in playerLoop.subSystemList) // Debug.Log($" ->{sys.type}"); return(true); } // recursively keep looking if (playerLoop.subSystemList != null) { for (int i = 0; i < playerLoop.subSystemList.Length; ++i) { if (AddToPlayerLoop(function, ownerType, ref playerLoop.subSystemList[i], playerLoopSystemType, addMode)) { return(true); } } } return(false); }
private static void AddSystemLoop <T1, T2>(PlayerLoopSystem.UpdateFunction update) { PlayerLoopSystem mainLoopSystem = PlayerLoop.GetDefaultPlayerLoop(); if (FindLoopSystem <T1>(mainLoopSystem, out int index, out PlayerLoopSystem targetLoopSystem)) { PlayerLoopSystem[] loopSystem = targetLoopSystem.subSystemList; int length = loopSystem.Length; Array.Resize(ref loopSystem, length + 1); loopSystem[length].type = typeof(T2); loopSystem[length].updateDelegate = update; targetLoopSystem.subSystemList = loopSystem; mainLoopSystem.subSystemList[index] = targetLoopSystem; PlayerLoop.SetPlayerLoop(mainLoopSystem); } }
internal static int FindPlayerLoopEntryIndex(PlayerLoopSystem.UpdateFunction function, PlayerLoopSystem playerLoop, Type playerLoopSystemType) { if (playerLoop.type == playerLoopSystemType) { return(Array.FindIndex(playerLoop.subSystemList, (elem => elem.updateDelegate == function))); } if (playerLoop.subSystemList != null) { for (int i = 0; i < playerLoop.subSystemList.Length; ++i) { int index = FindPlayerLoopEntryIndex(function, playerLoop.subSystemList[i], playerLoopSystemType); if (index != -1) { return(index); } } } return(-1); }
// helper function to find an update function's index in a player loop // type. this is used for testing to guarantee our functions are added // at the beginning/end properly. internal static int FindPlayerLoopEntryIndex(PlayerLoopSystem.UpdateFunction function, PlayerLoopSystem playerLoop, Type playerLoopSystemType) { // did we find the type? e.g. EarlyUpdate/PreLateUpdate/etc. if (playerLoop.type == playerLoopSystemType) { return(Array.FindIndex(playerLoop.subSystemList, (elem => elem.updateDelegate == function))); } // recursively keep looking if (playerLoop.subSystemList != null) { for (int i = 0; i < playerLoop.subSystemList.Length; ++i) { int index = FindPlayerLoopEntryIndex(function, playerLoop.subSystemList[i], playerLoopSystemType); if (index != -1) { return(index); } } } return(-1); }
private PlayerLoopSystem InsertLoopSubSystem(PlayerLoopSystem.UpdateFunction managedCallback, Type subSystemType, PlayerLoopSystem target, int index) { var loopUpdateSubSystem = new PlayerLoopSystem() { type = subSystemType, updateDelegate = managedCallback }; var newSubSystems = new PlayerLoopSystem[target.subSystemList.Length + 1]; var nativeLoopCondition = IntPtr.Zero; for (int i = 0, newSubSystemCount = newSubSystems.Length; i < newSubSystemCount; ++i) { if (i < index) { newSubSystems[i] = target.subSystemList[i]; if ((i + 1) == index) { nativeLoopCondition = target.subSystemList[i].loopConditionFunction; } } else if (i == index) { loopUpdateSubSystem.loopConditionFunction = nativeLoopCondition; newSubSystems[i] = loopUpdateSubSystem; } else { newSubSystems[i] = target.subSystemList[i - 1]; } } target.subSystemList = newSubSystems; return(target); }