第十章 游戏对象和组件访问

news2024/11/25 5:33:47

本节我们主要学习GameObject类,该类用于表示任何存在于场景中的游戏对象。这个类继承自Unity Object类(不是C#语言的Object类),我们可以理解这个Unity Object类是所有Unity的基类。这个Unity Object基类比较简单,我们很少使用这个基类的内容。我们还是重点介绍一些GameObject 类吧。GameObject 类有几个比较重要的类实例变量经常使用

1. activeSelf                    获取自身(激活状态)。

2. activeInHierarchy        获取自身(激活状态,与父游戏对象有关)。

3. name                           游戏对象的名称(其实是来自基类Object中)

4. scene                          游戏对象所属的场景Scene类。

5. layer                            游戏对象所属层(层的概念我们后面章节会详细介绍)。

6. tag                               游戏对象的标签(标签的概念我们后面章节会详细介绍)。

7. transform                     游戏对象的世界变换,所有游戏对象都拥有该组件。

以上的变量都可以通过GameObject的实例对象进行调用,不能直接通过类名调用。它代表了游戏对象的基本属性,因此有时候也称之为属性变量。

接下来我们继续介绍GameObject类的一些常用方法,如下所示:

1. setActive方法,参数为true或false,也就是激活或停用当前游戏对象,这个相当于我们在Inspector检视视图中游戏对象名称左边的那个勾选框。

2. AddComponent  给游戏对象添加指定类型的组件,可以是Unity内部标准组件,也可以是我们自定义的C#脚本。组件必须附加到游戏对象上面才能使用。

3. GetComponent返回指定类型的一个组件,如果没有就返回null。

4. GetComponents返回指定类型的所有组件,要么返回组件数组,要么返回null。

5. GetComponentInChildren从子游戏对象上面获取组件,游戏对象可以形成父子关系。

6. GetComponentInParent从父游戏对象上面获取组件,游戏对象可以形成父子关系。

7. CompareTag当前游戏对象是否使用了指定标签,标签就是一个字符串而已。

我们发现GameObject类的大部分方法都是用来查询并获取组件的。以上的方法都是普通方法,需要获取GameObject类实例后才能调用。接下来我们介绍GameObject类的静态方法。关于类的实例成员(变量和方法)和静态成员(变量和方法)的区别,大家一定要注意区分了。静态成员是直接通过类名进行调用的,而实例成员则是类的实例化对象调用的。

1. Find按照名称查询游戏对象,没有查到返回null。

2. FindWithTag按照标签(字符串)查询游戏对象,没有查到返回null。

3. FindGameObjectsWithTag 按照标签(字符串)查询所有游戏对象,返回数组或者null。

由此可见GameObject类的静态方法大部分是用来查询并获取游戏对象的,这样的设计也可以理解。毕竟如果需要实例化一个游戏对象后才能查询其他游戏对象,这样的操作就太繁琐且不人性化了,就不如使用静态方法直接查询并获取游戏对象。最终我需要记住的就是,GameObject类的静态方法是用来获取其他游戏对象的,而普通方法是用来获取游戏对象自身组件的,而实例变量则是获取游戏对象自身的一些基本属性(名称,标签,层等等)。

接下来,我们继续介绍一下MonoBehaviour类,它是一个基类,所有 Unity 组件脚本都继承该类(当然我们也可以定义普通的C#类在组件脚本中使用)。我们上面章节中讲解了它的一些内部方法(Start,Update等等),这些内部方法是Unity自动调用的,他们跟游戏的生命周期密切相关。接下来,我们说一说MonoBehaviour类的其他内容,首先是它的类实例变量

1. enabled当前脚本是否可用。

2. isActiveAndEnabled当前脚本是否激活可用,与附加游戏对象状态相关。

3. gameObject 当前脚本附加的当前游戏对象

4. name当前游戏对象名称

5. tag当前游戏对象的标签

6. transform当前游戏对象的transform组件

我们发现,它的大部分属性就是GameObject类中的属性。这样做的目的,就是方便我们在脚本中直接获取自身游戏对象的常用属性。避免我们先获取自身游戏对象实例,然后再通过该实例获取游戏对象属性。接下来就是MonoBehaviour类的一些常用方法,如下所示:

1. CompareTag当前游戏对象是否使用了指定标签

2. GetComponent按照类型获取一个组件

3. GetComponentInChildren从子游戏对象中获取一个组件

4. GetComponentInParent从父游戏对象中获取一个组件

5. GetComponents  按照类型获取所有组件

6. GetComponentsInChildren        从子游戏对象中获取所有组件

7. GetComponentsInParent从父游戏对象中获取所有组件

这个就比较明显了,在MonoBehaviour类中方法就是所属游戏对象中的方法,这样的设计可能是让我们更加方便的在脚本中对当前的游戏对象进行操作。当然,在MonoBehaviour类中还有一些事件类方法,他们的使用是有条件的。例如我们之前讲过的碰撞体(Collider)组件使用,还有就是一些用户响应事件(鼠标点击,键盘按下等等),这些内容我们会在后面的章节中详细介绍。

接下来在“ScriptDemo”工程中创建一个新的场景,点击菜单栏“File”->“New Scene”

我们选择“Basic(Built-in)”场景,然后点击右下角的“Create”按钮,就会创建一个Unity默认模板的场景,里面包含一个摄像机,平行光和一个天空盒。创建完毕后,我们继续点击菜单栏“File”->“Save”来保存当前新创建的场景,取名为“SampleScene2”,如下所示

我们选中“Scenes”目录,将我们的场景文件保存到“Scenes”目录下

保存成功后,我们就可以在Project工程面板中同步看到场景文件了。

每一个场景都会以个文件(.unity)形式保存。现在的大部分RPG游戏基本上都是多场景的,即便是同一个世界地图,也都是按照不同的区域分成各个小地图,那么这些小地图都可以理解为一个个的场景。这样做的好处在于可以将每一个地图场景独立开发,而不影响其他地图场景。接下来,我们在新场景中创建两个Cube游戏对象,分别取名为cube1和cube2。

接下来,我创建一个脚本文件“CubeTest1.cs”,并将该脚本附加到Cube1上面。为了更好的组织和管理脚本,我们在“Assets”目录下创建一个“Scripts”目录,并将我们刚刚创建的“CubeTest1.cs”脚本保存到这个目录下。创建目录非常简单,只需要在Project面板空白处右击选择“Create”->“Folder”,然后将目录命名为“Scripts”即可。

创建脚本完毕后,即可将其拖拽到Cube1上面,也就是它的Inspector检视面板中

然后双击脚本,打开VS补全我们的脚本代码

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

public class CubeTest1 : MonoBehaviour
{
    // Mesh Renderder组件
    private MeshRenderer meshRenderer;

    // Start is called before the first frame update
    void Start()
    {
        // 当前游戏对象名称
        Debug.Log(name);
        Debug.Log(gameObject.name);

        // 获取Mesh Renderder组件
        meshRenderer = GetComponent<MeshRenderer>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            meshRenderer.enabled = false;
            Debug.Log("Cube1 消失");
        }
    }
}

我们逐一来解释这些代码。首先,我们定义了一个类实例变量meshRenderer,它的类型是MeshRenderer,也就是渲染组件,在上面的截图中,我们能够看到这个组件,这个组件的用途就是将游戏对象cube1渲染出来。我们在Start方法中通过GetComponent方法来获取,该方法是从当前游戏对象(cube1)上面获取组件实例,而不是从当前场景中获取该组件(组件是挂载到游戏对象上面的)。然后在Start方法中,我们还访问了当前脚本MonoBehaviour的name属性以及gameObject游戏对象的name属性,其实这两个就是一回事(都是打印游戏对象的名称)。然后紧接着在Update方法中,我们检测字母A按键是否按下,如果被按下的话,我们就禁用MeshRenderer组件(渲染组件失效),那么游戏对象cube1将会从场景中消失。我们Play当前工程,然后仅给出控制台日志截图。

备注,如果游戏对象的组件在检视面板中被禁用的话,无法通过GetCompont找到。

接下来,我们继续创建“CubeTest2.cs”脚本,内容如下:

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

public class CubeTest2 : MonoBehaviour
{
    // 定义公开的字符类实例变量
    public string hello = "hello,unity! ";
}

在这个脚本中,我们只定义了一个普通的类变量。注意,如果Start和Update方法没有使用的话,最好将其删除掉,不要留着空方法在当前脚本类中。接下来,我们将这个“CubeTest2.cs”脚本也附加到游戏对象cube1(不是cube2)上面,同时调整“CubeTest1.cs”脚本内容。

接下来,我们还需要修改“CubeTest1.cs”的脚本代码

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

public class CubeTest1 : MonoBehaviour
{
    // CubeTest2脚本组件
    private CubeTest2 cubeTest2;

    // Start is called before the first frame update
    void Start()
    {
        // 获取CubeTest2脚本组件
        cubeTest2 = GetComponent<CubeTest2>();
        Debug.Log(cubeTest2.hello);
    }

}

CubeTest1脚本内容我们只展示修改的部分,其他部分不再展示了(其他代码没有改动)。

其实我们就是想从一个脚本中访问另一个脚本,脚本也是组件。因此,我们直接使用GetComponent方法来获取组件脚本,尖括号里面对应的就是想要获取脚本的类名称。然后我们打印CubeTest2脚本中的hello变量的内容。我们重新Play当前工程,查看日志输出。

接下来,我们继续调整“CubeTest1.cs”脚本内容,来获游戏对象cube2来试试

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

public class CubeTest1 : MonoBehaviour
{
    // Cube2游戏对象
    private GameObject cube2;

    // Start is called before the first frame update
    void Start()
    {
        // 获取Cube2游戏对象
        cube2 = GameObject.Find("Cube2");
        Debug.Log(cube2.name);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.B))
        {
            cube2.active = false;
            Debug.Log("Cube2 消失");
        }
    }
}

上面的代码非常简单,我们定义了一个GameObject游戏对象来代表立方体Cube2,然后在Start方法中通过GameObject类的静态方法Find通过游戏对象名称来获取Cube2,同时输出它的名称。然后在update方法中,我们检测字母B按钮是否按下,如果按下就让游戏对象Cube2失效,它也就是从场景中消失了。这里要注意,我们禁用游戏对象或者它的MeshRenderer组件,都会使得游戏对象不可见哦。我们Play工程查看日志输出吧。

最后说一下创建和销毁游戏对象GameObject。

在MonoBehaviour中有两个静态方法:Instantiate和Destroy,前者用户创建游戏对象,后者用于销毁游戏对象。Instantiate方法的参数列表有5个,一般情况下我们使用如下:

Instantiate (Object original, Vector3 position, Quaternion rotation);

第一参数通常是一个预制体(prefab),第二个参数是位置(向量),第三个是旋转朝向(四元数)。我们会在后面详细介绍这个方法的使用。而Destroy方法的使用比较简单,如下:

Destroy (Object obj, float t= 0.0F)

第一个参数就是需要销毁的游戏对象实例,也可以是组件,或者其他资源。

第二个参数代表延迟时间,单位是秒,也就是多少秒后才销毁该对象实例。

Destroy方法用于销毁游戏对象,该方法第二个参数可以设置延迟多次时间后再销毁。这个参数非常有用。比如我们创建子弹后,就可以调用这个方法来并设置子弹飞行多长时间后再销毁。这个方法我们也会在后面的章节中详细介绍如何使用。

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

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

相关文章

啃完这份笔记,18K妥妥的了......

大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;得准备面试了&#xff0c;又不知道从何下手&#xff01;为了帮大家节约时间&#xff0c;特意准备了一份面试相关的资料&#xff0c;内容非常的全面&#xff0c;真的可以好好补一补&#xff0c;希望大家在都能拿到理想…

MATLAB | 如何使用MATLAB绘制高度自定义的桑基图(sankey)

我之前也出过一个超简单的桑基图绘制函数&#xff0c;但是无法应对很多特殊情况&#xff0c;在这里我将其重构了一些写成了类&#xff0c;加了很多内置修饰函数&#xff0c;实现了流入流出数据不相等或者跨层数据流动的特殊情况绘制&#xff0c;首先展示一下使用我编写的函数能…

基于DSP+FPGA+ADS1282支持32Bit高精度数据采集方案(二)模拟电路设计

如图 4.1 所示是系统硬件系统的信号框图&#xff0c;数字信号处理板上的主要核心是 两个处理芯片&#xff0c;即 FPGA 和 DSP &#xff0c;其中 FPGA 主要作用是做 DSP 和外围接口的 桥梁及数据预处理&#xff0c; DSP 做为数据解算核心。 FPGA 通过各种的数据总…

【C++初阶】类和对象(一)

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;C初阶 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【C初阶】…

一文看懂低代码,5分钟从入门到原理全搞定

全球低代码市场已经走过了近20年&#xff0c;中国低代码市场近5年经历了百花齐放的广泛探索阶段&#xff0c;更旺盛的市场需求逐步在被激发。现在&#xff0c;让我们按下暂停键&#xff0c;看看这些产品给我们呈现了低代码市场一幅怎样的百景图。 低代码平台简介 广义上的低代…

[nesbot/carbon]轻松优雅的驾驭时间处理

简介 这个库的名字其实就很有意思&#xff1a;“carbon”&#xff0c;是化学元素的名字“碳”&#xff0c;为什么叫这个名字呢&#xff1f;在科学界&#xff0c;有一个"放射性碳定年法"的东西&#xff0c;是一种利用碳的同位素14C的放射性来对含有有机物质的物品进行…

废物,我TMD一个985却斗不过专科生(大厂自动化测试2年被裁)

前言 看到标题&#xff0c;可能很多读者朋友恐怕又要骂我了&#xff0c;985这个特殊的字眼也确实异常晃眼&#xff0c;实际上现在985&#xff0c;211也越来越多&#xff0c;它能代表你能够进入到更高的平台&#xff0c;拿到“高级工厂”的入场券&#xff0c;但并不意味着你会成…

每天一道算法练习题--Day14 第一章 --算法专题 --- -----------大话搜索

大话搜索 搜索一般指在有限的状态空间中进行枚举&#xff0c;通过穷尽所有的可能来找到符合条件的解或者解的个数。根据搜索方式的不同&#xff0c;搜索算法可以分为 DFS&#xff0c;BFS&#xff0c;A*算法等。这里只介绍 DFS 和 BFS&#xff0c;以及发生在 DFS 上一种技巧-回…

详解八大排序算法-附动图和源码(插入,希尔,选择,堆排序,冒泡,快速,归并,计数)

目录 &#x1f34f;一.排序的概念及应用&#x1f34f; 1.排序的概念 2.排序的应用 3.常用的排序算法 &#x1f34e;二.排序算法的实现&#x1f34e; 1.插入排序 1.1直接插入排序 1.2希尔排序&#xff08;缩小增量排序&#xff09; 2.选择排序 2.1直接选择排序 2.2堆排序…

LVS负载均衡群集部署—DR直接路由

目录 一、LVS-DR模式二、LVS-DR模式的特点三、LVS-DR中的ARP问题四、LVS-DR的优点与缺点五、为什么谁知lo:0而不是ens33:0六、LVS负载均衡群集-DR模式部署1.配置nfs共享&#xff08;192.168.154.10&#xff09;2.部署第一台nginx服务&#xff08;192.168.154.11&#xff09;3.部…

常用数据可视化对比类图表大全

优秀的数据可视化从来都不是罗列数据&#xff0c;更要根据自己的数据特征&#xff0c;设计出可以被读者轻松理解的图表。 图表类型有很多&#xff0c;选择正确图表的过程可能会让人混乱。本文将为您介绍数据可视化中比较类图表&#xff0c;以完美地表示您的数据并以最有效的方…

PostgreSQL安装和开启SSL加密连接【配置双向认证】

SSL单向认证和双向认证&#xff1a; SSL单向认证&#xff1a;只有一端校验对端的证书合法性&#xff0c;通常都是客户端来校验服务器的合法性。即在一般的单向认证中&#xff0c;只要求服务器端部署了ssl证书就行&#xff0c;客户端可以无证书&#xff0c;任何用户都可以去访问…

Rasa聊天机器人控制Python Turtle

背景 为了展示Rasa聊天机器人的使用效果以及如何将Rasa应用到业务系统中(这里将Python Turtle模块作为业务系统)&#xff0c;用户将语音或者文本输入至Rasa&#xff0c;经过处理后调用Python Turtle的功能。 turtle库是Python语言中一个很流行的绘制图像的函数库&#xff0c;想…

Docker常用命令笔记

docker常用命令 1 基础命令 sudo docker version #查看docker的版本信息 sudo docker info #查看docker系统信息&#xff0c;包括镜像和容器的数量 2 镜像命令 1&#xff0e;sudo docker images #查看本地主机的所有主机镜像 #解释 **REPOSITORY **#镜像的仓库源TAG **** …

微信小程序python+nodejs+php+springboot+vue 校园餐饮点单配送系统商家 配送员

管理员的主要功能有&#xff1a; 1.管理员输入账户登陆后台 2.个人中心&#xff1a;管理员修改密码和账户信息 3.学生管理&#xff1a;对注册的学生信息进行添加&#xff0c;修改&#xff0c;删除&#xff0c;查询 4.商家管理&#xff1a;对注册的商家信息进行添加&#xff0c;…

【在线研讨会】智慧汽车时代来临 -车规功能安全软硬件一次到位

随着科技的不断发展&#xff0c;智慧汽车的时代已经到来&#xff0c;在实现智慧汽车的过程中&#xff0c;车辆的功能安全、软硬件设计等方面都面临着严峻的挑战。为了确保智慧汽车的安全性和可靠性&#xff0c;在硬件设计方面&#xff0c;需要考虑到各种可能出现的故障和安全风…

日撸 Java 三百行day39

文章目录 说明day39 关键路径1.关键路径2. 代码分析 说明 闵老师的文章链接&#xff1a; 日撸 Java 三百行&#xff08;总述&#xff09;_minfanphd的博客-CSDN博客 自己也把手敲的代码放在了github上维护&#xff1a;https://github.com/fulisha-ok/sampledata day39 关键路…

PMP课堂模拟题目及解析(第1期)

1.在一个大型施工项目的规划阶段&#xff0c;出现了潜在的经济衰退迹象。之前关于经济衰退的风险被指定为低概率和高影响&#xff0c;预计持续 6-12 个月。项目开始后不久 发生了经济衰退&#xff0c;并按预期影响项目。六个月后&#xff0c;经济衰退影响的持续时间将更改为 24…

网络通信与密码相关概念流程

文章目录 前言一、明文通信二、密文通信1.对称加密2.非对称加密 三、安全信任机制1.CA(Certificate Authority) 证书授权中心2.数字证书 总结 前言 随着科技的发展&#xff0c;人们的通信都转化成电子通信&#xff0c;由于信息需要通过一个公有的网络进行传输&#xff0c;信息…

Spring IOC 源码解读

将回答以下问题&#xff1a; BeanFactory 和 ApplicationContext 之间的关系和区别。一个 Bean 是如何被注入到 IOC 容器里&#xff0c;中间经历了什么过程&#xff08;Bean 的生命周期&#xff09;。 先入为主 假设你已经有如下经验&#xff1a; 什么是 IOC。 don‘t call…