码迷,mamicode.com
首页 > 编程语言 > 详细

Unity3D中脚本的执行顺序和编译顺序

时间:2014-11-09 19:17:51      阅读:339      评论:0      收藏:0      [点我收藏+]

标签:style   blog   io   color   ar   sp   div   on   art   

在Unity中可以同时创建很多脚本,并且可以分别绑定到不同的游戏对象上,它们各自都在自己的生命周期中运行。与脚本有关的也就是编译和执行啦,本文就来研究一下Unity中脚本的编译和执行顺序的问题。

先说一下执行顺序吧。
官方给出的脚本执行顺序如下图:

我们可以做一个小实验来测试一下:
在Hierarchy视图中创建三个游戏对象,在Project视图中创建三条脚本,如下图所示,然后按照顺序将脚本绑定到对应的游戏对象上:

三条脚本的代码完全一样,只是做了一点名称上的区分:

 1 using System.Collections;
 2 
 3 public class Scring0 : MonoBehaviour
 4 {
 5     void Awake()
 6     {
 7         Debug.Log("Script0 ======= Awake");
 8     }
 9 
10     bool isUpdate = false;
11     void Update()
12     {
13         if(!isUpdate)
14         {
15             Debug.Log("Script0 ======= Update");
16             isUpdate = true;
17         }
18     }
19 
20     bool isLateUpdate = false;
21     void LateUpdate()
22     {
23         if(!isLateUpdate)
24         {
25             Debug.Log("Script0 ======= LateUpdate");
26             isLateUpdate = true;
27         }
28     }
29 }

播放游戏,看看它们的执行顺序。如下图所示,Awake、Update、LateUpdate,无论运行游戏多少次,它们的执行顺序是完全一样的。

接着我们再做一个测试,把Script0的Update方法注释掉!!

 1 using System.Collections;
 2 
 3 public class Scring0 : MonoBehaviour
 4 {
 5    void Awake()
 6    {
 7        Debug.Log("Script0 ======= Awake");
 8    }
 9 
10 //   bool isUpdate = false;
11 //   void Update()
12 //   {
13 //       if(!isUpdate)
14 //       {
15 //           Debug.Log("Script0 ======= Update");
16 //           isUpdate = true;
17 //       }
18 //   }
19 
20    bool isLateUpdate = false;
21    void LateUpdate()
22    {
23        if(!isLateUpdate)
24        {
25            Debug.Log("Script0 ======= LateUpdate");
26            isLateUpdate = true;
27        }
28    }
29 }

再次运行游戏,看看它的结果。脚本的执行顺序和以前完全一样,Script0即便删除掉了Update方法,但是它也不会直接执行LateUpdate方法,而是等待Script1和Script2中的Update方法都执行完毕以后,再去执行所有的LateUpdate方法。

通过这两个例子,我们就可以很清楚地断定,Unity后台是如何执行脚本的了。每个脚本的Awake、Start、Update、LateUpdate、FixedUpdate等等,所有的方法在后台都会被汇总到一起:

1 后台的Awake()
2 {
3     脚本0中的Awake();
4     脚本1中的Awake();
5     脚本2中的Awake();
6 }

后台的方法Awake、Update、LateUpdate等等,都是按照顺序,等所有游戏对象上脚本中的Awake执行完毕之后,再去执行Start、Update、LateUpdate等方法的。

1 后台的Update()
2 {
3     脚本0中的Update();
4     脚本1中的Update();
5     脚本2中的Update();
6 }

然后我们来看看这样一种情况:在脚本0的Awake方法中创建一个立方体对象,然后在脚本2的Awake方法中去获取这个立方体对象。代码如下:

 1 脚本0的代码:
 2 using UnityEngine;
 3 using System.Collections;
 4 
 5 public class Script2 : MonoBehaviour
 6 {
 7     void Awake()
 8     {
 9         GameObject.CreatePrimitive(PrimitiveType.Cube);
10     }
11 }
12 
13 脚本2的代码:
14 using UnityEngine;
15 using System.Collections;
16 
17 public class Script0 : MonoBehaviour
18 {
19     void Awake()
20     {
21         GameObject go = GameObject.Find("Cube");
22         Debug.Log(go.name);
23     }
24 }

如果脚本的执行顺序是先执行Script0,然后再执行Script2,那么Script2中的Awake就可以正确地获取到该立方体对象;可是如果脚本的执行顺序是先执行Script2,然后是Script0,那么Script2肯定会报空指针错误的。

那么实际项目中的脚本会非常多,它们的先后执行顺序我们谁也不知道(又说是按照栈结构来执行的,即后绑定到游戏对象上的脚本先执行。这一点值得研究)。但一般的,建议在Awake方法中创建游戏对象或Resources.Load(Prefab)对象,然后在Start方法中去获取游戏对象或者组件,这样就可以确保万无一失了。
另外,Unity也提供了一个方法来设置脚本的执行顺序,在Edit -> Project Settings -> Script Execution Order菜单项中,可以在Inspector面板中看到如下图所示:

点击右下角的"+"将弹出下拉窗口,包括游戏中的所有脚本。脚本添加完毕后,可以用鼠标拖动脚本来为脚本排序,脚本名后面的数字也越小,脚本越靠上,也就越先执行。其中的Default Time表示没有设置脚本的执行顺序的那些脚本的执行顺序。

Unity3D中脚本的执行顺序和编译顺序

标签:style   blog   io   color   ar   sp   div   on   art   

原文地址:http://www.cnblogs.com/champ/p/4085686.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!