【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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Notepad++不显示CRLF的方法

View -> Show Symbol -> 去掉勾选 Show All Characters

详解makefile中的foreach

在 Makefile 中&#xff0c;foreach 函数用于迭代处理一个以空格分隔的列表&#xff0c;并针对列表中的每个元素执行相同的操作。这个函数通常用于循环处理一组变量或文件名&#xff0c;并执行相同的规则或命令。 语法&#xff1a; makefile Copy Code $(foreach var, list, …

定位器与PWM的LED控制

文章目录 一、STM32定时器二、脉宽调制pwm三、定时器控制led&#xff08;1&#xff09;实验内容&#xff08;2&#xff09;创建工程&#xff08;3&#xff09;Keli程序&#xff08;4&#xff09;观察波形图&#xff08;5&#xff09;实物连接图&#xff08;6&#xff09;实践效…

nginx源码阅读理解 [持续更新,建议关注]

文章目录 前述一、nginx 进程模型基本流程二、源码里的小点1.对字符串操作都进行了原生实现2.配置文件解析也是原生实现待续 前述 通过对 nginx 的了解和代码简单阅读&#xff0c;发现这个C代码的中间件确实存在过人之处&#xff0c;使用场景特别多&#xff0c;插件模块很丰富…

【易错题】数据可视化基础练习题(30道选择题)#CDA Level 1

本文整理了数据可视化基础知识相关的练习题&#xff0c;共30道&#xff0c;适用于想巩固数据可视化知识的同学&#xff0c;也可作为备考CDA一级的补充习题。来源&#xff1a;如荷学数据科学题库&#xff08;技术专项-可视化&#xff09;。 1&#xff09; 2&#xff09; 3&…

EtherCAT协议概述

EtherCAT 是由德国 BECKOFF 自动化公司于2003年提出的实时工业以太网技术。它具有高速和高数据有效率的特点&#xff0c;支持多种设备连接拓扑结构。其从站节点使用专用的控制芯片&#xff0c;主站使用标准的以太网控制器。 EtherCAT 的主要特点如下 : ①泛的适用性&#xff0c…

SQL刷题笔记day4补

1题目 我的正确代码 select e.last_name,e.first_name,d.dept_name from employees e left join (select departments.dept_name,dept_emp.emp_no,dept_emp.dept_no from departments join dept_emp on departments.dept_nodept_emp.dept_no) d on e.emp_nod.emp_no复盘&…

【全开源】Java养老护理助浴陪诊小程序医院陪护陪诊小程序APP源码

打造智慧养老服务新篇章 一、引言&#xff1a;养老护理的数字化转型 随着老龄化社会的到来&#xff0c;养老护理需求日益凸显。为了更好地满足老年人及其家庭的需求&#xff0c;我们推出了养老护理助浴陪诊小程序系统源码。该系统源码旨在通过数字化技术&#xff0c;优化养老…

ORA-12514:TNS:监听程序当前无法识别连接描述符中请求的服务

ORA-12514&#xff1a;TNS&#xff1a;监听程序当前无法识别连接描述符中请求的服务 问题描述&#xff1a; 解决方案&#xff1a; 1、检查oracle的监听服务是否运行正常 1)点击键盘的winr&#xff0c;输入services.msc&#xff0c;点击确认/回车键&#xff1b; 2&#xff09;查…

GO语言 gin框架 简述

原文地址 基本路由 Go语言中文文档 一、简介 Gin是一个golang的轻量级web框架&#xff0c;性能不错&#xff0c;API友好。 Gin支持Restful风格的API&#xff0c;可以直接从URL路径上接收api参数或者URL参数&#xff0c;也可是使用json或者表单 数据绑定的方式接收参数。 Gin响…

Vue.js中如何实现以列表首列为表头

前言 一般情况table列表的展示&#xff0c;列头都在第一横行&#xff0c;此方法用于列头在第一列的情况。 效果图 核心代码 <template><div><table class"data-table"><tr v-for"(column, columnIndex) in columns" :key"col…

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

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

华为云Astro Zero低代码平台案例:小、轻、快、准助力销售作战数字化经营

客户背景&#xff1a; 随着业务的不断扩展&#xff0c;华为云某一线作战团队发现&#xff0c;原本基于线上Excel的项目跟踪方式面临新的挑战&#xff1a;多区域、多场景下的业务管理越来越复杂&#xff0c;项目管道存在多种不可控因素&#xff0c;客户关系、进展跟踪同步不及时…

三步走,Halo DB 安装指引

前文介绍了国产数据库新星 Halo 数据库是什么&#xff0c; 哈喽&#xff0c;国产数据库&#xff01;Halo DB! ★ HaloDB是基于原生PG打造的新一代高性能安全自主可控全场景通用型统一数据库。 业内首次创造性的提出插件式内核架构设计&#xff0c;通过配置的方式&#xff0c;适…

部署八戒-Chat-1.8B 模型

1 简单介绍 八戒-Chat-1.8B 八戒-Chat-1.8B是运用 InternLM2-Chat-1.8B 模型进行微调训练的优秀成果。其中&#xff0c;八戒-Chat-1.8B 是利用《西游记》剧本中所有关于猪八戒的台词和语句以及 LLM API 生成的相关数据结果&#xff0c;进行全量微调得到的猪八戒聊天模型。作为 …

LeetCode---链表

203. 移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 代码示例1&#xff1a;(直接使用原来的链表来进行移除节点操作) //时间复杂度: O(n) //空间复杂度: O(1) class Solu…

FANUC机器人点位IO监控指令TC_ONLINE

一、系统变量中打开该指令 在示教器系统变量页面中找到其中的MIX_LOGIC变量&#xff0c;点击enter进入变量设置页面 找到其中的USE_TCOL变量将其中的值改为true 即可在IO显示页面中找到TC_ONLINE的监控选项 在显示页面中也可找到其中的监控条件 二、在点位指令中添加点逻辑指令…

内网安全--隧道技术-MSF上线本地

免责声明:本文仅做技术交流与学习... 不得不说,小白最近也是用上了viper,这里要特别感谢一下my bro 北岭敲键盘的荒漠猫 MSF--viper: --生成马子-->上线 --进入meterpreter. 1-查看路由,添加路由. 查看路由信息 : run autoroute -p run post/multi/manage/autoroute 添加…

电脑卡顿---WINDOWS任何关闭应用开机自启动

打开windows11的控制面板&#xff0c;点击应用&#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…