Unity查找游戏物体的六种方式详解

一篇小白也能看懂的查找游戏物体的方式解析 – 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()得出结论:

  1. 全局查找参数名称游戏物体;
  2. 不对禁用(隐藏)物体进行查找;
  3. 若有同名物体时根据层级关系进行查找。

使用建议: 有同名物体存在时,尽量不要使用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(),就达到了查找父层级或更高层级物体的目的
  • 弊端是依赖游戏物体的层级关系,使用时需确保层级关系相对稳定。若不稳定会导致每次修改游戏体时还要修改代码,这就加大了工作量了。

总结

到此这篇关于Unity查找游戏物体的六种方式的文章就介绍到这了,更多相关Unity查找游戏物体内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Unity3D开发教程:愤怒的小鸟

    一.前言 "愤怒的小鸟"在2009年12月发布,由于它的高度上瘾的游戏,它很快成为有史以来最成功的移动游戏. 在本教程中,我们将在"Unity"中实现"愤怒的小鸟"翻版.游戏中最复杂的部分是物理系统,但是多亏了Unity,我们就不用担心太多了. 像往常一样,一切都会尽可能简单地解释,这样每个人都能理解它. 以下是项目的预览: 二.源码 UI资源: https://wwr.lanzoui.com/iENnJop2n9i 密码:bnj2 源代码: h

  • 详解Unity安卓共享纹理

    概述 本文的目的是实现以下的流程: Android/iOS native app 操作摄像头 -> 获取视频流数据 -> 人脸检测或美颜 -> 传输给 Unity 渲染 -> Unity做出更多的效果(滤镜/粒子) 简单通信 在之前的博客里已经说到,Unity 和安卓通信最简单的方法是用 UnitySendMessage 等 API 实现. Android调用Unity: //向unity发消息 UnityPlayer.UnitySendMessage("Main Cam

  • Unity UI实现拖拽旋转

    本文实例为大家分享了Unity UI实现拖拽旋转的具体代码,供大家参考,具体内容如下 跟随鼠标旋转 第一种效果是跟随鼠标旋转,原理是计算下鼠标位置与拖拽物体的相对位移 旋转方向即可 注意转换对应空间坐标 新建脚本mono类继承 IBeginDragHandler, IDragHandler, IEndDragHandler 接口 [SerializeField] private Canvas m_Canvas; private Vector3? CalculateWorldToScreenPos

  • Unity实现切割图集工具

    本文实例为大家分享了Unity实现切割图集工具的具体代码,供大家参考,具体内容如下 操作步骤 先将脚本拖入Editor 1.选中要切割的图片,texture type 选为default,并勾选Advanced下的read/Write Enabled 2.texture type改为sprite(2D and UI),Sprite mode 选为Multiple,apply一下 3.Sprite Editor 先选其他的切一下,在选第一个切一下,切割成小图,apply 4.选中图集右键,imag

  • 详解Unity入门之GameObject

    GameObject和Component GameObject是游戏场景中真实存在的,而且有位置的一个物件 Component附属于GameObject,控制GameObject的各种属性 GameObject是由Component组合成的,Component的生命周期和GameObject息息相关.调用此GameObject的Destroy方法,它的子对象和对应的所有Component都会被销毁,但也可以一次只销毁一个Component 常见的Component: Component 作用 R

  • Unity查找游戏物体的六种方式详解

    一篇小白也能看懂的查找游戏物体的方式解析 – Unity 之 查找物体的几种方式.本文通过实际测试得出使用结论,大家进行简单记录,在使用时想不起来可以再来看看,多用几次基本就没有问题了. 一,Object.Find() Object.Find():根据名称找到游戏对象并返回它. void ObjectFind() { // 找父级 GameObject parent = GameObject.Find("GameObject"); Debug.Log("找父级物体,是否找到:

  • JS定义类的六种方式详解

    在前端开发中,经常需要定义JS类.那么在JavaScript中,定义类的方式有几种,分别是什么呢?本文就JS定义类的六中方式说明如下(案例说明): 1.工厂方式 function Car(){ var ocar = new Object; ocar.color = "blue"; ocar.doors = 4; ocar.showColor = function(){ document.write(this.color) }; return ocar; } var car1 = Car

  • 基于String变量的两种创建方式(详解)

    在java中,有两种创建String类型变量的方式: String str01="abc";//第一种方式 String str02=new String("abc")://第二种方式 第一种方式创建String变量时,首先查找JVM方法区的字符串常量池是否存在存放"abc"的地址,如果存在,则将该变量指向这个地址,不存在,则在方法区创建一个存放字面值"abc"的地址. 第二种方式创建String变量时,在堆中创建一个存放&q

  • Spring中bean的初始化和销毁几种实现方式详解

    Bean的生命周期 : 创建bean对象 – 属性赋值 – 初始化方法调用前的操作 – 初始化方法 – 初始化方法调用后的操作 – --- 销毁前操作 – 销毁方法的调用. [1]init-method和destroy-method 自定义初始化方法和销毁方法两种方式:xml配置和注解. ① xml配置 <bean id="person" class="com.core.Person" scope="singleton" init-meth

  • C语言 小游戏打砖块实现流程详解

    始祖是美国英宝格公司(en:Atari Games,ja:アタリ (ゲーム))于1976年推出的街机游戏"Breakout"(en:Breakout),由该公司在1972年发行的"PONG"(en:PONG,ja:ポン (ゲーム),世界上第一款电子游戏,类似台球)改良而来.相较于其前作,一个人就可以玩与变化丰富这两项特点让Breakout相当卖座,使各家公司竞相模仿. 因为规则简单与游戏性,现在许多移动电话都有内建打砖块游戏,也有许多因特网小游戏版本,目前在网上可以

  • C语言折半查找法的由来及使用详解

    目录 引入二分查找 分析二分查找 计算中间下标的两种方法 第一种 第二种 代码实现 总结 引入二分查找 本文带着大家学习一个简单的**二分查找算法,也叫折半查找算法** 先给大家提出一个问题 额,大家应该都会碰到这种情况,那大家怎么猜呢? 我想一定是会说1000,他说太少了,你又猜1500… 这其实就是二分查找的应用. 接下来我们来看一个问题 如何在一个有序数组中查找一个数字? 有一部分帅气的观众可能会说: 直接遍历数组,一个一个对比就找到了啊 但是大家有没有想过一个问题,数组中如果只有几十个数

  • buildAdmin开源项目引入四种图标方式详解

    目录 正文 引入Element-Plus图标库 引入Iconfont图标库 引入FontAwesome图标库 引入本地svg图标 正文 在项目开发中,我们经常使用可能都是UI组件库里的图标,当然由于业务需要,可能当前图标库没有我们需要的图标这时候就需要引入其它图标库的图标,比如iconfont.FontAweSome.本地图标库.在了解引入这些图标库之前,我们先学习一下各种图标库的引入使用: Element-Plus:由于elemen官方已经把图标封装成了组件,所以当我们引入图标的时候,需要全局

  • Spark三种属性配置方式详解

    随着Spark项目的逐渐成熟, 越来越多的可配置参数被添加到Spark中来.在Spark中提供了三个地方用于配置: 1.Spark properties:这个可以控制应用程序的绝大部分属性.并且可以通过 SparkConf对象或者Java 系统属性进行设置: 2.环境变量(Environment variables):这个可以分别对每台机器进行相应的设置,比如IP.这个可以在每台机器的$SPARK_HOME/ conf/spark-env.sh脚本中进行设置: 3.日志:所有的日志相关的属性可以

  • 关于react-router的几种配置方式详解

    本文介绍关于react-router的几种配置方式详解,分享给大家,具体如下: 路由的概念 路由的作用就是将url和函数进行映射,在单页面应用中路由是必不可少的部分,路由配置就是一组指令,用来告诉router如何匹配url,以及对应的函数映射,即执行对应的代码. react-router 每一门JS框架都会有自己定制的router框架,react-router就是react开发应用御用的路由框架,目前它的最新的官方版本为4.1.2.本文给大家介绍的是react-router相比于其他router

  • classloader类加载器_基于java类的加载方式详解

    基础概念 Classloader 类加载器,用来加载 Java 类到 Java 虚拟机中.与普通程序不同的是.Java程序(class文件)并不是本地的可执行程序.当运行Java程序时,首先运行JVM(Java虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做Class Loader. JVM本身包含了一个ClassLoader称为Bootstrap ClassLoader,和JVM一样,BootstrapClassLoader是用本地代码实现

随机推荐