[Unity] Awake 与 Start 的使用, 为什么将 GetComponent 逻辑放到 Awake 中

Posted SlimeNull

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Unity] Awake 与 Start 的使用, 为什么将 GetComponent 逻辑放到 Awake 中相关的知识,希望对你有一定的参考价值。

如果你的 Unity 脚本是这么写的, 那么你需要注意了

using UnityEngine;

public class MyScript : MonoBehaviour

    SpriteRenderer spriteRenderer;
    void Start()
    
        spriteRenderer = GetComponent<SpriteRenderer>();
    

Unity 管线

Unity 不是完全渲染完 A 然后再去渲染 B 的, 而是先渲染 A 的一部分, 然后渲染 B 的一部分, 再渲染其他的一部分.

然后再次渲染 A 的一部分, 渲染 B 的一部分, 渲染其他的一部分

换做脚本, 假设有 ABC 三个对象, 执行的顺序应该是.

A.Method1
B.Method1
C.Method1

A.Method2
B.Method2
C.Method2

A.Method3
B.Method3
C.Method3

Awake 和 Start

Awake 和 Start 就相当于上面的 Method1, Method2, 所有对象的 Awake 都被调用一遍后, 然后再调用所有对象的 Start

不同对象顺序

Unity 是单线程, 所以 ABC 的 Method1 这种, 也是依次调用的, 也就是说, A 在调用 Method1 的时候, B 的 Method1 还没有被调用, 只能 A 的执行完之后轮到 B, 然后轮到 C

未初始化的变量

如果你把一些变量的初始化放在 Start 中, 那么在调用这个对象的 Start 前, 它的这些变量, 是完全没有初始化的, 为 null

引用未初始化的变量

如果你在某个对象没有调用 Start 前, 也就是它的变量未初始化时, 就调用这个对象的脚本暴露出来的一些公开方法, 例如依赖于 spriteRenderer 的 “角色姿态变换”, 那么, 由于 spriteRenderer 没有初始化, 你的程序就引发 NullReferenceException 了

假设 A 的 Start 中需要调用 B 的 “MethodQwq”, 在 B 的 MethodQwq 中, 用到了 B 类的字段 “spriteRenderer”, 但是, spriteRenderer 是在 B 的 Start 方法中被赋值的

当 A Start 执行时, 此时 B 的 Start 还没执行, B 的 spriteRenderer 为 null

A 的 Start 调用 B 的 MethodQwq, 因为 spriteRenderer 为空, 所以引发了 NullReferenceException

解决方案

统一在 Awake 方法中做变量的初始化, 统一在 Start 中做逻辑的开始执行. 这样在 Start 调用时, 所有对象的 Awake 已经调用过, 变量也全部初始化, 所以不会引发上述问题

以上是关于[Unity] Awake 与 Start 的使用, 为什么将 GetComponent 逻辑放到 Awake 中的主要内容,如果未能解决你的问题,请参考以下文章

Unity - 脚本的 Awake() 是不是在其他脚本的 Start() 之前运行?

如何正确继承Unity的回调函数,如Awake(),Start()和Update和FixedUpdate()?

酷熊科技工作积累 ----------- Unity3d中的Awake()OnEnable()Start()等默认函数的执行顺序和生命周期

Unity中Awake和Start的区别

Unity不同脚本或者多个脚本之间的执行顺序Awake, Start

Tip8:Unity中诸如 Awake() Start() Update()等函数的 执行顺序