Anything wrong with dispatching Update()s "manually"

I’m considering a design where GameObjects are created programmatically by a “MainApp” instance (a MonoBehaviour / script bound to an Empty object) at Startup or Awake.

For each GameObject created, a corresponding “DomaninObject” (which inherits from Object, implements method Update()) would also be created.

A subclass of DomainObject might be BasketballPlayer.

A GameObject would be assigned to (stored in) each BasketballPlayer.

The MainApp instance would keep a reference to the collection of DomainObjects it created.

When MainApp receives Update() from Unity, it would invoke Update() on each of its domain objects. Each domain object, in turn, would manipulate its GameObject however it saw fit (change position, orientation, animation).

So: I would not be relying on Unity to send Update() to scripts attached to each GameObject in the scene (the “normal” approach?). Instead, a single script/MonoBehavior would receive a single update from Unity and dispatch that update “manually” to its “subordinates.”

Is there anything fundamentally wrong with doing things this way?

Thank you.

Reminds me of this guy’s post:

I think the short version is: No, there’s nothing really wrong with it. Out of curiosity, what makes you want to bypass Unity’s built-in methods and roll your own update manager?

Good question. I think it resulted from the way in which the DomainObjects and GameObjects are being instantiated at Startup(). I’ve got the DomainObject->GameObject bound, but since there’s no script associated with the GameObject, how to update things? Thus the idea to have the “MainApp” behavior do it.

Perhaps a script/behavior should be attached to the original prefab (the “normal” approach) and when the instance is created from the prefab at startup, MainApp keeps a reference to the MonoBehaviour attached to the GameObject. i.e., the “DomainObjects” are simply subclasses of “MonoBehaviour”, not Object (?).

I have a singleton class with static instance and I have a List in it. When a component needs the Update loop I implement the IUpdateable interface in it. (It enforces to have a DoUpdate method)
The singleton class has the only Unity Update call in my entire application and every time when it happens I just go through the list and call the DoUpdate methods. When I have a “final” sense how many items are in there I will switch to an array. This way I always know what receives Update loop and I can adjust the order of the calls, I can pause them, remove them, etc. Obviously in exchange they have to register for it.

1 Like

It’s probably fairly situational, and pretty dependent on what you’re trying to do, but I’d personally avoid a non-MonoBehaviour approach unless I really felt I was getting something critical out of it. Missing out on the whole GameObject lifecycle and event flow (Unity - Manual: Order of execution for event functions) seems like it sets up a lot of extra work. There are probably some smaller unique cases that could benefit from it, but I wouldn’t want to approach a whole game that way.

If you really just need awareness of what’s in your scene, it’s pretty simple to set up a behaviour where objects register themselves with a central service on Awake, and unregister on Destroy, so your service always have convenient and efficient access to them. I’d probably consider that approach before setting off on a very different direction.

Running 10k updates from single managed manager is faster than receiving native events from Unity.

So it depends. I suggest using something like MEC, or MicroCoroutines from UniRx to avoid overhead of native messaging.

Alternatively, create your own manager and do it manually. It will be faster

I only keep it in Unity’s Update loop, because it is guaranteed that it’s in sync with rendering. And FixedUpdate is with physics simulation.
Any other coroutine needs are served by MEC for me too. (Just realized not so long ago that at some point in the past I bought the Pro version of it… )

No, it’s absolutely fine to do your own Update(), I always do my own Scheduling when possible because Update and LateUpdate is not distinct enough for most applications.

This is my heavily modified Version of the well known “TickManager” (see attachment). You just put this script on a single persistent GameObject and you can use this in every other Script like this:

Usage Example

// usage: subscribe to event within OnDisable and OnEnable
//        void OnEnable(){
//            TickManager.Tick1        += MyUpdate;
//            ... there are a lot more TickTypes, use how many you like, even the same multiple times
//        }
//        void OnDisable(){
//            TickManager.Tick1        -= MyUpdate;
//            ... always unsubscribe here!
//        }
//        private void MyUpdate(){
//            /*your previous Update() code here
//        }
//

It has these hooks (chronologic order):
“FirstTickWithDeltaTime, FirstTick1, FirstTick2, FixedTick1, FixedTick2, PreInternalPhysicsRoutines, FixedTick3, FixedCoTick1, FixedCoTick2, Tick1, Tick2, CoTick1, CoTick2, LateTick1, LateTick2, LateTick3, EndOfFrame”

This thing can do even more than the built in Updates! It allows you to perform Input before the physics Update. This means that, depending on how you do things, Movement and Similar physic-stuff will get the current input, not the input of the last frame.

What i don’t know is if unsubscribing and subscribing is slower than Unity’s built in Update() subscription und unsubscription. The good thing is, when you don’t use a specific Tick, it won’t get called at all.

E.g. When you use “FirstTickWithDeltaTime” the script creates a dummy script at the end of every frame and destroys it again in order to use it’s Start() which is only called next frame before the Internal physics update (Unity - Manual: Order of execution for event functions). When you don’t use it anywhere in your active scene(s) it won’t do any of that.

If you use it and find any mistakes or conceptual errors, let me know, thanks

4158118–366748–TickHelper.cs (942 Bytes)
4158118–366751–TickManager.cs (16.5 KB)

MEC and Microcoroutines also run in sync with update, because underneeth it’s a single Update / FixedUpdate subscription manager.

I agree completely that it’s best to work with (leverage) the framework rather than against it unless there’s a show-stopper standing in the way. And, thinking about it a bit more, I’m going to need MonoBehavs on my GameObjects anyway because I need trigger and collision events. AFAIK, I cannot get those using a central controller.

The update issue aside, my main goal is to instantiate and configure pretty much everything at runtime via prefabs as I want the user to be able to customize players (uniforms, faces, etc.). Virtually nothing will be set up statically in the Scene using the Editor, other than some “hooks” to allow prefab access. Anyway, all of that is the topic of another thread…

Thank you (and everyone) for the responses!!! I just came from Apple’s SceneKit-land where support is practically non-existent.

When ever I have more then a few tens of gameobjects doing Update I do the manager that gets the unity event and dispaches to the objects.

When you get to the hunderds/thousands it gets very significant.
When you get to the range of thousands I’d also consider cutting down on function calls, I’ve seen performence increase in the range of 70% (the calculations in it were very low cost so it had a bigger impact, but still) when I moved some logic from a seprate function and stuck it in the update, I can post said code when I get home if anyones interested.