找回密码
 立即注册
查看: 325|回复: 2

Unity开发入门指南(6): 组件与游戏对象

[复制链接]
发表于 2023-4-6 17:51 | 显示全部楼层 |阅读模式
在开始之前,我们先来了解两个概念:GameObject 和 Transform。
第一个概念:GameObejct
    GameObject是一个Unity的内建类,同样我们可以通过vs的F12来剖析下它的内部结构。我们可以发现这个GameObject也是从Object派生而来,在它的属性方法中,我们看到它定义了很多的公有的Component实例,
也就是说我们也可以通过GameObject的实例来获取这些公有的组件实例。其它的像布尔类型的active(设置隐藏显示),静态方法Find()等等也是后续编程中经常会用到的。
    那么这个GameObject要怎么理解?Object指明了所有的类都是来源于它,而GameObject则指明了Unity中的所有游戏对象都是他的实例。那游戏对象是什么?其实很简单,我们直接看Hierarchy窗口就可以,在这个窗口里出现的对象都是游戏对象,不管是摄像机,灯光,图片,模型,还是UI,甚至是一个空的物体,这些都是GameObject的实例,也就是说,在Unity里我们可以用GameObject来声明任意物体。


第二个概念:Transform
    Transform同样也是Unity的内建类,通过F12,我们知道他继承自Component,在Unity里,组件是最重要的核心理念之一,每个组件定义了属于自己的能力,通过组件的插拔组合,游戏对象就拥有了新的能力。这跟变形金刚很像,需要飞行的能力,就接入一个飞行器,需要火炮的能力,就接入一个火炮筒,不需要某个能力时,就销毁那个组件,很灵活。我们说回Transform,字面意思是变换,它包含了三个基本的对象信息:Position(位置),Rotation(旋转),Scale(缩放)。我们创建的任何一个GameObject都会标配Transform组件(每个GameObject实例有且只有一个Transform组件,唯一性),并且无法移除,因为这是对象单元存在所必须的最基本信息。我们描述一个具象化的物体时,我们会说明物体的具体形态,这就会包含Transform里的基本信息(至少一项)。



    这两个概念并不难理解,一个GameObject对应一个实例对象,比如场景里的摄像机,而摄像机在什么位置,只是它最基本的属性之一,我们可以通过获取摄像机的Transform组件来得知甚至是改变它的位置信息。那么问题来了,如何获取组件?
获取gameobject自身的组件:
    我们可以通过使用GetComponent<T>()这个unity内建方法来获取对应的组件。这个方法可以通过GameObject及Transform的实例来调用。我们可以试着来获取摄像机组件,并读取摄像机的Field of view,我们在Start方法中添加代码:
Debug.Log(GetComponent<Camera>().fieldOfView);运行,正确的打印出了60,这是摄像机默认的FOV(field of view 简称)值。因为我们这里是获取当前游戏对象自身的组件(脚本挂载的对象)所以可以不指明是由谁获取组件,默认是由当前的实例去获取。方便理解也可以写成:  Debug.Log(this.GetComponent<Camera>().fieldOfView);
接着我们通过代码动态修改下FOV的值,在Start方法中修改如下代码:
  Debug.Log(this.GetComponent<Camera>().fieldOfView += 20);
运行后,打印出了80,这是运算后的新值。
获取gameobject自身之外的组件
    除了以上的方法,当然我们也有更便捷的获取方式,就是将需要获取的对象以公共变量的形式在Inspector面板上直接赋值,我们修改代码:

using UnityEngine;
public class MyTest : MonoBehaviour {
public Camera mCamera;

void Start()
    {
Debug.Log(this.GetComponent<Camera>().fieldOfView += 20);
    }

}然后在inpector面板中将camera直接拖放到mCamera的标签栏里进行赋值,或者从标签的边缘的圆形按钮点开选择窗口选择对应的camera对象。这样也可以直接获得相机的对象实例,进而对相机进行操作控制。



通过gameobject的查找方法来获取组件
    单个gameobject身上可能有多个组件,如果我们的脚本也在同一个gameobject上,那么要使用当前脚本获取当前gameobject上的其他组件,直接使用this.Getcomponent<T>()方法即可。如果要获取的组件不在当前的gameobject,我们可以采用公共变量的形式,在inspector面板直接将我们需要的对象组件拖过来赋值即可。
    当然如果不希望通过这种拖拉的形式赋值,我们还可以使用查找的方式来动态赋值。主要分为两类,一类是gameobject的静态方法find和findwithtag。另一类则是transform的实例方法:childcount,find方法。
    gameobject的静态方法通过名称或者tag来查找对象。通过名称的方式:
using UnityEngine;


public class MyTest : MonoBehaviour {

private Camera mCamera;


void Start()
    {
mCamera = GameObject.Find("Main Camera").GetComponent<Camera>();
mCamera.fieldOfView += 20;
    }


} 当然,以上只是方便大家来了解名称查找的方法,而实际中,场景的MainCamera有更便捷的获取方法:使用Camera.main即可直接拿到主相机的对象。
通过Tag的方式,我们在hierarchy面板创建一个cube,选中这个cube在inspector面板中更改tag为player,当然我们也可以自定义自己的tag,直接点击add tag进行添加即可。



使用tag查找单个物体时:
private GameObject cube;


void Start()
    {
cube = GameObject.FindWithTag("Player");
    }如果我们需要找到场景里所有的tag为enemy时,则可使用fingameobjectswithtag静态方法,它将返回一个存储tag为enemy的GameObejct数组,我们先给场景中所有的敌人添加enemy的tag,然后编写代码:
private GameObject[] enemies;

void Start()
    {
enemies = GameObject.FindGameObjectsWithTag("Enemy");
    }使用Transform的实例方法来查找子对象:
有时我们需要获取一系列相当的游戏对象,比如敌人,障碍物,或者寻路点,这时如果我们通过定义一个公共数组然后手动一个个的拖放进行赋值,这确实很让人厌烦的操作的。这时我们可以考虑使用遍历子物体的方法将它们缓存起来。
    以waypoint为例,我们在hierarchy中先创建一个empty object,重命名为waypoint,然后创建几个空的子对象。



创建一个WayPoint脚本,并挂载到Waypoint对象上,然后双击打开waypoint脚本进行编辑:
using UnityEngine;


public class WayPoint : MonoBehaviour {
//定义一个Transform类型的数组
public Transform[] waypoints;


private void Start()
    {
//设置数组的大小为当前物体的子物体个数
waypoints = new Transform[transform.childCount];
int i = 0;
//遍历子物体,并将值依次赋给waypoint数组的每个项
foreach (Transform t in transform)
        {
waypoints[i++] = t;
        }
    }


}定义个transform的数组,通过最上一级的waypoint(脚本所挂载的层级)往下遍历子物体,并将遍历的子物体赋值给数组的每个元素。运行结果如下:



当然,你也可以直接使用transform.Find(“1”);来查找到指定的子对象。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2023-4-6 18:01 | 显示全部楼层
对我来说有用,感谢分享。
发表于 2023-4-6 18:02 | 显示全部楼层
讲的非常通俗易懂和受用,给我这个小白带来很大帮助。感谢作者辛苦码字
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-4-29 17:13 , Processed in 0.119479 second(s), 28 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表