Skip to content

Commit

Permalink
Add UnityFrameProvider.PostFixedUpdate in Unity
Browse files Browse the repository at this point in the history
  • Loading branch information
neuecc committed Aug 8, 2024
1 parent 3186eff commit 8eb18b4
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 20 deletions.
49 changes: 29 additions & 20 deletions src/R3.Unity/Assets/R3.Unity/Runtime/PlayerLoopHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ namespace R3
{
public static class R3LoopRunners
{
public struct Initialization { };
public struct EarlyUpdate { };
public struct FixedUpdate { };
public struct PreUpdate { };
public struct Update { };
public struct PreLateUpdate { };
public struct PostLateUpdate { };
public struct TimeUpdate { };
public struct R3Initialization { };
public struct R3EarlyUpdate { };
public struct R3FixedUpdate { };
public struct R3PreUpdate { };
public struct R3Update { };
public struct R3PreLateUpdate { };
public struct R3PostLateUpdate { };
public struct R3TimeUpdate { };
public struct R3PostFixedUpdate { };
}

internal enum PlayerLoopTiming
Expand All @@ -34,6 +35,8 @@ internal enum PlayerLoopTiming
PreLateUpdate = 5,
PostLateUpdate = 6,
TimeUpdate = 7,

PostFixedUpdate = 8 // new in v1.2.4
}

public static class PlayerLoopHelper
Expand Down Expand Up @@ -68,19 +71,21 @@ static void Init()

public static void Initialize(ref PlayerLoopSystem playerLoop)
{
runners = new UnityFrameProvider[8];
runners = new UnityFrameProvider[9];

var newLoop = playerLoop.subSystemList.ToArray();

// Initialization
InsertLoop(newLoop, typeof(PlayerLoopType.Initialization), typeof(R3LoopRunners.Initialization), runners[0] = (UnityFrameProvider)UnityFrameProvider.Initialization);
InsertLoop(newLoop, typeof(PlayerLoopType.EarlyUpdate), typeof(R3LoopRunners.EarlyUpdate), runners[1] = (UnityFrameProvider)UnityFrameProvider.EarlyUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.FixedUpdate), typeof(R3LoopRunners.FixedUpdate), runners[2] = (UnityFrameProvider)UnityFrameProvider.FixedUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.PreUpdate), typeof(R3LoopRunners.PreUpdate), runners[3] = (UnityFrameProvider)UnityFrameProvider.PreUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.Update), typeof(R3LoopRunners.Update), runners[4] = (UnityFrameProvider)UnityFrameProvider.Update);
InsertLoop(newLoop, typeof(PlayerLoopType.PreLateUpdate), typeof(R3LoopRunners.PreLateUpdate), runners[5] = (UnityFrameProvider)UnityFrameProvider.PreLateUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.PostLateUpdate), typeof(R3LoopRunners.PostLateUpdate), runners[6] = (UnityFrameProvider)UnityFrameProvider.PostLateUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.TimeUpdate), typeof(R3LoopRunners.TimeUpdate), runners[7] = (UnityFrameProvider)UnityFrameProvider.TimeUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.Initialization), typeof(R3LoopRunners.R3Initialization), runners[0] = (UnityFrameProvider)UnityFrameProvider.Initialization);
InsertLoop(newLoop, typeof(PlayerLoopType.EarlyUpdate), typeof(R3LoopRunners.R3EarlyUpdate), runners[1] = (UnityFrameProvider)UnityFrameProvider.EarlyUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.FixedUpdate), typeof(R3LoopRunners.R3FixedUpdate), runners[2] = (UnityFrameProvider)UnityFrameProvider.FixedUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.PreUpdate), typeof(R3LoopRunners.R3PreUpdate), runners[3] = (UnityFrameProvider)UnityFrameProvider.PreUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.Update), typeof(R3LoopRunners.R3Update), runners[4] = (UnityFrameProvider)UnityFrameProvider.Update);
InsertLoop(newLoop, typeof(PlayerLoopType.PreLateUpdate), typeof(R3LoopRunners.R3PreLateUpdate), runners[5] = (UnityFrameProvider)UnityFrameProvider.PreLateUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.PostLateUpdate), typeof(R3LoopRunners.R3PostLateUpdate), runners[6] = (UnityFrameProvider)UnityFrameProvider.PostLateUpdate);
InsertLoop(newLoop, typeof(PlayerLoopType.TimeUpdate), typeof(R3LoopRunners.R3TimeUpdate), runners[7] = (UnityFrameProvider)UnityFrameProvider.TimeUpdate);
// FixedUpdate - Post
InsertLoop(newLoop, typeof(PlayerLoopType.FixedUpdate), typeof(R3LoopRunners.R3PostFixedUpdate), runners[8] = (UnityFrameProvider)UnityFrameProvider.PostFixedUpdate);

playerLoop.subSystemList = newLoop;
PlayerLoop.SetPlayerLoop(playerLoop);
Expand Down Expand Up @@ -127,10 +132,14 @@ static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem[] subSystemList, Type lo
var source = subSystemList.Where(x => x.type != loopRunnerType).ToArray(); // remove duplicate(initialized previously)
var dest = new PlayerLoopSystem[source.Length + 1];

Array.Copy(source, 0, dest, 1, source.Length);

// insert first
dest[0] = new PlayerLoopSystem
var insertIndex = (runner.PlayerLoopTiming != PlayerLoopTiming.PostFixedUpdate)
? 0 // insert first
: dest.Length - 1; // insert last

Array.Copy(source, 0, dest, insertIndex == 0 ? 1 : 0, source.Length);

dest[insertIndex] = new PlayerLoopSystem
{
type = loopRunnerType,
updateDelegate = runner.Run
Expand Down
1 change: 1 addition & 0 deletions src/R3.Unity/Assets/R3.Unity/Runtime/UnityFrameProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class UnityFrameProvider : FrameProvider
public static readonly FrameProvider PreLateUpdate = new UnityFrameProvider(PlayerLoopTiming.PreLateUpdate);
public static readonly FrameProvider PostLateUpdate = new UnityFrameProvider(PlayerLoopTiming.PostLateUpdate);
public static readonly FrameProvider TimeUpdate = new UnityFrameProvider(PlayerLoopTiming.TimeUpdate);
public static readonly FrameProvider PostFixedUpdate = new UnityFrameProvider(PlayerLoopTiming.PostFixedUpdate);

FreeListCore<IFrameRunnerWorkItem> list;
readonly object gate = new object();
Expand Down
79 changes: 79 additions & 0 deletions src/R3.Unity/Assets/Scenes/NewBehaviourScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
using UnityEngine.UI;
using Cysharp.Threading.Tasks;
using System.Threading;
using System.Text;
using UnityEngine.LowLevel;
using System.Linq;

public class NewBehaviourScript : MonoBehaviour
{
Expand Down Expand Up @@ -76,3 +79,79 @@ public class NantonakuProperty
{
public int value;
}


public class PlayerLoopInfo
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void Init()
{
// var playerLoop = UnityEngine.LowLevel.PlayerLoop.GetDefaultPlayerLoop();
var playerLoop = UnityEngine.LowLevel.PlayerLoop.GetCurrentPlayerLoop();
DumpPlayerLoop("After SubsystemRegistration", playerLoop);
}

public static void DumpPlayerLoop(string which, UnityEngine.LowLevel.PlayerLoopSystem playerLoop)
{
var sb = new StringBuilder();
sb.AppendLine($"{which} PlayerLoop List");
foreach (var header in playerLoop.subSystemList)
{
sb.AppendFormat("------{0}------", header.type.Name);
sb.AppendLine();
foreach (var subSystem in header.subSystemList)
{
sb.AppendFormat("{0}.{1}", header.type.Name, subSystem.type.Name);
sb.AppendLine();

if (subSystem.subSystemList != null)
{
UnityEngine.Debug.LogWarning("More Subsystem:" + subSystem.subSystemList.Length);
}
}
}

UnityEngine.Debug.Log(sb.ToString());
}

public static Type CurrentLoopType { get; private set; }

public static void Inject()
{
var system = PlayerLoop.GetCurrentPlayerLoop();

for (int i = 0; i < system.subSystemList.Length; i++)
{
var loop = system.subSystemList[i].subSystemList.SelectMany(x =>
{
var t = typeof(WrapLoop<>).MakeGenericType(x.type);
var instance = (ILoopRunner)Activator.CreateInstance(t, x.type);
return new[] { new PlayerLoopSystem { type = t, updateDelegate = instance.Run }, x };
}).ToArray();

system.subSystemList[i].subSystemList = loop;
}

PlayerLoop.SetPlayerLoop(system);
}

interface ILoopRunner
{
void Run();
}

class WrapLoop<T> : ILoopRunner
{
readonly Type type;

public WrapLoop(Type type)
{
this.type = type;
}

public void Run()
{
CurrentLoopType = type;
}
}
}

0 comments on commit 8eb18b4

Please sign in to comment.