-
Notifications
You must be signed in to change notification settings - Fork 16
GameComponent x GameLoop
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
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() |
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); }
}
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);
}
}