Player Loop Hack

Integration with Unity PlayerLoop

In One Line

Unity's heartbeat, now under your command!

Overview

The PlayerLoop represents Unity Engine's core execution cycle, orchestrating when and how various systems and component updates are processed. This package provides tools to interact with Unity's low-level PlayerLoop system, allowing you to create, inject, and remove custom systems.

Package Info

display name

AceLand Player Loop Hack

package name

com.aceland.playerloophack

latest version

1.0.7

namespace

AceLand.PlayerLoopHack

dependencies

com.aceland.library: 1.0.10

If you're not familiar with these concepts, we recommend gaining more experience before implementing this package in your projects.

Several AceLand packages leverage this PlayerLoop system as their foundation. For example, AceLand States utilizes this framework to implement state machines as injectable PlayerLoop systems, allowing state logic to execute at the engine level for optimal performance.

Key Features:

  • Custom system creation

  • PlayerLoop injection

  • System removal and management

  • Low-level performance optimization


Project Settings

Logging Level

Level of Logging on inject or remove system default: BuildLevel.DevelopmentBuild

System Logging Level

Level of Logging whole system structure after inject or remove system.

default: BuildLevel.DevelopmentBuild


Create Your System

using AceLand.PlayerLoopHack;

public class YourSystem : IPlayerLoopSystem
{
    public void SystemUpdate()
    {
        // your system cycle
    }
}
  • create your class inherite to IPlayerLoopSystem


Inject/Remove System

using AceLand.PlayerLoopHack;
using UnityEngine.LowLevel;

public class YourSystem : IPlayerLoopSystem
{
    private PlayerLoopSystem _system;
    
    public void SystemStart()
    {
        _system = this.CreatePlayerLoopSystem();
        _system.InjectSystem(PlayerLoopState.EarlyUpdate);
    }

    public void SystemStop()
    {
        _system.RemoveSystem(PlayerLoopState.EarlyUpdate);
    }
    
    public void SystemUpdate()
    {
        // your system cycle
    }
}
  • create a system and set as reference

  • insert system by passing player loop state

  • remove system by passing player loop state

// inject system
// default at the end of the type
_system.InjectSystem(PlayerLoopState.EarlyUpdate);

// inject system at the top of the type
// by giving an index
_system.InjectSystem(PlayerLoopState.EarlyUpdate, 0);

Technical Details

The PlayerLoop consists of multiple execution phases:

TimeUpdate

Updates time-related values (Time.deltaTime, Time.fixedTime, etc.) for the current frame

Initialization

Handles basic setup, including input events and initial frame preparations

EarlyUpdate

Processes input and platform-specific updates

FixedUpdate

Physics and fixed-time-step logic

PreUpdate

Preparation for main update()

Update

Main update phase where most game logic occurs

PreLateUpdate

Preparation for late updates

PostLateUpdate

Final phase, handles rendering and cleanup

This package allows you to inject custom systems into any of these phases, giving you precise control over when your code executes in Unity's frame cycle.


Safe Usage

using AceLand.PlayerLoopHack;
using AceLand.TaskUtils;
using UnityEngine;
using UnityEngine.LowLevel;

namespace YourName.Package
{
    internal static class SafeUsageBootstrapper
    {
        private static SafeUsageExample _system;
    
        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
        private static void Initial()
        {
            _system = new SafeUsageExample();
        }
    }
    
    internal sealed class SafeUsageExample : IPlayerLoopSystem
    {
        internal SafeUsageExample() => SystemStart();
        
        private PlayerLoopSystem _system;
        
        private void SystemStart()
        {
            _system = this.CreatePlayerLoopSystem();
            _system.InjectSystem(PlayerLoopState.Initialization);
            Promise.AddApplicationQuitListener(SystemStop);
            Debug.Log("System is started");
        }
    
        private void SystemStop()
        {
            _system.RemoveSystem(PlayerLoopState.Initialization);
            Debug.Log("System is stoped");
        }
        
        public void SystemUpdate()
        {
            // perfect stuffs
        }
    }
}
  • create a unique and independent system

  • start the system with a static Bootstrapper

  • add SystemStop() to Application Quit Listerner

  • Logging for checking

Package AceLand Task Utils is required.

Last updated