Unity查找游戏物体的六种方式详解
作者:陈言必行 发布时间:2021-07-09 18:23:17
一篇小白也能看懂的查找游戏物体的方式解析 – Unity 之 查找物体的几种方式。本文通过实际测试得出使用结论,大家进行简单记录,在使用时想不起来可以再来看看,多用几次基本就没有问题了。
一,Object.Find()
Object.Find()
:根据名称找到游戏对象并返回它。
void ObjectFind()
{
// 找父级
GameObject parent = GameObject.Find("GameObject");
Debug.Log("找父级物体,是否找到:" + (parent != null));
// 找子级
GameObject child = GameObject.Find("Child");
Debug.Log("找子级物体,是否找到:" + (child != null));
// 找父级隐藏物体
GameObject parentHide = GameObject.Find("GameObjectHide");
Debug.Log("找父级隐藏物体,是否找到:" + (parentHide != null));
// 找子级隐藏物体
GameObject childHide = GameObject.Find("ChildHide");
Debug.Log("找子级隐藏物体,是否找到:" + (childHide != null));
}
测试结果如下图:
当有使用GameObject.Find("GameObject")
, 场景中有多个名为“GameObject”的物体存在时,将每个“GameObject”设置为不同的标签,多运行几次查看结果。
测试场景如下:
测试代码如下:
// 找同名物体
GameObject nameObj = GameObject.Find("GameObject");
Debug.Log("找同名,是否找到:" + nameObj.tag);
测试结果: 查找顺序是:“自身”(挂载脚本的物体) --> 和自身同层级上面物体 --> 和自身同层级下面物体 --> 自身子物体 --> 自身父物体。
Object.Find()得出结论:
全局查找参数名称游戏物体;
不对禁用(隐藏)物体进行查找;
若有同名物体时根据层级关系进行查找。
使用建议: 有同名物体存在时,尽量不要使用Object.Find()
进行查找,或者说使用Object.Find()
进行查找时,应控制查找物体命名唯一。
二,FindGameObjectWithTag()
GameObject.FindGameObjectWithTag()
根据标签查找游戏物体并返回。GameObject.FindGameObjectsWithTag()
根据标签查找当前场景中所有这个标签的游戏物体并返回所有物体的数组。
将如下场景:除主摄像机~(Main Camera)外的所有游戏物体的标签(Tag)~都修改为Player,进行测试。
测试代码如下:
void GameObjectFindWithTag()
{
GameObject tagObj = GameObject.FindGameObjectWithTag("MainCamera");
Debug.Log("根据标签查找游戏物体,是否查到:" + (tagObj != null));
GameObject[] tagObjs = GameObject.FindGameObjectsWithTag("Player");
for (int i = 0; i < tagObjs.Length; i++)
{
Debug.Log("根据标签查找游戏物体名称:" + tagObjs[i].name);
}
}
测试结果:
查找不存在的标签测试:
GameObject tagObj = GameObject.FindGameObjectWithTag("MainCamera1");
Debug.Log("根据标签查找游戏物体,是否查到:" + (tagObj != null));
报错:UnityException: Tag: MainCamera1 is not defined.
翻译: MainCamera1是一个未定义的标签
FindGameObjectWithTag()得出结论:
查找不到禁用物体,使用时需确认要查找的物体是启用(显示)状态;
有多个有游戏物体使用同一标签时,尽量不使用FindGameObjectWithTag此方式查找单一游戏体,因为查找顺序会受到层级影响;
查找未定义标签会报错,使用时需确认查找的字符串是已定义的标签;
查找的标签是已定义但是未使用过,会找不到游戏物体,返回空值。
三,GameObject.FindObjectOfType()
和上面根据标签查找的逻辑差不多。
GameObject.FindObjectOfType<类型>();
:根据类型(组件/自定义脚本)查找并返回这个类。
GameObject.FindObjectsOfType<类型>()
:根据类型(组件/自定义脚本)查找当前场景中所有这个类并返回一个这个类的数组。
void FindObjectOfType()
{
Camera typeCamera = GameObject.FindObjectOfType<Camera>();
Debug.Log("根据类型查找物体,是否查到:" + (typeCamera != null));
Transform[] typeTransArr = GameObject.FindObjectsOfType<Transform>();
for (int i = 0; i < typeTransArr.Length; i++)
{
Debug.Log("根据类型查找到的物体名称:" + typeTransArr[i].name);
}
}
FindObjectOfType()得出结论:
查找不到禁用物体,使用时需确认要查找的物体是启用(显示)状态;
查找场景中不存在类型时会返回null,不会报错;
通常使用情况为:初始化时在一个脚本中获取另一个脚本的引用,通过这种形式查找。【后多被单例取代】
四,Transform.Find()
查找挂载物体父级,同级,子级物体:
void TransformFind()
{
// 找父级
Transform parent = transform.Find("Root");
Debug.Log("找父级物体,是否找到:" + (parent != null));
// 找同级
Transform selfObj = transform.Find("Parent_1");
Debug.Log("找同级物体,是否找到:" + (selfObj != null));
// 找子级
Transform child = transform.Find("Child");
Debug.Log("找子级物体,是否找到:" + (child != null));
// 找子级隐藏物体
Transform childHide = transform.Find("ChildHide");
Debug.Log("找子级隐藏物体,是否找到:" + (childHide != null));
}
找多层级子物体:
// 找二级子物体
Transform child_1 = transform.Find("Child_1_1");
Debug.Log("找二级子物体 参数只写名称,是否找到:" + (child_1 != null));
// 找二级子物体
Transform child_1_1 = transform.Find("Child/Child_1_1");
Debug.Log("找二级子物体 参数写全路径,是否找到:" + (child_1_1 != null));
Find()得出结论:
只能找其子物体,不能找其同级或更高层级物体
找子物体时不考虑是否被禁用(隐藏)
找多层子物体时需写全路径(否则即使存在也找不到)
五,Transform.FindObjectOfType()
经过测试和GameObject.FindObjectOfType()
没什么区别,测试结果一致,测试代码和截图就不发处理占地方了。
测试时我发现 GameObject.FindObjectsOfType<类型>()
和Transform.FindObjectsOfType<Transform>()
被合并了,应该说完全是一个方法了,根据下图可以看到,我虽然前打的是Transform
的标签,但是它是灰色的,鼠标放上去看到方法引用的却是GameObject.FindObjectsOfType
。
得出结论:
Transform.FindObjectOfType() 和 GameObject.FindObjectOfType()使用方式一样,结果也没有区别…
六,transform.GetChild()
Transform.GetChild()
是找子物体的方法,也是我个人比较喜欢用的方式,弊端是不能随意修改游戏物体的层级关系。
使用起来也很简单
比如:找一级子物体的第一个物体
Transform child1 = transform.GetChild(0);
找一级子物体的第一个物体的第三个子物体
Transform child1 = transform.GetChild(0).GetChild(2);
使用方式:几个层级就几个GetChild()
,参数就是当前层级的第几个物体(从0开始)
使用拓展:
遍历子物体:
for (int i = 0; i < transform.childCount; i++)
{
Debug.Log(transform.transform);
}
获取当前物体的父物体transform.parent
获取当前物体的根物体transform.root
transform.GetChild()使用总结:
以自身为基础,查找子物体(注意索引从0开始,写多报错)
可以使用transform.parent.parent 的形式无限向上,然后再GetChild(),就达到了查找父层级或更高层级物体的目的
弊端是依赖游戏物体的层级关系,使用时需确保层级关系相对稳定。若不稳定会导致每次修改游戏体时还要修改代码,这就加大了工作量了。
总结
来源:https://blog.csdn.net/Czhenya/article/details/117530824


猜你喜欢
- 本文实例讲述了C#使用HtmlAgilityPack抓取糗事百科内容的方法。分享给大家供大家参考。具体实现方法如下:Console.Writ
- 这篇文章主要介绍了Java数据封装树形结构代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可
- 这篇文章主要介绍了通过实例解析JMM和Volatile底层原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
- 一,哈希表(Hashtable)简述在.NET Framework中,Hashtable是System.Collections命名空间提供的
- 由于Android对单个应用所施加的内存限制,比如16MB,这导致加载Bitmap的时候很容易出现内存溢出,本文主要包含2个方面的内容分析B
- java 弹幕小游戏的最初版本,供大家参考,具体内容如下最近在学习javaSE,根据b站视频老师的讲解,也参考了他的代码,做了一个弹幕小游戏
- 先看看效果Like This↓一、公共WiFi 公用电脑什么的在我们日常在线上工作、玩耍时,不论开电脑、登录淘宝、玩网游统统都会用到键盘输入
- 前言身在孤岛有很多无奈,比如说程序员属于比较偏门的职业。尤其是早些年,在行业里跳过几次槽后,可能你就已经认识整个圈子的人了。然后,再跳槽很可
- 下面通过代码给大家介绍c++ string insert() 函数,具体内容如下:basic_string& inser
- 本文实例讲述了Android编程实现的手写板和涂鸦功能。分享给大家供大家参考,具体如下:下面仿一个Android手写板和涂鸦的功能,直接上代
- 问题onClick事件是Android开发中最常见的事件。比如,一个submitButton,功能是点击之后会提交一个订单,则一般代码如下,
- 利用AsyncQueryHandler能异步任务获取手机联系人,增加用户体验,使用起来也很方便。不多说,上干货。布局文件main.xml&l
- jstat命令简介jstat(Java Virtual Machine Statistics Monitoring Tool)是JDK提供的
- 前言人类建造迷宫已有5000年的历史。在世界的不同文化发展时期,这些奇特的建筑物始终吸引人们沿着弯弯曲曲、困难重重的小路吃力地行走,寻找真相
- 前言MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手
- 本文实例为大家分享了android实现录屏功能的具体代码,供大家参考,具体内容如下1、mian.activitypackage com.fp
- protobuf对象不能直接使用jsonlib去转,因为protobuf生成的对象的get方法返回的类型有byte[],而只有String类
- Spring AOP对嵌套方法不起作用今天在调研系统操作记录日志时,好多教程都是借助于Spring AOP机制来实现。于是也采用这种方法来实
- 前言最近做项目框架,需要在框架结束的时候,关闭服务器连接,清除部分框架运行lock文件,这里就想到了shutdownhook,顺便学了学Ru
- 前言你一定会好奇:“老周,你去哪开飞机了?这么久没写博客了。”老周:“我买不起飞机,开了个铁矿,挖了一年半的石头。谁知铁矿垮了,压死了几条蜈