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

【知识链】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.mzph.cn/pingmian/18544.shtml

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

相关文章

python os模块库

os模块 os模块是python的内置模块&#xff0c;是对目录和文件的操作 使用时需要导包 import os os用法 方法描述os.getcwd()展示当前路径os.listdir()展示当前目录下载文件os.chdir()改变当前目录路径os.mkdir()创建目录os.rmdir()删除指定路径的目录&#xff0c;必须得目录…

【个人博客搭建】(20)获取操作用户信息(IHttpContextAccessor)

IHttpContextAccessor在ASP.NET Core中扮演着至关重要的角色。它为开发者提供了一种方便的方式来访问和操作HttpContext对象&#xff0c;从而允许在整个应用程序中轻松地管理和使用HTTP请求和响应的相关信息。下面将深入探讨IHttpContextAccessor的作用、使用方法以及如何通过它…

【区分vue2和vue3下的element UI lauout布局,分别详细介绍属性,事件,方法如何使用,并举例】

首先&#xff0c;需要澄清一点&#xff1a;Element UI 是基于 Vue 2 的组件库&#xff0c;它并没有直接为 Vue 3 提供官方支持。但是&#xff0c;有一些社区版本的 Element UI 试图兼容 Vue 3&#xff0c;比如 Element Plus。以下我会分别介绍 Element UI&#xff08;基于 Vue …

[ue5]建模场景学习笔记(1)——混合材质

卷首&#xff1a;这部分会记录建模场景等相关学习内容&#xff0c;与ue引擎学习笔记不同的是&#xff0c;可能会略过一些基础内容&#xff0c;因为部分知识在blender中已经学习过了&#xff0c;不再继续记录。 1.需求分析&#xff1a; 想构建一个山地的场景&#xff0c;在ue5中…

[RK3588-Android12] 关于EDP屏外设为Panel,不支持HPD的配置

问题描述 直接附上dts配置&#xff0c;也可自行查看先关文档RKDocs\common\display\Rockchip_RK3588_User_Guide_eDP_CN.pdf 解决方案&#xff1a; // EDP屏参数panel-edp {compatible "simple-panel";// 屏en脚 自行根据原理图配置enable-gpios <&gpioX R…

【扫雷game】

编写一个扫雷游戏程序需要考虑几个关键部分&#xff1a;游戏逻辑、用户界面和交互。这里我将提供一个基本的扫雷游戏逻辑的伪代码和概念&#xff0c;你可以使用Python等编程语言来实现它。 游戏逻辑 初始化游戏板 创建一个二维数组来表示游戏板&#xff0c;每个单元格可能包含…

解读vue3源码-1

提示&#xff1a;看到我 请让滚去学习 vue3渲染流程 文章目录 vue3渲染流程vue3的3个核心&#xff1a;1.响应式模块(Reactivity Module)--创建响应式数据2.编译模块(Compiler Module)--模版编译器将html转换为一个渲染函数3.渲染模块(Renderer Module) 渲染流程&#xff1a;1.首…

python办公自动化——(二)替换PPT文档中图形数据-柱图

效果: 数据替换前 &#xff1a; 替换数据后&#xff1a; 实现代码 import collections.abc from pptx import Presentation from pptx.util import Cm,Pt import pyodbc import pandas as pd from pptx.chart.data impo…

Python项目开发实战:酒店管理系统(案例教程)

一、引言 在当今信息化社会,酒店管理系统作为酒店运营的重要组成部分,其重要性不言而喻。一个高效、稳定的酒店管理系统不仅能提升酒店的运营效率,还能为顾客提供更为便捷、舒适的服务体验。本文将详细介绍如何使用Python语言开发一个基本的酒店管理系统,并从需求分析、系统…

【量算分析工具-贴地距离】GeoServer改造Springboot番外系列九

【量算分析工具-概述】GeoServer改造Springboot番外系列三-CSDN博客 【量算分析工具-水平距离】GeoServer改造Springboot番外系列四-CSDN博客 【量算分析工具-水平面积】GeoServer改造Springboot番外系列五-CSDN博客 【量算分析工具-方位角】GeoServer改造Springboot番外系列…

postman都有哪些功能?

接口测试 可以方便地发送 HTTP 请求&#xff0c;包括各种方法&#xff08;GET、POST、PUT、DELETE 等&#xff09;&#xff0c;并查看响应结果。 参数设置 能够灵活设置请求的参数&#xff0c;如查询参数、请求头、请求体等。 环境管理 支持创建不同的环境&#xff0c;方便…

Web前端三大主流框架技术分享

在当今快速发展的互联网时代&#xff0c;Web前端技术作为连接用户与服务的桥梁&#xff0c;其重要性不言而喻。随着技术的不断进步&#xff0c;为了提升开发效率、优化用户体验&#xff0c;一系列强大的前端框架应运而生。其中&#xff0c;Angular、React和Vue.js作为当前最为主…

广东海上丝绸之路文化促进会正式批复荐世界酒中国菜的指导单位

广东海上丝绸之路文化促进会正式批复成为“世界酒中国菜”系列活动指导单位 近日&#xff0c;广东海上丝绸之路文化促进会近日正式批复荐酒师国际认证&#xff08;广州&#xff09;有限公司&#xff0c;成为备受瞩目的“世界酒中国菜”系列活动的指导单位。此举旨在通过双方的…

IDEA中各种Maven相关问题(文件飘红、下载依赖和启动报错)

错误情况 包名、类名显示红色、红色波浪线&#xff0c;大量依赖提示不存在&#xff08;程序包xxx不存在&#xff09; 工程无法启动 一、前提条件 1、使用英文原版IDEA 汉化版的可能有各种奇怪的问题。建议用IDEA英文版&#xff0c;卸载重装。 2、下载maven&#xff0c;配置环…

2024HW|常见红队使用工具

目录 什么是HW&#xff1f; 什么是网络安全红蓝对抗&#xff1f; 红队 常见工具 信息收集工具 Nmap 简介 漏洞扫描工具 Nessus简介 AWVS 简介 抓包工具 Wireshark简介 TangGo 简介 web 应用安全工具 Burpsuite 简介 SQLMap webshell 管理工具 蚁剑 冰蝎 后…

uniapp input点击旁边按钮,如何不失去焦点

有遇到在评论的时候&#xff0c;唤起键盘。旁边的其他按钮&#xff08;匿名、发送等&#xff09;&#xff0c;input会失去焦点。软键盘会隐藏 处理方法: 1、重新获取键盘焦点 &#xff08;通过重置focus状态来处理&#xff09; #页面 用focus变量来动态设置 <input v-mod…

《PNAS》和《Nature Communications》仿章鱼和蜗牛的粘液真空吸附,赋予了机器人吸盘新的“超能力”

想象一下&#xff0c;如果机器人能够像章鱼一样牢牢吸附在粗糙崎岖的岩石上&#xff0c;或者像蜗牛那样在墙面上悠然负重爬行&#xff0c;那会是多么神奇的一幕&#xff01;近日&#xff0c;布里斯托大学机器人实验室的Jonathan Rossiter教授课题组就为我们带来了这样的“超能力…

嵌入式功耗

adb ADB&#xff08;Android Debug Bridge&#xff0c;安卓调试桥&#xff09;是一个多功能的命令行工具&#xff0c;允许用户与运行 Android 的设备进行通信。它是 Android SDK 的一部分&#xff0c;广泛用于开发和调试 Android 应用程序。以下是 ADB 的一些主要功能和使用场景…

Java中的堆(Heap)和栈(Stack):深入解析与对比

在Java的内存管理中&#xff0c;堆&#xff08;Heap&#xff09;和栈&#xff08;Stack&#xff09;是两个至关重要的概念。它们各自扮演着不同的角色&#xff0c;对于理解和编写高效的Java程序至关重要。以下&#xff0c;我们将从技术难点、面试官关注点、回答吸引力和代码举例…

gulp入门1-安装

Gulp 是一个流行的自动化构建工具&#xff0c;主要用于前端开发中的任务自动化&#xff0c;如文件压缩、代码合并、代码校验等。以下是一个 Gulp 的入门教程&#xff0c;帮助你快速上手&#xff1a; 1. 安装 Node.js 和 npm 首先&#xff0c;你需要在你的计算机上安装 Node.j…