有些人问继承MonoBehaviour的类,都可以自动调用Start、Update方法,那可以将其写成虚方法吗?这样派生类都可以进行重载实现?
答:其实我们查看MonoBehaviour类的定义,发现MonoBehaviour 中看不到这些函数,派生类也并没有特别的override或者new关键字,也不能base.Start(),所以Start、Update 方法并不属于 MonoBehaviour 类。
那为什么派生类只要写了这些函数,都可以自动调用呢。
答:我们知道Unity大致上分为两个部分,大部分核心逻辑使用Cpp开发,之后包装一层C#,把C#接口开放给开发者。
在 Runtime时候,引擎CPP部分会去检测继承MonoBehaviour的类,如果发现有实现这些函数则会注册进列表,后面游戏中引擎仅仅需要简单地遍历列表,执行这些方法就行。这样调用,和正常函数调用性能差不多,绕过了虚拟机内部一大堆的处理
这样实现的优点:
1、内存。空函数也是占内存的,不是所有派生的monobehaviour都需要实现,只是按需实现。如果MonoBehivour作为基类声明了所有的start、update这种空函数,那么每个对象都都会有一大量的空函数,这就很浪费了。
2、性能。unity主循环会遍历所有的monobehaviour,调用空的函数,虽然函数为空,但是call的时候也是会有消耗的。
所以unity做了一件事,在cpp层实现了个类似C# 反射的机制,其实就是直接去找Start、update的函数指针。如果这个monobehaviour有实现start,那么就调,没那么就不调。monobehaviour自身就干干净净的不包含这些函数的定义。让用户自己按需声明。