Hi everyone,
In order to optimize our game, I wanted to disable some parts of the PlayerLoop that we don’t use (e.g cloth update, Kinect update (why is this even here), everything XR related…). I started by using this package which seemed to work well, except that as soon as any change was made to the Player Loop, we started having problems with ReadValue
calls.
I thought the package had a problem so I tried rolling my own, and the exact same thing happened. After a bit of digging I can say that:
- As soon as there’s a change on the PlayerLoop, all
ReadValue
calls made from a FixedUpdate will return 0.0f/Vector2.zero.
- Any change on the PlayerLoop will cause the problem, even doing
PlayerLoop.SetPlayerLoop(PlayerLoop.GetDefaultPlayerLoop())
.
- All input events (i.e
performed
, cancelled
…) still work, as well as any ReadValue
call made from an Update.
- Changing the Input System’s update mode to Fixed Update instead of Dynamic Update makes everything work as intended again.
- Not doing any change to the PlayerLoop makes everything work as intended again.
- This happens even in an empty project, with just the PlayerLoop editing scripts.
My guess is that the Input System package adds a method to the PlayerLoop, and since it isn’t part of the DefaultPlayerLoop, it gets removed when making changes and/or resetting the current PlayerLoop to the Default one, but I can’t seem to find anything online about that.
Could someone explain what happens there?
Thanks!
Out of interest did you try just disabling the built in packages and such before branching down this path? unity lets you without the need of additional packages
1 Like
I think your guess is correct.
#nullable enable
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.LowLevel;
namespace TestPlayerLoop
{
public class TestScript : MonoBehaviour
{
void Awake()
{
var defaultLoopNames = new List<string>();
GetPlayerLoopNameList(PlayerLoop.GetDefaultPlayerLoop(), defaultLoopNames);
var currentLoopNames = new List<string>();
GetPlayerLoopNameList(PlayerLoop.GetCurrentPlayerLoop(), currentLoopNames);
Debug.Log($"DefaultPlayerLoop: count = {defaultLoopNames.Count}");
Debug.Log($"CurrentPlayerLoop: count = {currentLoopNames.Count}");
foreach (var cname in currentLoopNames)
if (!defaultLoopNames.Contains(cname))
Debug.Log($"Additional CurrentPlayerLoop Event: {cname}");
}
static void GetPlayerLoopNameList(in PlayerLoopSystem playerloop, List<string> result)
{
result.Add(playerloop.type?.ToString() ?? "no type");
if (playerloop.subSystemList != null)
for (int i = 0; i < playerloop.subSystemList.Length; i++)
GetPlayerLoopNameList(playerloop.subSystemList[i], result);
}
}
}
// DefaultPlayerLoop: count = 136
// CurrentPlayerLoop: count = 142
// Additional CurrentPlayerLoop Event: Unity.Entities.RuntimeApplication+UpdatePreFrame
// Additional CurrentPlayerLoop Event: UnityEngine.InputSystem.LowLevel.NativeInputRuntime+InputSystemPlayerLoopRunnerInitializationSystem
// Additional CurrentPlayerLoop Event: Unity.Entities.InitializationSystemGroup
// Additional CurrentPlayerLoop Event: Unity.Entities.SimulationSystemGroup
// Additional CurrentPlayerLoop Event: Unity.Entities.PresentationSystemGroup
// Additional CurrentPlayerLoop Event: Unity.Entities.RuntimeApplication+UpdatePostFrame
You can avoid the issue by using GetCurrentPlayerLoop instead of GetDefaultPlayerLoop.
2 Likes
You did profile that they provide a not insignificant overhead to your frame time? Because I find it hard to imagine that (unused) PlayerLoop calls contribute anything of significance in relation to whatever code you wrote.
I also agree with bugfinders, first I would simply disable these wholly unnecessary Built-In/Modules in Package Manager like Cloth, Vehicles, Wind, and so forth. This will also shave off some Kb from your build.