频道栏目
首页 > 程序开发 > 移动开发 > 其他 > 正文
再议Unity3D中的Awake(),OnEnable()和Start()
2017-04-24 09:48:19           
收藏   我要投稿

引言

近来遇到了一个问题,排查到最后,发现问题的原因在于,对于Unity原生函数执行顺序的理解还不到位。之前转载过一篇介绍Unity原生函数执行顺序的文章Unity3D中脚本的执行顺序和编译顺序

单纯的讨论一个GameObject的Awake在Start函数执行是没什么实际意义的。当遇到动态加载对象,或者相互引用时,情况要复杂一些。

官方介绍

First Scene Load

These functions get called when a scene starts (once for each object in the scene).

● Awake: This function is always called before any Start functions and also just after a prefab is instantiated. (If a GameObject is inactive during start up Awake is not called until it is made active.)

● OnEnable: (only called if the Object is active): This function is called just after the object is enabled. This happens when a MonoBehaviour instance is created, such as when a level is loaded or a GameObject with the script component is instantiated.

● OnLevelWasLoaded: This function is executed to inform the game that a new level has been loaded.

Note that for objects added to the scene, the Awake and OnEnable functions for all scripts will be called before Start, Update, etc are called for any of them. Naturally, this cannot be enforced when an object is instantiated during gameplay.

Before the first frame update

● Start: Start is called before the first frame update only if the script instance is enabled.

For objects added to the scene, the Start function will be called on all scripts before Update, etc are called for any of them. Naturally, this cannot be enforced when an object is instantiated during gameplay.

可以看到Awake和OnEnable是在GameObject instantiate阶段被调用的。而Start是在Update第一次执行前被调用的。

测试

测试用例:

写了两段脚本,第一段脚本StartGo.cs挂在默认对象上,通过点击场景上的按钮来动态创建第二个对象,其上挂载着第二段脚本DynamicGo.cs。

StartGo.cs

using UnityEngine;

using System.Collections;

public class StartGo : MonoBehaviour {

private bool operateOnce = false;

void Awake()

{

Debug.Log("StartGo Awake, frame: " + Time.frameCount);

}

void OnEnable()

{

Debug.Log("StartGo OnEnable, frame: " + Time.frameCount);

}

// Use this for initialization

void Start ()

{

Debug.Log("StartGo Start, frame: " + Time.frameCount);

}

// Update is called once per frame

void Update ()

{

if (!operateOnce)

{

Debug.Log("StartGo Update, frame: " + Time.frameCount);

operateOnce = true;

}

}

void OnGUI()

{

if (GUI.Button(new Rect(100, 100, 200, 30), "Create Dynamic Go"))

{

Debug.Log("Click Create Dynamic Go, frame: " + Time.frameCount);

GameObject go = Resources.Load("DynamicGo") as GameObject;

GameObject.Instantiate(go);

Debug.Log("Instantiate Finished, frame: " + Time.frameCount);

}

}

}

DynamicGo.cs

using UnityEngine;

using System.Collections;

public class DynamicGo : MonoBehaviour {

private bool operateOnce = false;

void Awake()

{

Debug.Log("DynamicGo Awake, frame: " + Time.frameCount);

}

void OnEnable()

{

Debug.Log("DynamicGo OnEnable, frame: " + Time.frameCount);

}

// Use this for initialization

void Start ()

{

Debug.Log("DynamicGo Start, frame: " + Time.frameCount);

}

// Update is called once per frame

void Update ()

{

if (!operateOnce)

{

Debug.Log("DynamicGo Update, frame: " + Time.frameCount);

operateOnce = true;

}

}

}

运行结果:

这里写图片描述
这里写图片描述
这里写图片描述

1.其中StartGo.cs的Start信息在OnEnable的下一帧打印出来,而DynamicGo.cs的Start信息与OnEnbale在同一帧打印出来。

2.通过查看DynamicGo的堆栈调用,可以看到OnEnable与Awake是在UnityEngine.Object:Instantiate阶段被调用的。而Start是在Update执行之前在会触发。

结论:

OnEnable与Awake是在GameObject实例化阶段被调用的。

Start可能与OnEnable在同一帧执行,也可能在OnEnable的下一帧执行。

点击复制链接 与好友分享!回本站首页
上一篇:Firebase系列之---Cloud Messaging/Notifications(云消息,推送)的使用
下一篇:TextWatcher中的参数
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站