Component 组件脚本及其基本生命周期

【Unity编程】 Component 组件脚本及其基本生命周期




    3.1组件 Component

    组件是Unity中最核心的一个概念,它是一切编程的基础。没有组件,也就没有了Unity编程。

    打开一个新Unity工程,我们在Project面板中右键可以直接创建出一个C#脚本。

    脚本的内容如下:

    复制代码
    using UnityEngine;
    using System.Collections;
    
    public class NewBehaviourScript : MonoBehaviour {
    
        // Use this for initialization
        void Start () {
        
        }
        
        // Update is called once per frame
        void Update () {
        
        }
    }
    复制代码

         默认的脚本继承自MonoBehavior类,这个类是通常的自定义脚本组件继承类,也就是我们自己所编写的脚本的父类。而Unity内部组件,如相机等是继承自

    MonoBehavior的父类Behavior或者再上层的父类Component。Unity为何要分成三个级别继承?从Component到Behavior只是增加了一个是否可以enable

    的属性,用于区别有些组件是可以禁用的,而有些组件是不可以的。而从Behavior到MonoBehavior,则纯粹是为了Unity程序员准备的,因为它增加了很多响应

    消息,包括上面代码中看到的Start、Update以及后面提到的LateUpdate、FixedUpdate等消息。这些消息均是为了让程序员可以方便地控制和响应组件,而这

    些消息对于Unity内置组件来说它是不需要的,它内部自己知道什么时候需要进行启动、更新等等操作。

         因此,我们尝试参考MonoBehavior的文档,将常见的消息响应全部都打印到控制台上,于是代码看起来是这样:

    复制代码
    using UnityEngine;
    using System.Collections;
    using Assets.AndrewBox.Util;
    
    public class TestComponenets : MonoBehaviour 
    {
    
        void Awake()
        {
            Debuger.LogAtFrame("Awake");
        }
    
        void Start () 
        {
            Debuger.LogAtFrame("Start");
        }
        
        // Update is called once per frame
        void Update () 
        {
            //Debuger.LogAtFrame("Update");
        }
        void LateUpdate()
        {
            //Debuger.LogAtFrame("LateUpdate");
        }
        void FixedUpdate()
        {
            //Debuger.LogAtFrame("FixedUpdate");
        }
    
        void OnEnable()
        {
            Debuger.LogAtFrame("OnEnable");
        }
        void OnDisable()
        {
            Debuger.LogAtFrame("OnDisable");
        }
        void OnDestroy()
        {
            Debuger.LogAtFrame("OnDestroy");
        }
    }
    复制代码

    附加的Debuger类,用于打印消息,这里在显示消息的同时,记录了当前画面运行的帧数,以便于我们观察函数调用的次序以及时机:

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using UnityEngine;
    
    namespace Assets.AndrewBox.Util
    {
        public static class Debuger
        {
            public static void LogAtFrame(string infor)
            {
                Debug.Log("["+Time.frameCount+"]"+infor);
            }
        }
    }
    复制代码

    准备好代码之后,在场景中新建一个Cube(其实任意GameObject都可以),将TestComponenets拖放其上,然后尝试启动运行,并且在Cube的TestComponenets组件上,

    将勾选状态关闭再打开,可以看到控制台输出的内容。而后停止运行,将上述代码中的注释去掉,暴露出几个Update方法,再次运行以便查看结果。

    最终,我们可以得出如下结论:

    • Awake 方法:当GameObject被启用时,立刻被执行,中文的字面意思就是说,组件已经苏醒,但是它还没有执行,只是准备好了而已。只执行一次。
    • OnEnable方法:当组件被启用时(如果GameObject都没启用,组件更谈不上启用),立刻执行,当多启用时反复执行。
    • OnDisable方法:与OnEnable对应,当组件被禁用时,立刻执行,当多禁用时反复执行。
    • Start方法:当组件被启用后的下一帧,才会被执行。只执行一次。【特别注意,这里是下一帧,如果不注意的话,在资源加载方面可能会出现问题】
    • OnDestroy方法:当组件被销毁时执行。
    • Update:每帧执行一次,每秒刷新次数取决于硬件图像的刷新速度。
    • LateUpdate:每帧执行一次,后于Update执行,这里一般用作绘制到屏幕的最后处理(如无此特殊需要,用Update即可)。
    • FixedUpdate:默认按每隔0.02秒(具体时间可以设置)执行一次,与图像刷新率无关,用于物理逻辑计算。

    正常情况下,执行的顺序是如下图:

    也就是说,在Awake、OnEnable、Start之后开始几种Update循环。

    一般OnEnable用作处理开启和关闭组件时的开关量转换,那么对于此组件的初始化我们可以写在Awake和Start中。

    由于Awake是加载和启用GameObject后立刻执行的,因此,如果本组件跟随GameObject加载后,应该立刻初始化本组件的共有成员,如果这些成员需要被其它代码所访问的话。

    因为如果放在Start中初始化的话,那么还需要等待一帧,而这一帧过程中,很可能已经发生了对这些共有成员的访问,而此时尚未初始化。所以应该避免这种情况出现。

    我们暂时将其成为二阶段初始化,以便更好的记忆。在后续的章节中我们会有更多的体现。


    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值