浅谈Unity中的MonoBehaviour

从第一次在unity创建C#脚本开始就会发现每个脚本都继承了一个叫MonoBehviour的类,那么MonoBehaviour是做什么的呢?




一层层进入MonoBehaviour父类,不妨看出MonoBehaviour间接继承了Component,所以继承自MonoBehaviour的脚本充当的是组件的角色,当我们需要将一个自定义脚本以组件的形式添加到对应的GameObject时(Unity中Inspector面板中的每一项都称为组件,包括创建的脚本),该脚本是必须要继承MonoBehaviour,否则无法添加为组件。


那么如果继承了MonoBehaviour,那么这个类的生命周期是怎样的呢?
首先可以将生命周期分为两种状态

  • 编辑器下的状态:只有Reset函数一个
  • 运行状态(真正的生命周期):除Reset函数外,其余函数都在运行状态执行(加特殊字段,也可以在编辑器运行)

Reset函数

只能在编辑器模式下执行,点击Reset或者添加该脚本到游戏物体上时执行(这个方法我几乎没有用过不是很常用)


Awake,OnEnable,Start函数:
Awake:仅执行一次,当游戏物体被创建的时候执行,无论该脚本是否处于激活状态,只要游戏物体处于激活状态即可执行。
在Inspector面板中的脚本组件上有一个复选框,这是在脚本中有生命周期函数时才会显示的,但是测试后发现只有Awake和Reset并不会出现复选框,因为这两个函数与脚本是否激活无关。
OnEnable:可执行多次,当组件设置enable = true或游戏物体 active = true 调用。
Start:仅执行一次,当游戏物体处于激活状态并且脚本也处于激活状态才可以执行。



上述是生命周期的开始,先将生命周期的运行跳过,先来说说生命周期的结束。

OnApplicationQuit,OnDisable,OnDestroy函数:

OnApplicationQuit:当你的应用程序退出时,会先调用OnApplicationQuit。
OnDisable:除在OnApplicationQuit调用时会调用,还会再设置enable = false 或 active = false 调用。
OnDestory:除在OnApplicationQuit调用时会调用,还有在Destroy游戏物体时调用。
 



看完了生命周期的开始与结束,下面是比较重要的部分——生命周期的运行过程


FixedUpdate,Update,LateUpdate函数:
可以将生命周期的运行以Update函数作为分割线,FixedUpdate,物理系统,输入系统的相关函数都是在Update之前先执行,携程是在Update之前LateUpdate函数之后执行。



FixedUpdate与Update:
FixedUpdate:每帧调用而且每帧的时间间隔间隔是固定的,不受帧率(FPS)影响。每一帧的时间是在Edit->Project Settings->Time面板中的Fixed Timestep设置,默认为0.02s,则0.02秒为一帧也就是每帧之间的间隔是0.02s。
对于更新频率比较稳定的物理系统来说就合适放在FixedUpdate中处理,如果在Update中处理则会出现抖动效果。
FixedUpdate原理实际上是位移=速度*时间。因为他是固定时间调用的所以自动乘上了fixedDeltaTime,而Update并不是按照单位时间调用的所以想要解决帧率不一致这个问题就需要乘以Time.deltaTIme。
Time类的相关详解:
Time类详解
Update:每帧调用但是每帧的时间间隔不固定,受到帧率影响,而帧率(FPS)与电脑性能有关。
例如FPS是30,则每秒执行30帧,如果FPS是10,则每秒执行10帧。是不稳定的。



写了一个例子更好的说明FixedUpdate与Update的区别


用不同的脚本控制两个人物移动,一个用FixedUpdate,一个用Update。
无论帧率(FPS)如何变化,用FixedUpdate移动的人物一秒钟都是移动固定的距离,而当帧率为50时,用Update移动的人物一秒钟是移动50M,而帧率为10时,用Update移动的人物一秒钟就只会移动10M。



LateUpdate比较好理解:
LateUpdate:与Update一样每帧之间的时间是不固定的,受到帧率影响,而帧率(FPS)与电脑性能有关。
先举个例子,比如一家三口要出去玩,每个人的起床都在Update中执行,则出发应该在LateUpdate中执行,这样就保证了在都都起床之后才出发。
所以相机的跟随一般在LateUpdate中实现,这样可以确保在人物移动结束后再进行相机的跟随。
 



很重要的一点,官方对于LateUpdate解释成一句话:LateUpdate是在所有Update函数调用后被调用。
比如写两个脚本,挂载到同一个游戏物体上,同时拥有这三个关于Update的方法,运行查看输出结果。


这也就不难理解为什么相机跟随操作要放在LateUpdate函数中实现了
每个游戏物体中脚本上的同名函数会被放在同一个线程中,执行完Awake线程再执行Stat线程.....
得出结论:在Unity中所有脚本的Awake函数执行完才会执行Start函数,所有Start函数执行完才会执行Update函数。


普通类与继承MonoBehaviour类的区别:

1.继承MonoBehaviour的类不需要创建它的实例,也不能自己创建(用new),因为从MonoBehaviour继承过来的类Unity会自动创建实例,并且调用被重载的函数(Awake,Start.....)。
如果用new会出现以下警告:


警告说的很明显,就是如果继承了MonoBehaviour就不允许你用new创建,你可以用添加组件的方式替代,或者根本没有基类(不继承MonoBehaviour的普通类)。
2.不继承MonoBehaviour不能使用Invoke,Coroutine,prin以及生命周期函数等。
3.不继承MonoBehaviour不能挂在到Inspector上,也就是说不能看到公有的参数。

猜你喜欢

转载自blog.csdn.net/LLLLL__/article/details/88187367