---
title: "【优化】Messages of Monobehaviour"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/unity-monobehaviour-message-optimization/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/05-游戏图形与运行时/游戏性能优化/【优化】Messages of Monobehaviour.md"
content_hash: 5c5e3d7edc8266ce994bea69eb1bffb5e6ec5836e319ba8992d1c1448ef2651d
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
# 【优化】Messages of Monobehaviour

> 创建时间：2021/1/26 15:22

  * 【优化】Messages of Monobehaviour
    * 对”Magic Methods”原理的理解
      * Unity官方文档中的解释
      * 其他博主的理解
    * Cost of magic methods
    * 优化方案：Update Manager
      * Experimentation
    * Ref

## 对”Magic Methods”原理的理解

### Unity官方文档中的解释

Internally, Unity tracks lists of objects interested in its callbacks, such as Update, FixedUpdate and LateUpdate. These are maintained as intrusively-linked lists to ensure that list updates occur in constant time. MonoBehaviours are added to/removed from these lists when they are Enabled or Disabled, respectively.
via. <https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity8.html>

### 其他博主的理解

‘Magic Methods’ are all the methods inherited from MonoBehaviour such as Awake(), Start(), Update(), FixedUpdate(), etc… When a MonoBehaviour is accessed for the first time, it is then scanned by the Common Language Runtime (CLR) for any ‘Magic Methods’ it may have in it. When the MonoBehaviour is scanned, all the ‘Magic Methods’ within it are then added to lists i.e. a list of Update() methods, a list of Start() methods, etc. Then when Unity calls these functions it simply iterates through the list of methods.
via. <https://creaturesurvive.github.io/repo/blog/unity-update-manager/>

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. During the game Unity just iterates through these lists and executes methods from it.
via. <https://blogs.unity3d.com/cn/2015/12/23/1k-update-calls/>

## Cost of magic methods

  * They are calls from native C++ land to managed C# land. There is a small but significant overhead to invoking managed-code callbacks from native code

> All of our C# scripts that we create inside Unity are compiled into Managed Code, managed code is code that is read and interpreted by the CLR. whereas Unity is made up of C++ that is compiled into Native Code, native code is code that is read and interpreted directly by the computer making it really fast.
>  So here is the problem with this, Unity handles executing all of the magic methods from within the engine meaning its handled in Native Code, however the methods it is executing are contained in the Managed Code. Every time a method is executed from native to managed it generates overhead.

  * Unity carries out a number of safety checks before calling these functions. The safety checks ensure that the GameObject is in a valid state, hasn’t been destroyed, and so on.

## 优化方案：Update Manager

An update manager is a class that holds a reference to all of your MonoBehaviour’s and executes all of their Update() methods each frame.

An Update Manager works the exact same way as unity handles its ‘Magic Methods’, it simply has a list of all the methods and executes them as needed. However there is one key difference, It’s all handled in Managed Code, so instead of suffering the same overhead as the unity implementation on a per call basis, it only generates overhead once.

### Experimentation

Example:
10000 MonoBehaviours are created with this code inside:

```csharp
string s1 = &quot;Hello &quot;;
string s2 = s1;
s1 += &quot;World&quot;;

System.Console.WriteLine(s2);
//Output: Hello

```

10000 MonoBehaviours are created but instead of having an Update they have a custom UpdateMe method which is called by a manager script every frame like so:

```csharp
string s1 = &quot;Hello &quot;;
string s2 = s1;
s1 += &quot;World&quot;;

System.Console.WriteLine(s2);
//Output: Hello

```

![Alt text](/media/2945cd66c3f429ed0a54.png)

当有大量的GameObjects执行Update逻辑时，自己写Manager，对这些Update逻辑进行管理，能节省CPU耗时。

## Ref

<https://blogs.unity3d.com/cn/2015/12/23/1k-update-calls/>
<https://creaturesurvive.github.io/repo/blog/unity-update-manager/>
