Unity 中的 Start、Update 方法是否属于 MonoBehaviour 类?
如果是,为什么在 MonoBehaviour 中看不到这些函数,而且也不是重写函数。我是这么认为的,调用这些函数,都是通过反射实现,也就是说这些函数只是约定好的,通过检测继承 MonoBehaviour 的类中是否存在这些字的方法来调用。我在 Unity Manual 却看到MonoBehaviour.Start()。还有一些网友贴的源码: unity魔改了mono cpp代码,自己拿csharp类的函数,注意这个函数是cpp代码里面的,类似于函数指针之类的,和csharp代码没啥关系
然后缓存起来,每次引擎cpp需要调用的gameoobject上面的组件时,直接告诉mono虚拟机调用某个csharp函数的cpp代表,绕过了正常的cpp和csharp交互逻辑
所以跟反射啥的都没太大关系,就是引擎魔改mono,改变了cpp和csharp交互方式
这种改法交互性能高,但就是太黑科技了,导致mono升级困难,unity现在自己维护一个mono版本
如果真用csharp语言自带的反射机制,那性能太差了
有点像cpp调用lua里面的函数一样,给个名字,cpp拿到lua函数的index,每次调用时候正常调用
这样调用,和正常函数调用性能差不多,绕过了虚拟机内部一大堆的处理
这种类方法的cache 用于跨语言的函数调用
因为csharp语言运行时有完整的运行时类型信息,所以很方便根据函数名字来找函数指针 是反射,
写Start/Update时,并没有特别的override或者new关键字。也不能base.Start()使用Rider写了一个空的Update时,IDE会提示删掉它。这是因为,不被反射到就不会调用,就不会有性能开销。MonoBehaviour类的C#部分在这,直接看就知道了。https://github.com/Unity-Technologies/UnityCsReference/blob/9034442437e6b5efe28c51d02e978a96a3ce5439/Runtime/Export/Scripting/MonoBehaviour.bindings.cs
具体来说,它的反射并不是使用.net库(System.Reflection)来实现的。
我们知道,Unity大致上分为两个部分,大部分核心逻辑使用Cpp开发,之后包装一层C#,把C#接口开放给开发者。
这里的反射的详细做法是,由Cpp在C#的runtime层面反射出相应的方法,并由Cpp集中管理和调用。(如Update之类的方法,并不会每帧反射一次,而是一开始反射完了就直接存起来。)
(网络上流传有unity4.x泄露的源码,可以仅以学习目的去看看实现。(充钱的话也可以看到最新的源码) 这种没有显式调用的方法叫做魔术方法(magic method)。很多人以为它们都是通过反射(System.Reflection)去调用的,这可能是一个常见的知识误区。
其实是mono或者il2cpp会去检查MonoBehavior里有没有这些魔术方法,有的话就把它们注册进列表。游戏中仅仅简单地遍历列表,执行这些方法。这也就是为什么魔术方法无所谓是public还是private的原因了。 就是反射,这叫魔 术 方 法 对的,你没猜错,就是反射来的 我也好奇过这个问题,然后在StackOverflow上提了个问,然后被删除关闭了
页:
[1]