1. 调用时机
Start 方法在 Awake 方法之后被调用。具体来说,是在所有脚本的 Awake 方法执行完毕,并且游戏对象被激活后的第一帧更新之前调用。也就是它会在游戏开始时,游戏对象准备好参与游戏逻辑的第一时间被触发。
有点拗口,简单来说就是在Update调用前调用,但又晚于Awake和OnEnable。

从官方给的图就可以看出来,Start处于一个中间位置,如果一个游戏对象在场景加载时是非激活状态,那么它的 Start 方法会在它被激活后的第一帧更新之前调用。
当我们新建一个脚本文件时,Start会被创建好,这和Awake、OnEnable不同。
void Start()
{
print("Start调用");
}
我们可以测试一下Awake、Enable和Start的执行顺序。
private void Awake()
{
print("Awake调用");
}
private void OnEnable()
{
print("OnEnable调用");
}
void Start()
{
print("Start调用");
}

通过这个可以看出Start会被最后调用,并且哪怕调换一下他们在代码中的位置,结果依旧不会改变。
void Start()
{
print("Start调用");
}
private void Awake()
{
print("Awake调用");
}
private void OnEnable()
{
print("OnEnable调用");
}

2. 功能用途
Start用于执行比 Awake 更复杂的初始化操作。这些操作的资源可能依赖于其他脚本的 Awake 阶段,或者需要访问游戏对象在激活状态下的一些初始属性。例如,在一个多人在线游戏场景中,一个玩家脚本的 Start 方法可以用于初始化网络连接相关的设置,因为这可能需要等待其他脚本在 Awake 阶段完成一些基础配置。
private void Awake()
{
//初始化资源
}
void Start()
{
InitializeNetworkConnection();
}
void InitializeNetworkConnection()
{
// 网络连接初始化代码
}
此外,可以用于初始化那些依赖于游戏对象层次结构或者其他组件完整初始化的变量。一个脚本可能需要获取父对象或者子对象上的某个组件的引用,并且这些组件的 Awake 方法中可能有一些复杂的初始化逻辑,那么在 Start 方法中获取这些引用会更加安全。
public class ChildObjectScript : MonoBehaviour
{
private ParentObjectScript parentScript;
void Start()
{
parentScript = GetComponentInParent<ParentObjectScript>();
if (parentScript!= null)
{
// 基于获取到的父对象脚本进行操作
}
}
}
3. 注意事项
- 和 Awake 一样,Start 在整个脚本生命周期中也只被调用一次。所以在这个方法中进行的初始化操作应该是一次性的,不需要在后续阶段重复执行。
- 虽然 Start 方法通常在游戏开始时被调用,但如果在游戏运行过程中通过代码动态创建游戏对象并且添加脚本,那么新脚本的 Start 方法会在对象创建并激活后的第一帧更新之前调用。
- 不要在 Start 方法中放入那些应该在 Awake 方法中执行的简单初始化操作,以免影响脚本初始化的逻辑顺序。
2774

被折叠的 条评论
为什么被折叠?



