对Start()方法执行顺序的思考

Unity版本:Unity5.6.4f1

在Unity中,先执行Awake()方法,后执行Start()方法

 

有这样一个例子,

public class Item:MonoBehaviour
{
  private UILabel name; //Item类的属性

  void start() 
  {
    //获取Item属性的代码
    name = transform.Find("name").GetComponent<UILabel>();
  };
          
  void SetName()
  {
    //给Item的属性赋值
    name = "Tom";
  }
}
public class UI:MonoBehaviour
{
  void start() 
  {
    //实例化Item,并调用Item.SetName 赋值
  };
}

本例中,UI类在Start()方法中实例化Item,并用Item类的方法给其赋值,这样写会导致空指针错误。

其实际的执行顺序是 : UI.Start() → Item.Awake() → Item.SetName() → Item.Start()

在name初始化前就对其赋值导致出错。

 

这样,我们就知道,Start()方法并不是在Awake() 执行完成后立即执行的。

查阅官方文档,事件函数的执行顺序如下

 

在Start()调用前,会进行一次OnEnable的判断,也就是Inspector界面,组件旁的√  ,我们通常可以把勾去掉以阻止脚本的执行。

这个方法并不是完美的,上文的例子中,若禁用了Item脚本,Item.Start()不会执行,而Item.Awake() 和 Item.SetName() 依然会执行。

 即禁用脚本并不能阻止Awake方法的执行,也不能阻止其他类调用该脚本的其他public方法。

 

 

 

PS:一个有趣的现象

当一个脚本中没有定义Start及后续事件函数时,脚本旁的√ 会消失,无法设置OnEnable,如下图)

无Start及后续事件函数的情况

有Start及后续事件函数

笔者第一次遇到这种情况时,还以为又是Unity的小毛病,重启了好几次

 

 

总结:

1,初期的架构很重要

2,坚持代码的风格可以有效防止错误,也能快速定位错误

3,为防止再次出现这种错误,决定以后统一写法,将初始化语句写入一个独立的函数,然后在赋值前调用,确保赋值前完成初始化。

posted @ 2018-03-04 19:41  neos1891  Views(276)  Comments(0)    收藏  举报