Skip to content

GameComponent x GameLoop

yenmoc edited this page Mar 9, 2024 · 4 revisions

What

First it is similar to MonoBehaviour because it inherits MonoBehaviour

So why do we create it?. That's because Managed, It is based on Update manager optimization technique, Update manager optimization technique is a special technique which avoids unnecessary interop update calls by using a managed only UpdateManager class.

Every class that inherits from GameComponent will be managed by GlobalComponent

The purpose of this is to optimize performance

This technique has been mentioned for a long time, you can refer to this document

That was back in the day, but now GameComponent has been stripped of all that complexity and is now exactly like MonoBehaviour. Now the main purpose of using it is to easily customize or manipulate it through the IComponent interface only or you can use CacheGameComponent where the Transform and T type are cached.

Result benchmark performance you can found at here

For Now

unity-architecture-pattern-the-main-loop

We will now use the PlayerLoop API that Unity provides from 2018.1 for better control update. Improves performance (a bit) as each MonoBehaviour 'magic' Fixed/Late/Update method has some overhead due native C++ to managed C# call.

about better loop control is because it provides more points to be able to run the loop like:

GameLoop Timing
Initialize Early PlayerLoop.Initialization
PostInitialize Late PlayerLoop.Initialization
Start Before MonoBehaviour.Start()
PostStart After MonoBehaviour.Start()
FixedUpdate Before MonoBehaviour.FixedUpdate()
PostFixedUpdate After MonoBehaviour.FixedUpdate()
Update Before MonoBehaviour.Update()
PostUpdate After MonoBehaviour.Update()
LateUpdate Before MonoBehaviour.LateUpdate()
PostLateUpdate After MonoBehaviour.LateUpdate()

Usages

We will have interfaces corresponding to each time you want to run the update loop. You just need to implement the corresponding interface to use

  • IInitialize :
  • IPostInitialize :
  • IStart :
  • IPostStart :
  • IFixedUpdate :
  • IPostFixedUpdate :
  • IUpdate :
  • IPostUpdate :
  • ILateUpdate :
  • IPostLateUpdate :

Now you need to add it to the PlayerLoop class do this in the foundation which is GameLoop

using Pancake.PlayerLoop;
using UnityEngine;

public class PlayerMoveComponent : MonoBehaviour, IUpdate
{
    private void Awake()
    {
        GameLoop.Register(this);
    }

    public void OnUpdate()
    {
        // TO_DO
    }
}

You can unsubscribe with

GameLoop.UnRegister(this);

On Editor, all update-loop will be automatically unregistered when exiting playmode.

You can also use PlayerLoop for classes that do not inherit from MonoBehaviour

You can now register at object creation time

public class PlayerMoveComponent : IUpdate
{
    public static PlayerMoveComponent Rent()
    {
        var playerMove = new PlayerMoveComponent();
        GameLoop.Register(playerMove);
        return playerMove;
    }

    public void OnUpdate()
    {
        // TO_DO
    }
}
public class Demo : MonoBehaviour
{
    private PlayerMoveComponent _playerMoveComponent;
    private void OnEnable() { _playerMoveComponent = PlayerMoveComponent.Rent(); }

    private void OnDisable() { GameLoop.Unregister(_playerMoveComponent); }
}

Note

In case you are not using GameLoop and you still want to update through MonoBehaviour but still want better performance as mentioned above you can still use managed updates managed by the GlobalComponent class accessed through App

public class PlayerMoveComponent : MonoBehaviour, IUpdate
{
    private void Awake()
    {
        App.AddListener(UpdateMode.Update, OnUpdate);
    }

    public void OnUpdate()
    {
        // TO_DO
    }

    private void OnDisable()
    {
        App.RemoveListener(UpdateMode.Update, OnUpdate);
    }
}
Clone this wiki locally