Unity简单机制深究之一——谁调的Awake?
前言
最近突然发现很多基础知识虽然知道、会用,但是一问自己为什么却答不上来。这就说明自己的基础知识挖掘地不够深,在此做个学习总结。
Unity生命周期
这个是Unity官方文档的生命周期图解:
这里抛出几个问题。
1、MonoBehavior的第一个生命周期是什么?
2、Awake和Start是具体在什么时候调用的?
3、什么情况下不会走Awake?什么情况下不会走Start?
可以先在脑海中试想一下。
OK。
对于问题一,肯定都能不假思索地回答是Awake。
但是对于问题二和问题三,部分人可能就突然懵了。为什么会懵?因为生命周期这种基础知识实在是太过简单和基础了,平常开发过程中根本就没有想过会出现这种问题。然后如今突然一看发现这么简单的东西我居然不知道?内心突然产生急剧的落差。不由地感叹一句“卧槽?”。
细节总结
确实,在很多时候,越简单的东西越容易让人忽略细节。
这里就做一下生命周期有关问题的总结:
Awake是在MonoBehavior实例化的时候调用的,Start是在MonoBehavior第一次激活的时候调用的。
然而MonoBehavior需要等GameObject实例化的时候才会进行实例化。
GameObject只有在激活的时候才会实例化。
所以也就是说,只有当GameObject未实例化时,MonoBehavior的Awake才不会走。而只要MonoBehavior没有激活过,MonoBehavior的Start就不会走。
当场景中存在多个GameObject同时实例化时,Unity会优先把这些GameObject全部实例化完,之后再去实例化各个GameObject上的MonoBehavior。由此可见,在Awake中去查找场景中的GameObject是完全没问题的。但是,在实例化这些MonoBehavior的时候顺序是无法确定的。所以说MonoBehavior之间相互引用的代码应该在Start及之后。
还有一个需要注意的,Awake无法作为协程。
说到MonoBehavior实例化,可能有人会想到new一个MonoBehavior出来。
但实际上,如果尝试new一个MonoBehavior,Unity会告诉你说不允许,请使用AddComponent来创建实例。
Unity存在AddComponent方法,但是却没有RemoveComponent这种方法。
试想一下为何Unity要如此设计?难道添加一个RemoveComponent方法很麻烦吗?
并不是,Unity希望开发者多复用组件,减少组件的创建和卸载操作,毕竟新添加一个组件还是很费的。
如果实在是想删除组件,Unity还是提供了方式,调用UnityEngine.Object.Destroy( )可以删除GameObject、资源和组件。
后记
如果想知道Unity引擎非常具体地在哪调用的Awake,请自行查看引擎cpp源码。这里只是简单地补充一些平常不太会想到的细节知识点。
加油吧!打工人!
挖坑
Unity简单机制深究之二——为什么会出现委托?
Unity简单机制深究之三——传说中的三大坐标系
Unity简单机制深究之四——为什么Layout不刷新?