第九章 C#脚本(下)

news2025/1/15 17:44:42

本章节我们说一说MonoBehaviour这个类,它的内部有很多方法用来执行不同的逻辑。Unity脚本从唤醒到销毁都有着一套比较完善的生命周期,添加任何脚本都要遵守生命周期法则!直白的讲,就是MonoBehaviour类中的方法的执行是有严格的顺序的。我们常用的方法如下所示:Awake --> OnEnable --> Start --> Update --> FixedUpdate --> LateUpdate --> OnGUI --> OnDisable --> OnDestroy

1. Awake :意为唤醒方法,该方法在所有游戏对象被实例化之后调用,可用于游戏开始前初始化。在脚本整个生命周期内它仅被调用一次。需要注意的是,Awake方法的执行与否与当前脚本的状态(启用或禁用)并没有关系,而是与当前脚本所绑定的游戏对象的状态有关。

2. OnEnable :意为激活方法,当游戏对象变为可用状态时被调用。通常也是执行一次。但是如果当前游戏对象被取消后再重新激活启用,该方法会被再次执行一次。

备注:游戏对象可以激活启用,也可以取消不启用,在Inspector检视视图中最上面的游戏对象名称的左边的勾选框来设置。默认是勾选状态,也就是启用,去掉勾选就是不可用状态,被取消的游戏对象不会在场景中被渲染出来,也不会执行任何的组件行为。游戏对象的脚本可以激活启用,也可以取消不启用。我们之前说过,脚本属于组件。每一个组件都可以激活或者取消。组件的激活或取消同样在Inspector检视视图中组件名称前的勾选框来设置。如果我们取消组件的话,该组件将不再提供它对应的功能。如果是脚本的话,则脚本里面的大部分代码将不会执行(Awake方法和OnDestroy方法仍然会执行)。


 

3. Start :意为开始方法,仅在Update方法第一次被调用前调用。Start在脚本的生命周期中只被调用一次。它和Awake的不同是Start只在脚本实例被启用时调用,且Awake先执行。

4. Update :意为正常帧更新方法。每一帧都被循环调用执行。一般情况下,游戏的交互逻辑,动画播放等等都会在这里完成,我们大部分代码都是在这里完成的。

5 . FixedUpdate :意为固定帧更新方法。该方法会按照固定时间被循环调用。这个固定时间通常是0.02秒,当然也可以通过菜单“Edit”-->“Project Setting”-->“Time”选项窗口中右侧的 “Fixed Timestep”输入框进行修改。如下图所示:

这里我们需要解释一下FixedUpdate和Update的区别。我们上面已经讲过FPS值不是一个固定的数值,也就是Update方法的调用次数也不是固定的。产生这样的原因是因为,Update主要用于游戏画面的渲染,这项工作需要消耗计算系的大量性能,而且与当前场景的有关。如果当前场景的游戏对象很多,游戏特效也多,那么渲染该场景画面就需要消耗大量的时间;相反,渲染画面的时间就非常短;这就造成了Update方法的执行时间不固定,因此我们就无法保证1秒钟内调用固定次数的Update方法了。但是,对于某些物理行为的更新,这种Update操作可能会产生误差。因为在现实世界中,任何物体的物理行为(例如移动)肯定是按照固定的时间进行改变了。例如,某人按照1米/秒的速度前进,5秒后他肯定在前方5米的位置上。如果我们在Update方法中处理该逻辑的话,就不如在固定时间的FixedUpdate方法中处理更好一些。因为调用 FixedUpdate 的频度常常超过 Update,这个会让我们的物理行为计算更加准确,对物理行为的渲染效果也更加友好,但需要更大的计算机性能开销。

6. LateUpdate :在每帧Update方法调用后被调用,可用于Update的补充。如果在 Update 内让角色移动和转向,可以在 LateUpdate 中执行所有摄像机移动和旋转计算。这样可以确保角色在摄像机跟踪其位置之前已完全移动。

7. OnGUI :在渲染和处理GUI事件时调用。该方法也是每帧执行一次。

8. OnDisable :当游戏对象不可用状态时被调用,与OnEnable方法相反。

9. OnDestroy :当游戏对象被销毁的时候被调用,与Awake方法相反。

上面的几个方法是常用的,当然还有其他一些方法。比如我们给当前游戏对象添加碰撞体 (Collider) 组件后,就可以在脚本中使用OnCollisionEnter,OnCollisionStay,OnCollisionExit方法进行碰撞检测,然后做出对应的逻辑处理。这些内容我们会在后面的章节详细介绍。

接下来,我们就来验证上面的方法的执行,同时为下一个问题做铺垫。

我们在当前工程中创建三个Cube立方体游戏对象,名称为cube1,cube2,cube3

为了能够区分不同的游戏对象,可以在Inspector检视面板游戏对象名称的最左边的下拉弹框中选择一个不同颜色的Icon用于区分,这个不影响游戏的运行效果。

然后我们创建四个脚本,分别是Test1.cs,Test2.cs,Test3.cs和Test4.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test1 : MonoBehaviour
{
    private void Awake()
    {
        Debug.Log("Test1 Awake");
    }

    private void OnEnable()
    {
        Debug.Log("Test1 OnEnable");
    }

    void Start()
    {
        Debug.Log("Test1 Start");
    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log("Test1 Update");
    }

    private void FixedUpdate()
    {
        Debug.Log("Test1 FixedUpdate");
    }

    private void LateUpdate()
    {
        Debug.Log("Test1 LateUpdate");
    }

    private void OnGUI()
    {
        Debug.Log("Test1 OnGUI");
    }

    private void OnDisable()
    {
        Debug.Log("Test1 OnDisable");
    }

    private void OnDestroy()
    {
        Debug.Log("Test1 OnDestroy");
    }
}

以上只是Test1.cs脚本的内容,我们将这个脚本附加到Cube1上面。

为了更好的展示当前脚本代码运行的效果,我们将之前的“Test.cs”脚本取消不启用。

接下来,我们就来Play运行当前工程。

从日志来看,我们大致能够看到优先执行了Awake,OnEnable和Start方法,然后就开始循环执行FixedUpdate,Update,LateUpdate,OnGUI四个方法,最后的OnDisable和OnDestroy方法是我们停止运行的时候调用的。关于单一脚本内方法执行顺序我们就不继续讨论了。

接下来,我们将Test1的代码复制到Test2, Test3和Test4中,修改日志输出的TestX名称即可。以下是“Test2.cs”脚本文件的部分代码内容。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test2 : MonoBehaviour
{
    private void Awake()
    {
        Debug.Log("Test2 Awake");
    }

    // 省略其他代码

}

以下是“Test3.cs”脚本文件的部分代码内容。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test3 : MonoBehaviour
{
    private void Awake()
    {
        Debug.Log("Test3 Awake");
    }

    // 省略其他代码

}

以下是“Test4.cs”脚本文件的部分代码内容。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test4 : MonoBehaviour
{
    private void Awake()
    {
        Debug.Log("Test4 Awake");
    }

    // 省略其他代码

}

然后,我们需要依次将Test2附加到cube2上,Test3附加到cube3上,Test4也附加到cube3上。请注意,这个附加操作的顺序不能改变哦!

 

最后我们重新Play当前工程。

 

 

从上面的日志我们大致能得到两个结论。第一,Unity会执行完所有脚本的Start方法后再去执行所有脚本的Update方法(这里面比较特殊就是Awake和OnEnable方法,以及OnDisable和OnDestroy方法,由于他们都是结对出现,因此被一起执行);第二,就是所有脚本中相同方法的执行顺序,这是顺序大致是按照附加操作的先后顺序反向执行,也就是先附加的后执行,后附加的先执行。请注意,是附加到游戏对象的操作顺序,并不是Inspector检视视图上的脚本的上下顺序哦。因为我们附加的顺序是Test1.cs,Test2.cs,Test3.cs和Test4.cs。因此脚本执行的顺序则是Test4.cs > Test3.cs > Test2.cs > Test1.cs。那可能有人就会产生疑问,这个附加操作是人为产生的,每个人的操作大概率是不太一样的,所以这个代码的执行顺序会跟随开发人员的操作不同而不同。这个问题,有些时候确实会出现问题,尤其是各个脚本之间有前后依赖关系的时候。如何能够固定这些脚本的执行顺序呢?当然可以了!我们在Project工程视图中点击任意一个脚本文件(Test1.cs),然后查看其对于的Inspector检视视图。

在右上角有一个“Execution Order…”按钮,我们点击一下。

在弹出的新窗口中,右下角有一个“+”按钮,点击这个按钮会弹出一个列表,该列表中列举出了当前的C#脚本文件,我们依次选择“Test1”,“Test2”, “Test3”,“Test4”。

当我们添加完毕后,发现每一个方法后面都有一个Default Time数值,他们依次为100,200,300,400。注意Default Time值越小,对应的方法越先执行。因此,我们的数值设置就决定了脚本会按照“Test1”->“Test2”->“Test3”->“Test4”进行执行。当然,这个顺序只影响同一个方法(例如Start)不同脚本的执行先后顺序,而对于不同方法的顺序执行还是之前的(Awake --> OnEnable --> Start等等)。设置方法后点击“Apply”应用一下,就可以关闭这个窗口了。然后我们Play当前工程查看日志。

我们就拿“Start”方法来验证,发现他们的执行顺序就变成了Test1,Test2,Test3和Test4了。

最后,我们再说一个简单的问题。所有的组件都可以在Inspector检视视图中编辑其属性,脚本也不例外。脚本的属性其实就是对外公开的类变量而已。这个类变量可以是一个普通的基本数据类型,也可以是另一个组件,也可以是场景中的另一个游戏对象。这里需要注意的是,必须将变量声明为 public 才能在 Inspector 中查看该变量。接下来,我们创建“Demo.cs”的脚本文件,并在脚本中添加一个“name”的字符串变量,如下所示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Demo : MonoBehaviour
{
    // 对外公开的属性变量
    public string name = "";

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log(name);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

为了方便我们的测试,我们之前的所有附加脚本全部取消(在Inspector检视视图中去掉脚本组件名称前面的勾选框即可),然后将我们当前的“Demo.cs”附加到摄像机上面。

当我们附加成功后,我们就会发现下面出现一个“Name”的属性输入框。该属性就是我们在脚本中定义的类变量(name),我们在输入框中输入文本“hello”,然后Play工程。

 

我们可以看到输出了我们在Inspector检视视图中输入框中的文本“hello”。同时我们还发现,虽然我们禁用了脚本组件,但是还执行了Awake方法。我们上文提到,Awake方法的执行与游戏对象的状态有关,与组件的状态无关,OnDestroy同理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/471055.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows强制删除文件夹

命令:rd/s/q 路径 如果文件较大,需要等待几分钟,但一定会删掉的。

使用Fork和GitHub完成团队项目开发

前提 拥有自己的GitHub账号项目组组长已经创建好了 一个远程仓库能够科学上网安装了Fork软件 基础步骤 该内容分为两个部分,分别为团队协作者(项目成员)和团队组织者(项目组长),我们首先来介绍作为项目成员…

Docker-Compose 了解 部署nginx与lnmp

Docker-Compose Docker-compose 简介YAML 文件格式及编写注意事项Docker Compose配置常用字段Docker Compose 常用命令Docker Compose 文件结构部署 composeDocker Compose 环境安装 compose部署nginx(1)准备依赖文件编写配置文件docker-compose.yml com…

学生无线耳机哪款好?两百左右适合学生党的无线耳机推荐

学生无线耳机哪款好?现如今,学生党也成为了蓝牙耳机的主要用户群体之一。接下来,我来给学生群体推荐几款两百左右的无线耳机,一起来看看吧。 一、南卡小音舱Lite2蓝牙耳机 参考价:299 南卡小音舱的音质和佩戴体验都在…

Vue过渡与动画的实现效果

使用 transition 标签配合 CSS3 过渡实现【不完整代码】: Vue 还提供了四个 class 类名,分别是进入的起点(v-enter)进入的终点(v-enter-to)离开的起点(v-leave)离开的终点&#xff…

纷享销客标讯通,大客招标经营的杀手锏

呀,对手都中标了,我咋才知道?呀,能不能预测目标客户的招标?呀,对手有什么客户可以挖一挖? 呀,ROI 300倍的奥秘是什么? 纷享销客标讯通,帮助企业&#xff1a…

射频基础(一)

目录 一、电磁波 二、直射波 三、反射波 四、绕射波 五、散射波 六、趋肤效应 七、多径效应 八、阴影效应 九、菲涅尔区 十、慢衰落和快衰落 一、电磁波 电磁波是能量的一种,凡是高于绝对零度的物体,都会释出电磁波。电与磁可说是一体两面,电…

85.qt qml-炫酷烟花粒子特效(支持多种爆炸模式(文字)、爆炸阴影、背景场景)

效果如下所示: 截图如下所示: 实现内容如下所示: 1.实现多个爆炸效果2.爆炸的时候增加光度阴影效果3.由于场景有湖面,所以还需要增加一个倒影粒子组首先我们来学习下,该示例中所需要常用的类型点 1.如何更改粒子生命周期时的颜色变换动画 方法有两种。 1.1通过colorTable和s…

在 PDF 中添加文本的 3 种简单方法

我们更喜欢将我们的文件保存为 PDF 并打印它,这样打印的文件将保持原始的完美结构。你不得不承认,有时候,当你打印一个 Word 文件时,它可能会打印出乱七八糟的排版,这对进一步的工作来说是令人沮丧的。 PDF在我们的日…

【Python基础篇】从Hello, world到函数几分钟看完就都会了~

大家好,我是辣条哥~ Python是一种高级编程语言,易于学习和使用。以下是Python入门基础的一小部分: 目录 安装Python:编写第一个Python程序变量和数据类型运算符算术运算符:比较运算符:逻辑运算符&#xff1…

[CDC 2018] 理解压缩对抗隐私

Understanding Compressive Adversarial Privacy | IEEE Conference Publication | IEEE Xplore 摘要 本文提出了一种新的隐私保护方法,称为 压缩对抗隐私(Compressive Adversarial Privacy,CAP),它结合了 压缩感知和 …

移动通信网络频段大全

01 5G NR 3GPP已指定5G NR 支持的频段列表,5G NR频谱范围可达100GHz,指定了两大频率范围: ①Frequency range 1 (FR1):就是我们通常讲的6GHz以下频段,被称为 sub 6GHz; •频率范围&…

TDA4VM/VH 芯片硬件 mailbox

请从官网下载 TD4VM 技术参考手册,地址如下: TDA4VM 技术参考手册地址 概述 (Mailbox 的介绍在 TRM 的第7.1章节) Mailbox 使用邮箱中断机制实现了 VM 芯片的核间通信。 Mailbox 是集成在 NAVSS0 域下的一个外设(NAVSS0 的说明可以查看&a…

(六)ArcCatalog应用基础——目录内容浏览

(二)ArcCatalog应用基础——目录内容浏览 目录 (二)ArcCatalog应用基础——目录内容浏览1.目录内容浏览2.地理数据浏览3.表格数据浏览3.1调整、冻结、排列3.2修改属性3.3表格数据统计3.4查询3.5数据字段的增删 1.目录内容浏览 Ca…

职责链设计模式解读

目录 问题引进 传统方案解决 OA 系统审批,传统的设计方案(类图) 传统方案解决 OA 系统审批问题分析 职责链模式基本介绍 基本介绍 职责链模式的原理类图 对原理类图的说明 职责链模式解决 OA 系统采购审批 应用实例要求 思路分析和图解(类图) 代码落地 …

局域网远程桌面工具推荐

有多种软件选项适用于局域网 (LAN) 中的远程桌面,包括 微软远程桌面、Splashtop、Teamviewer 等。 以下是根据性能、安全性、价格、品牌历史和其他因素对这些软件选项进行的详细比较和分析。 微软远程桌面: 微软远程桌面是专为 Windows 设备设计的远程…

题解,超星进程

A - Geometric Progression 思路&#xff1a;矩阵快速幂 构造[1,c]*[f(n-1)] [0,c] [c^(n-2)] ​ #include<bits/stdc.h> #include<iostream> using namespace std; typedef long long ll; ll a, x, MOD; struct matrix {ll a1, a2, b1, b2;matrix(ll a1, …

Day957.重构“烂代码” -遗留系统现代化实战

重构“烂代码” Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于重构“烂代码”的内容。 一、基于坏味道的重构 在重构时&#xff0c;要尽量先去识别《重构》中总结的二十几种坏味道&#xff0c;再用书中对应的重构手法去重构。可能会质疑&#xff0c;要不要这么教条…

powershell搞定烦人的Windows Defender

0x00 Windows Defender真烦 最近装了不少虚拟机&#xff0c;发现目前较新版本的windows Defender是真的烦&#xff0c;关了一段时间后&#xff0c;自己又打开。特别是装了域控后的winserver 2016&#xff0c;半都关不掉&#xff0c;做个实验是真烦。 顺手去查了下如何使用pow…

如何查看自己是否使用了国产SSL证书?“套牌”SSL证书?

最近有用户提到国产SSL证书&#xff0c;有没有符合历史及现在浏览器信任的99%的国产SSL证书&#xff0c;目前看到一些网站正在使用国产SSL证书&#xff0c;而且价格很便宜&#xff0c;大概两千多&#xff0c;而且还符合99%是真的吗&#xff1f;他们属于国产SSL证书吗&#xff1…