11
\$\begingroup\$

Why does Unity use reflection in order to access MonoBehaviour message methods like Awake, Update, Start,...?

Wouldn't it be slow to use reflection? Why doesn't it leverage other approaches like Template Method? It could simply define the methods as abstract in MonoBehaviour base class and force the subclasses to implement it.

\$\endgroup\$
18
\$\begingroup\$

It doesn't

How Update is called

No, Unity doesn’t use System.Reflection to find a magic method every time it needs to call one.

Instead, the first time a MonoBehaviour of a given type is accessed the underlying script is inspected through scripting runtime (either Mono or IL2CPP) whether it has any magic methods defined and this information is cached. If a MonoBehaviour has a specific method it is added to a proper list, for example if a script has Update method defined it is added to a list of scripts which need to be updated every frame.

During the game Unity just iterates through these lists and executes methods from it — that simple. Also, this is why it doesn’t matter if your Update method is public or private.

As for the reasons it is done this way, I'll largely refer you (the reader) to DMGregory's answer, which boils down to a balance of two competing things:

  1. Performance optimization
  2. Ease of new developer utilization

A new developer just wants it to Work and doesn't want to have to figure out "how do I connect this in to the event system?" but it should still run fast with minimal overhead.

The solution is probably the best that can be achieved within these two constraints. Or at least, the best the Unity dev team was able to come up with at the time. We may never know.

\$\endgroup\$
  • 2
    \$\begingroup\$ tl;dr same process, different, faster API. But why did they not choose a different method as asked by OP? \$\endgroup\$ – wondra Oct 29 '18 at 7:31
  • 10
    \$\begingroup\$ We should not deny the possibility of plain old "bad design" reason. After release of c# source code users have found tons of mistakes and unexplained design decisions. Some gamedevs were finally able to understand those unexpected behaviours they were fighting with for years. \$\endgroup\$ – Exerion Oct 29 '18 at 7:48
  • \$\begingroup\$ Technicalities aside this is among the first things newcomers learn, so it must be easy to add or skip. \$\endgroup\$ – Nikaas Oct 29 '18 at 8:37
  • 6
    \$\begingroup\$ There might also be historic reasons for this design. Unity started out with their own scripting language, which they then gradually phased out in favor of C#. It is just natural that they wanted to keep using the same patterns, even if it meant to cheat a bit. \$\endgroup\$ – Philipp Oct 29 '18 at 9:34
  • 3
    \$\begingroup\$ I think we can usefully answer "What does Unity accomplish by this means" — eg. what's the advantage over a collection of a abstract public methods that must all be implemented. We can't answer "what were the Unity devs thinking?" but we can tackle "why is this approach useful to users of the engine?" \$\endgroup\$ – DMGregory Oct 29 '18 at 13:51
8
\$\begingroup\$

It could simply define the methods as abstract in MonoBehaviour base class and force the subclasses to implement it.

One of the advantages of the system Unity uses is that you don't have to implement every MonoBehaviour message, of which there are over 60.

Usually we just need one or a small handful of these methods. Since some are specific to 2D/3D physics, some unique to cameras or particle systems, it's highly unlikely that any one script would ever need all of them.

By leaving the messages we don't need as unimplemented, we can clearly signal to the runtime "don't even bother calling OnCollisionStay2D on this object — I don't need it"

This can be a substantial efficiency win. Now the engine can filter down a short-list to call Update on only the ~20 objects in my scene that need custom update logic every frame, and not all ~200 objects that make up all the scenery or only respond to physics events.

\$\endgroup\$
  • \$\begingroup\$ Just a question... as far as I know (not personally), if you have thousands of GameObjects, all of which use a script with an Update method, you have significant performance impacts. The alternative is to use lists and iterate through them with only one Update method in a manager script, which seems to be significantly more performant. Is that still the case, or did that change already? -- If nothing changed, it would imply that Unity's way to do it is nowhere near optimum regarding performance. \$\endgroup\$ – Battle Oct 29 '18 at 14:05
  • 3
    \$\begingroup\$ @Battle what you describe is consistent with the link that Draco18s cites from 2015, and I'd suspect it's still true. Being able to leave the Update method undefined on those thousands of objects is precisely what allows this optimization to work. If every MonoBehaviour had an Update method defined via an abstract base class as described in the section of the question I quoted, then we wouldn't have the ability to limit our update calls to just the manager's list iteration. Note that this Q&A doesn't address "Is Unity's approach optimal?" but only how the current approach can be of benefit. \$\endgroup\$ – DMGregory Oct 29 '18 at 14:15
  • \$\begingroup\$ Ah I see, that makes indeed sense. Thanks for the answer! \$\endgroup\$ – Battle Oct 29 '18 at 14:20
  • \$\begingroup\$ @Battle Its still true. While the thing Unity does is more performant than the alternatives it still has more overhead than a regular function call. \$\endgroup\$ – Draco18s Oct 29 '18 at 16:05
  • \$\begingroup\$ @Draco18s - Yeah. I already implemented an UpdateManager for my projects which takes care of that optimization long time ago. I just wanted some confirmation that it is still needed/useful. \$\endgroup\$ – Battle Oct 29 '18 at 16:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.