Unity3D Awake OnEnable Start 和Update 先后顺序探究

版权声明:本博客能容版权由本人所有,未经本人许可,不可转载。 https://blog.csdn.net/mynameiszhuli/article/details/88224640

Unity中,我们知道同一个脚本的Awake,OnEnable,Start和Update是按照先后顺序运行的。

有如下疑问:

  1. 多个脚本在一个GameObject上的时候,每个Awake一定会比所有脚本的Start要早吗?每个Awake一定会比所有脚本的OnEnable要早吗?
  2. 当GameObject是通过代码Instantiate或者AddComponent的时候这些方法的先后顺序到底是怎样的呢?一个物体在一帧中instantiate的时候,他们的脚本是在同一帧进行Update,还是在下一帧呢?

下面,我们就进行实验。

问题一:同一个GameObject上的不同脚本之间是什么顺序

一个基类代码如下:

public class ScriptBase : MonoBehaviour {
    protected virtual string ScriptName
    {
        get
        {
            return "ScriptBase";
        }
    }
        
    protected virtual void Awake()
    {
        LogMessage ("Awake");
    }

    protected virtual void OnEnable()
    {
        LogMessage ("OnEnable");
    }

    protected void Start () 
    {
        LogMessage ("Start");
    }
  
    protected void Update () 
    {
        LogMessage ("Update");
    }

    private void LogMessage (string message)
    {
        Debug.LogFormat ("{0}({1}) {2} frame {3}", name, ScriptName, message, Time.frameCount);
    }
}

public class ScriptA : ScriptBase {
    protected override string ScriptName 
    {
        get 
        {
            return "ScriptA";
        }
    }
}

public class ScriptB : ScriptBase 
{
    protected override string ScriptName 
    {
        get 
        {
            return "ScriptB";
        }
    }
}

public class ScriptC : ScriptBase {
    protected override string ScriptName 
    {
        get 
        {
            return "ScriptC";
        }
    }
}

给大家看一篇场景设置和运行结果

场景内容

物体配置

从结果中我们可以看出,有三个阶段:

  1. Awake和OnEnable ,一个脚本Awake之后马上执行OnEnable。
  2. Start
  3. Update

所以,不能保证一个脚本的Awake一定比所有脚本的OnEnable要早。但是可以保证一个脚本的Awake一定比所有脚本的Start早。同样道理,可以保证一个脚本的Start一定比所有脚本的Update早。

 

问题二:Instantiate时候的执行顺序是怎样的?

首先给大家分享Instantiate的脚本,注意,这里我直接修改Prefab的名字,实际上,直接修改Prefab是非常不推荐的。这里是因为方便大家查看Log,才不得不直接修改Prefab的名字。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IntantiateOrderTest : MonoBehaviour {
    public GameObject Prefab;
    bool _firstUpdate;
    void Awake(){
        _firstUpdate = true;
        Prefab.name = "AwakeGameObject";
        Instantiate<GameObject> (Prefab);
    }
    void Start(){
        Prefab.name = "StartGameObject";
        Instantiate<GameObject> (Prefab);
    }
    void Update(){
        if (_firstUpdate) {
            Prefab.name = "UpdateGameObject";
            Instantiate<GameObject> (Prefab);
        }
        _firstUpdate = false;
    }
}

我们来看一下场景设置和运行结果。

场景物体的配置

prefab的配置

得到如下结论:

  1. Awake和OnEnable实在Instantiate这一行运行的时候直接被调用的
  2. 在Awake和Start中创建的物体,它的Start是在同一帧执行的,它的Update也在同一帧中执行
  3. 一个物体如果是从Update的时候创建的,它的Start也是在同一帧执行,但是它的Update是在下一帧执行

猜你喜欢

转载自blog.csdn.net/mynameiszhuli/article/details/88224640