【Unity脚本】Unity中如何按类型查找游戏对象(GameObject)

news2024/10/7 18:20:04
【知识链】Unity -> 脚本系统 -> 访问游戏对象 -> 按类型访问游戏对象

摘要:本文介绍了Unity中按类型查找游戏对象(GameObject)的五种方法,并提出了使用这些方法的最佳实践。

本文目录

    • 一、访问游戏对象的方法
    • 二、如何按类型查找游戏对象
    • 三、五种查找方法的使用
    • 四、最佳实践
    • 五、学以致用 - 随堂测验
    • 六、福利:给你介绍个对象:)

一、访问游戏对象的方法

在Unity中,对游戏对象进行操作前,首要步骤是确保能准确查找到目标游戏对象。Unity提供了多种脚本访问游戏对象的方法,以满足不同需求:

(1)通过名称访问:使用Find(string name)方法,通过指定游戏对象的名称来查找并获取该对象。

(2)通过标签访问:FindGameObjectsWithTag(string tag)FindWithTag(string tag)方法允许开发者通过标签来查找具有相同标签的游戏对象集合或单个对象。

(3)通过类型访问:FindObjectByType(Type type)方法允许开发者按照游戏对象的类型进行查找。值得注意的是,按名称和按标签的访问方法属于GameObject类,而按类型访问的方法则属于更广泛的Object类。由于GameObjectObject的子类,因此也可以通过类型访问游戏对象。

请添加图片描述
在这里插入图片描述

二、如何按类型查找游戏对象

按类型查找游戏对象作为Object类的一个重要方法,其核心功能在于实现针对特定类型的游戏对象的检索。该方法主要提供了五个不同的重载方法,以便用户能够根据不同的需求进行精确查找。具体方法如以下表格所示:

方法说明重载
FindAnyObjectByType查找任意按指定类型匹配的已加载的游戏对象(未排序时返回第一个匹配)public static Object FindAnyObjectByType(Type type, FindObjectsInactive findObjectsInactive);
FindFirstObjectByType查找第一个按类型匹配的已加载的游戏对象(排序后返回第一个匹配对象)public static Object FindFirstObjectByType(Type type, FindObjectsInactive findObjectsInactive);
FindObjectsByType查找所有按类型匹配的已加载的游戏对象(可以选择是否按InstanceID排序)public static Object[] FindObjectsByType(Type type, FindObjectsInactive findObjectsInactive, FindObjectsSortMode sortMode);
FindObjectOfType查找第一个按类型匹配的已加载的游戏对象(默认按InstanceID排序)public static Object FindObjectOfType(Type type, bool includeInactive);
FindObjectsOfType查找所有按类型匹配的已加载的游戏对象(默认按InstanceID排序)public static Object[] FindObjectsOfType(Type type, bool includeInactive);

在正式介绍各个方法的使用细节之前,我们首先需要明确每个方法中涉及的Type参数的含义。在此处,Type特指Object的类型定义。请注意,在后续的最佳实践部分,我们会明确指出,上述方法并不适用于查找资产类(Assets)资源。此外,本文末尾还将对Object的类别进行详细阐述,以便读者更好地理解与应用。

三、五种查找方法的使用

这五种方法均具备四种重载形式,现以FindAnyObjectByType方法为例进行详尽阐述,其余四种方法的使用方式与之相类似。

1. FindAnyObjectByType
重载方法:

public static T FindAnyObjectByType();
public static T FindAnyObjectByType(FindObjectsInactive findObjectsInactive);
public static Object FindAnyObjectByType(Type type);
public static Object FindAnyObjectByType(Type type, FindObjectsInactive findObjectsInactive);

(1)四种重载,可以分为两类,一是泛型方法,另外一种是指定对象类型的方法。
(2)从参数上看,两个参数
Type:要查找的对象的类型
FindObjectsInactive:是否包含附加到非活动游戏对象的组件。如果不指定此参数,则此函数不会在结果中包含非活动对象。

那如何选择在什么场合使用哪种重载方法呢?

如果你在编译时就知道要查找的类型,并且希望代码简洁,可以使用泛型方法 FindAnyObjectByType。
如果类型是在运行时动态确定的,或者你需要在不确定类型的情况下查找对象,可以使用 FindAnyObjectByType(Type, FindObjectsInactive)。

示例代码1 - 使用泛型方法

using UnityEngine;

public class FindAnyObjectByTypeWithInactiveExample : MonoBehaviour {
    void Start() {
        // 查找第一个匹配类型为 PlayerController 的对象,包括非活动对象
        PlayerController playerController = Object.FindAnyObjectByType<PlayerController>(FindObjectsInactive.Include);
        
        if (playerController != null) {
            Debug.Log("Found a PlayerController object.");
        } else {
            Debug.Log("No PlayerController object found.");
        }
    }
}

示例代码2 - 使用常规方法

using UnityEngine;

public class FindAnyObjectByTypeWithInactiveExample : MonoBehaviour {
    void Start() {
        // 查找第一个匹配类型为 PlayerController 的对象,包括非活动对象
        PlayerController playerController = (PlayerController)Object.FindAnyObjectByType(typeof(PlayerController), FindObjectsInactive.Include);
        
        if (playerController != null) {
            Debug.Log("Found a PlayerController object.");
        } else {
            Debug.Log("No PlayerController object found.");
        }
    }
}

2. FindFirstObjectByType

此方法用于查找第一个匹配类型的对象,包括非活动对象。

public static Object FindFirstObjectByType(Type type, FindObjectsInactive findObjectsInactive);

findObjectsInactive: 是否包含附加到非活动游戏对象的组件。如果不指定此参数,则此函数不会在结果中包含非活动对象。

2. FindObjectsByType

此方法用于查找所有匹配类型的对象,可以选择是否包含非活动对象,并对结果进行排序。

public static T[] FindObjectsByType(FindObjectsInactive findObjectsInactive, FindObjectsSortMode sortMode);

sortMode: 是否以及如何对返回的数组进行排序。不对数组进行排序可使此函数的运行速度显著加快。

FindObjectsSortMode有两个值

(1)InstanceID:对结果按InstanceID升序排列(InstanceID是Unity内部对每个对象指定的一个整数ID,只存在于Unity运行时,不能用于游戏逻辑)

(2)None:不对结果进行排序

4. FindObjectOfType

此方法用于查找一个类型的对象,默认查找活动对象,但可以选择包含非活动对象。

public static Object FindObjectOfType(Type type, bool includeInactive);

includeInactive:是否包含非活动游戏对象。如果不指定此参数,则此函数不会在结果中包含非活动对象。

5. FindObjectOfType

此方法用于查找所有匹配类型的对象,可以选择是否包含非活动对象。

public static Object[] FindObjectsOfType(Type type, bool includeInactive);

经过对比分析,FindObjectByType与FindObjectOfType的主要差异在于前者提供了是否进行排序的选项,而后者则默认对查找结果进行了排序处理。

值得注意的是,自2023.1版本起,FindObjectOfType和FindObjectsOfType这两个方法已被弃用。因此,在学习和使用过程中,我们应主要关注前三个方法。

弃用这两个方法的原因在于,它们对查找结果进行排序的过程消耗了大量时间,占据了整个查找过程用时的90%以上。为了提高效率,开发团队决定废除这两个方法,并推荐使用FindObjectByType等三个方法,由开发者自行根据需求决定是否对查找结果进行排序。如需更多信息,请查阅相关文档。
在这里插入图片描述

翻译一下就是:

使用Volvo测试项目和 Gigaya 对进入/退出游戏模式进行分析表明,在 FindObjectsOfType() 中花费的时间中约有 95% 用于按 InstanceID 对数组进行排序,尽管在几乎所有情况下这都被认为是不必要的。

在 Volvo 项目 (2022.1) 中,在单次进入/退出播放模式循环中,Object::FindObjectsOfType() 花费了 203 毫秒,其中 190 毫秒用于排序 (93.6%)

在 Gigaya (2021.3) 中,在单次进入/退出播放模式循环中,Object::FindObjectsOfType() 花费了 496 毫秒,其中 461 毫秒用于排序 (92.9%)

在 #devs-scripting 中,关于此问题的可能解决方案进行了长时间的讨论 (https://unity.slack.com/archives/C06TPSM32/p1651840563109579),现在达成的共识是弃用 FindObjectsOfType() 并将其替换为 FindObjectsByType()

让用户选择是否执行排序

请注意,让 API 更新程序自动将 FindObjectsOfType() 转换为FindObjectsByType(FindObjectsSortMode.InstanceID),因为我们确实希望用户根据具体情况评估其使用情况,并且只在必要时选择

排序以最大化性能增益

* 计划是:

2023.1 :

* FindObjectsOfType() 已过时(警告),将用户引导至 FindObjectsByType

* FindObjectOfType() 已过时(警告),将用户引导至 FindFirstObjectByType 和 FindAnyObjectByType

2023.2

* FindObjectsOfType() 已过时(错误),将用户引导至 FindObjectsByType

* FindObjectOfType() 已过时(错误),将用户引导至 FindFirstObjectByType 和 FindAnyObjectByType

2024.2

* FindObjectsOfType() 已删除

* FindObjectOfType() 已删除

这项工作已在 https://jira.unity3d.com/browse/COPT-854 中记录

在这里插入图片描述

四、最佳实践

当然在使用上述方法过程中还有以下需要注意的。

(1)以上方法都不能查看资源(例如mesh, texture, prefab),或者未激活游戏对象。如果对象设置了HideFlags.Dontsave标签,这个对象也不会被返回。可以使用 Resources.FindObjectsOfTypeAll 来避免以上的限制。

(2)在编辑器中,默认情况下会搜索场景视图。如果要在预制件阶段查找对象,请参阅StageUtility API。

(3)这里面速度最快的是FindAnyObjectByType,因为不会对结果进行排序。

五、学以致用 - 随堂测验

测验1:寻找任意一个指定类型的游戏对象
场景描述
你正在开发一个Unity项目,需要在游戏启动时找到场景中的任意一个Light组件,并根据它的属性设置其他组件的初始状态。
问题:在这种情况下,你应该使用哪种方法来查找Light组件?
A. FindAnyObjectByType()
B. FindFirstObjectByType()
C. FindObjectsByType()

测验2:寻找场景中所有的敌人对象
场景描述
你正在开发一个塔防游戏,需要在每一帧更新时遍历所有的敌人对象,以便调整它们的行为和状态。敌人对象都包含一个Enemy脚本组件。
问题:在这种情况下,你应该使用哪种方法来查找所有Enemy组件?
A. FindAnyObjectByType()
B. FindFirstObjectByType()
C. FindObjectsByType()

测验3:寻找第一个活动的玩家对象
场景描述
你正在开发一个多人游戏,需要在玩家加入游戏时找到第一个活动的PlayerController组件,以便初始化该玩家的相关数据。
问题:在这种情况下,你应该使用哪种方法来查找第一个活动的PlayerController组件?
A. FindAnyObjectByType()
B. FindFirstObjectByType()
C. FindObjectsByType()

六、福利:给你介绍个对象:)

(一)关于类型的说明
本文中所有方法参数中的Type指的是游戏对象的类型。在Unity中,Object类是所有游戏对象及组件的基类。从Object派生出来的所有类如下图所示。我们可以看出,绝大多数的类都属于Component(组件),这也和Unity组件化的架构设计是呼应的。
在这里插入图片描述
(二)介绍一下游戏对象

本文中提到按类型查找游戏对象的方法是不能用来查找游戏资产的。下面来介绍一下Unity中游戏对象(Object)和游戏资产(Assets)的区别与联系。

简单来说,游戏对象是游戏世界中的实体,动态存在并且可以在运行时操作,而游戏资产是静态资源,定义了游戏对象的属性和行为。游戏对象可以在Inspector中编辑属性,而游戏资产则是通过Project进行管理。

对于游戏对象和资产的关系,我们可以以搭建舞台为例:

  • 舞台上的道具、灯光、布景、音响等都是资产:这些道具、灯光、布景、音响等存储在仓库里,定义了舞台上将要使用的所有资源。
  • 当这些元素被使用在舞台上时,它们就成了游戏对象:这些元素一旦被放置在舞台上,并开始演出,它们就变成了具体的对象,成为演出的一部分。

二者间联系

  • 实例化:就像从仓库中拿出道具、灯光等并布置到舞台上,游戏资产也可以被实例化为游戏对象,并放置在游戏场景中。
  • 引用:道具的具体外观、灯光的颜色和强度等属性都由这些资产决定,正如游戏对象引用游戏资产来定义其属性和行为。

【学以致用】随堂测验的正确答案:(1)A(2)C(3)B

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

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

相关文章

【oracle】Oracle RAC中的GNS到底是什么?

本文为云贝教育 刘峰 原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎和未经注明出处的转载 一、概述 Oracle Grid Naming Service (GNS) 是Oracle Grid Infrastructure的一个重要组件&#xff0c;它提供了一种集中式的命名服务&…

css样式,点击 箭头方向上下转换

实现效果&#xff1a; 点击切换箭头方向 实现代码 <divclass"modelPart"click"showClick"><div class"modelPart_left"><img:srcaidefalutIconclass"sNodeIcon"><div>{{ selectModel }}</div><div …

C# 配置文件设置详解

文章目录 1. 配置文件在 C# 项目中的作用和重要性2. 不同类型的配置文件app.configconfig.exejson 3. 创建和修改配置文件文件位置添加内容修改内容保存和加载 4. 读取和写入配置文件app.config 文件读取config.exe 文件写入JSON 文件读写 5. 示例代码演示6. 配置文件在安全性方…

利用AI技术实现Medium文章的高效中文翻译

在深入学习大模型的过程中&#xff0c;我们常常需要查阅Medium上的技术文章。Medium作为一个流行的内容发布平台&#xff0c;汇集了大量高质量的技术和科学文章&#xff0c;对于希望紧跟技术前沿的学习者来说&#xff0c;是一个宝贵的知识库。然而&#xff0c;这些文章大多为英…

eclipse启动时间过长的问题

项目场景&#xff1a; 由于我用eclipse比较习惯&#xff0c;虽然IDEA很好&#xff0c;但是因为收费&#xff0c;所以在个人开发学习过程中一直还是使用eclipse&#xff0c;本文不讨论eclipse与IDEA孰优孰劣问题。 开发环境&#xff1a; 操作系统&#xff1a;Windows 11 22631…

CANDela studio之CDDT与CDD

CDDT有更高的权限&#xff0c;作为模板规范CDD文件。 CDD可修改的内容比CDDT少。 CDDT根据诊断协议提供诊断格式&#xff0c;主要就是分类服务和定义服务&#xff0c;一般是OEM释放&#xff0c;然后由供应商细化成自己零部件的CDD文件。 在这里举个例子&#xff0c;OEM在CDDT…

心链4---搜索页面前后端业务实现以及分布式session的共享实现

心链 — 伙伴匹配系统 搜索详情页面 之前前端的代码写到了搜索页面可以挑选搜索标签&#xff0c;并没有去根据具体标签搜索用户。这里就开始实现。 新建SearchResultPage.vue&#xff0c;并添加相关路由。 在搜索页添加搜索按钮&#xff0c;和触发点击。搜索页选择标签&#x…

ubuntu server 24.04 (Linux) 源码编译安装 OpenResty 1.25.3.1 Released

1 下载: OpenResty - 开源官方站 2 通过xftp等方式上传到ubuntu服务器 3 安装 #解压 tar zxvf openresty-1.25.3.1.tar.gz #创建运行用户 sudo groupadd www sudo useradd -g www www -s /bin/false #安装依赖软件 sudo apt update sudo apt-get install libpcre3-dev l…

数据分析之统计学基础

数据分析是现代企业和科研中不可或缺的一部分&#xff0c;而统计学是数据分析的基石。在本篇博客中&#xff0c;我们将介绍统计学的基础知识&#xff0c;涵盖数据类型、描述性统计&#xff08;集中趋势、离散程度和偏差程度&#xff09;&#xff0c;并通过代码实例加以说明。 …

释放 OSINT 的力量:在线调查综合指南

开源情报 (OSINT) 是从公开信息中提取有价值见解的艺术。无论您是网络安全专业人士、道德黑客还是情报分析师&#xff0c;OSINT 都能为您提供先进的技术&#xff0c;帮助您筛选海量的数字数据&#xff0c;发现隐藏的真相。 在本文中&#xff0c;我们将深入研究大量的OSINT 资源…

Vue进阶之Vue项目实战(四)

Vue项目实战 出码功能知识介绍渲染器性能调优使用 vue devtools 进行分析使用“渲染”进行分析判断打包构建的产物是否符合预期安装插件使用位置使用过程使用lighthouse分析页面加载情况使用performance分析页面加载情况应用自动化部署与发布CI/CD常见的CI/CD服务出码功能 出码…

AI赋能数字人:打造与语音节奏完美匹配的高质量手势动画

在数字化时代,人机交互正以前所未有的速度进化,而AI数字人的发展正是这一进程中的重要里程碑。近期,一项旨在根据语音内容自动生成匹配手势的技术方案引起了广泛关注,该技术不仅增强了数字人的表现力,也为远程沟通、教育、娱乐等多个领域带来了革新性的应用潜力。本文将深…

【ArcGIS For JS】前端geojson渲染行政区划图层并加标签

原理 通过DataV工具 生成行政区的geojson&#xff08;得到各区的面元素数据&#xff09;, 随后使用手动绘制featureLayer与Label&#xff0c;并加载到地图。 //vue3加载geojson数据public/geojson/pt.json,在MapView渲染上加载geojson数据 type是"MultiPolygon"fetc…

Web渗透-MySql-Sql注入:联合查询注入

SQL注入&#xff08;SQL Injection&#xff09;是一种网络攻击技术&#xff0c;攻击者通过将恶意的SQL代码插入到应用程序的输入字段&#xff0c;从而欺骗应用程序执行未经授权的操作。这种攻击方式可以导致严重的安全问题&#xff0c;包括&#xff1a; 数据泄露&#xff1a;攻…

【MATLAB源码-第216期】基于matlab的北方苍鹰优化算法(NGO)机器人栅格路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 北方苍鹰优化算法&#xff08;Northern Goshawk Optimization&#xff0c;简称NGO&#xff09;是一种新兴的智能优化算法&#xff0c;灵感来源于北方苍鹰的捕猎行为。北方苍鹰是一种敏捷且高效的猛禽&#xff0c;广泛分布于北…

qrcode和qrcodejs2生成二维码+刷新

1、使用qrcode生产二维码&#xff0c;封装组件 创建Qrcode.vue文件 <template><divclass"QRCode":style"{ width: width, height: height }"><canvas:id"canvasId"ref"canvas":style"{ width: width, height: …

上海冠珠旗舰总店盛装开业暨冠珠瓷砖中国美学设计巡回圆满举办

上海&#xff0c;这座融合了东西方文化的国际化大都市&#xff0c;不仅是中国的时尚中心&#xff0c;也是全球潮流的汇聚地。在这里&#xff0c;古典与现代交织&#xff0c;传统与前卫并存&#xff0c;为传统色彩与现代设计的融合提供了得天独厚的条件。 5月25日&#xff0c;上…

分频器对相位噪声影响

本文我们将分析输入时钟被N分频之后的输出时钟的相位噪声如何变化。首先理想分频器的意思是我们假设分频器不会引入附加相位噪声&#xff0c;并且输入和输出时钟之间没有延时。我们假设每一个输出边沿的位置都完美的与输入边沿相对齐&#xff0c;这样便于分析。由于每N个输入时…

简单3步,ERP、OA、CRM等客户端,安全远程访问服务端

如今&#xff0c;企业员工出差远程办公和分支机构的协同工作变得越来越普遍。然而&#xff0c;如何确保在不同地点的员工都能安全、便捷地访问公司内网的C/S&#xff08;Client/Server&#xff09;架构办公系统&#xff0c;是一个亟待解决的问题。 贝锐花生壳内网穿透服务提供…

Elasticsearch8.13.4版本的Docker启动关闭HTTPS

博主环境是&#xff1a; 开发环境&#xff1a;SpringbootElasticSearch客户端对应的starter 2.6.3版本 maven配置 <!-- ElasticSearch --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elas…