zoukankan      html  css  js  c++  java
  • Unity中调用Awake,Start,Update等方法的原理机制

    首先声明这里的理解并不是官方释义,只是舶主根据晚上的各位大佬的关点理解总结的,如果有什么不对的地方希望大家指正:

    作为Unity中的生命周期准确的闹明白它的实现原理还是很重要的我认为。生命周期方法的实现机制实际上是一种类反射机制。Uniy引擎整体是架设在mono IDE基础上的。mono IDE是支持通过string来查找方法的,且和真正的反射一样是能够查找调用私有方法的,当找到这些方法后会存下指针,待使用。在引擎内部存在一张表,这张表的形成是通过在场景中查找全部的MonoBehaviour

    类型脚本然后便利里面的方法,将需要的调用的方法是全部记录下来,然后进行调用。防止那些不需要调用的MonoBehaviour中的方法占用空间,节省资源开耗。Mono的API可能效率更高,但对于单次调用,性能仍然逊于虚方法调用。反射实际上是开销非常大的调用方式,比之虚方法来说要高得多,因此Unity选择使用反射并非是出于性能方面的考虑。实际上,每帧调用的这些事件方法从数量级上来说是很卑微的,反射造成的性能影响亦可忽略不计。

     Unity使用这种事件机制的根本原因是出于对灵活性的考虑。Unity采用组件式设计,触发一个事件,需要通知到相应gameobject的所有组件。如果使用多态来实现,则必须假设所有组件都派生自包含此事件的基类,或者筛选出派生自此基类的组件逐一通知。这样一来是麻烦,二来则容易带来复杂的继承关系,与组件式这种倡导用聚合代替继承的设计从理念上就是相悖的。
    另一方面的原因则是为了跟JS保持一致性。这种事件机制对于JS这种动态类型语言来说是浑然天成的。
    这种设计最大的缺陷在于事件名通过字符串耦合,如此一来,完全绕开了编译期静态检查,无法为事件调用的正确性提供保障;在复杂的系统里,也可能因为事件重名而导致bug。
     

    Unity的确是通过反射来调用脚本的方法的,并且这一过程会在运行时不停对所有MonoBehaviour遍历进行。

    Unity之所以统一地使用这一套固定的函数命名方案,便于明确地划出了每个函数需要做些什么。这样做的目的我猜测是有利用保留脚本的灵活性。这种做法被惯称为“事件机制”,一旦某个脚本被执行完成之后,它的控制权会重新回到调度管理处,可以轻松地再去执行下一个,并且也能在运行时通过反射方式让其它脚本使用Component.SendMessage进行调用。

    如果采用了抽象方式让子类去实现这样的方法,那么对于Unity本身的对象管理是没有任何好处的,并且对于拥有多个脚本组件的对象来说,维护成本不但增加了,还可能让脚本之间的管理变得混乱。

    使用反射也许会丢失一些性能,但却能让每个不同的MonoBehaviour之间看起来都是独立的,只需要在它提供的几个内置方法中关注自己的逻辑就可以了。
  • 相关阅读:
    使用vimdiff作为svn diff的查看代码工具
    Source Insight :在 { 后敲回车后让代码自动缩进
    关于浏览器内核的一些小知识
    Linux内存点滴 用户进程内存空间
    自定义eclipse代码模板
    sqlplus 小记
    LD_PRELOAD的用法 以及链接库的用法
    如何更方便的使用sooset
    [hadoop源码阅读][0]初衷和各种资源
    hadoop streaming和pipes资料
  • 原文地址:https://www.cnblogs.com/morning-lee/p/7509018.html
Copyright © 2011-2022 走看看