欢迎来到我的博客小站。  交流请加我微信好友: studyjava。  也欢迎关注同名公众号:Java学习之道

学Unity的猫之探索GameObject游戏对象(六)

  |   0 评论   |   0 浏览

​6.1 组件的容器——GameObject

皮皮:“铲屎官,我有一个问题没想明白,为什么之前我们每次都是把脚本挂到Main Camera上,是只有Main Camera才能运行脚本吗?”

我:“当然不是呀,只是因为空工程中,场景里就只有一个Main Camera和一个Directional Light,为了测试脚本,就随便挂到Main Camera上了。事实上,我们也可以把脚本挂到Directional Light上测试之前的脚本,当然,我们还可以自己创建GameObject。”皮皮:“什么是GameObject呀。”

我:“GameObject就是游戏对象的意思,在Unity中,所有实体都是游戏对象,比如摄像机Main Camera、直射光Directional Light,它们其实都是GameObject,你可以把GameObject理解为一个容器,不同能力的组件装在这个容器里,容器便具有了相应的能力,比如挂了Camera组件的GameObject,它便具备了摄像机的能力,挂了Light组件的GameObject,它便具备了灯光的能力。”

皮皮:“原来如喵,我懂了。那怎么创建GameObject呢?”

我:“来,看我变魔术。”

6.2 创建物体

6.2.1 创建空物体——Create Empty

Hierarchy视图中右键点击菜单Create Empty,即可创建一个空物体。默认空物体的名字为GameObject我们可以对它进行重命名,选中物体后,在Inspector最上方的输入栏中即可重新输入物体的名字,输入后按回车即可生效,比如我这里将物体重命名为EmptyGameObject

皮皮:“为什么这个EmptyGameObjectGame视图中看不见?”

我:“问得好,但我先不回答你这个问题,我们先来创建一个看得见的GameObject。”

皮皮:“记得微信搜索公众号 [爱上游戏开发],回复 “资料”,免费领取 200G 学习资料!”

6.2.2 创建几何体物体

Hierarchy视图中右键点击菜单3D Object - Cube此时场景中出现了一个正方体Cube这回,我们看见了,一个看得见的GameObject我:“老皮,你自己观察观察,这个Cube和我们刚刚创建的空物体EmptyGameObject有什么不同?”

皮皮:“我发现了,Cube身上比EmptyGameObject多了好几个组件。一定是这些组件让Cube具有被看得见的能力。”我:“如喵可教也,一点即通。那你再观察观察,是什么让它的外形是正方体,而不是一个球体或者别的呢?” 皮皮用鼠标点来点去,点开了Mesh的选择框。皮皮:“原来秘密藏在这里呀。”

我:“不错不错,Mesh就是网格的意思,你可以理解为骨架,我们可以选择别的Mesh,比如球体Sphere,这样它的外形就变成一个球啦。”

6.2.3 用代码动态创建物体

我:“刚刚我们都是手动创建物体的,有时候我们需要用代码动态创建物体。”

皮皮:“看到代码就犯困。”

我:“不要忘记你们喵星人的使命。其实很简单,一行代码就可以实现。”

创建一个脚本CreateGameObjectTest代码如下:

using UnityEngine;




public class CreateGameObjectTest : MonoBehaviour
{
    void Start()
    {
        
        var go = new GameObject("EmptyGo");
    }
}

CreateGameObjectTest脚本挂到Main Camera上,运行Unity,可以看到动态创建出了一个EmptyGo物体了。皮皮:“你上面是用代码动态创建一个空物体,那如果我想动态创建几何体呢?”

我:“Unity已经帮我们封装好接口了,使用GameObject.CreatePrimitive接口。” 例:

var go = GameObject.CreatePrimitive(PrimitiveType.Cube);

其中PrimitiveType是枚举类型,传对应的枚举值即可创建不同的几何体。

public enum PrimitiveType
{
 
    Sphere = 0,
    
    Capsule = 1,
    
    Cylinder = 2,
    
    Cube = 3,
    
    Plane = 4,
    
    Quad = 5
}

皮皮:“看出来了,它只能创建一些简单的几何体形状,如果我想创建一个很复杂的几何体呢?”

我:“那就要建模软件在外部制作好然后再导入Unity中,包装成预设,然后通过预设实例化的方式来啦。”

皮皮:“太酷了,我要学建模。”

我:“你就是小学课本里那只钓鱼的猫,看见蝴蝶就去抓,结果鱼没钓到,蝴蝶也没抓到。你要耐下性子,后面有时间我再教你建模。”

皮皮:“铲屎官怎么啥都会!”

我:“艺多不压身,功到自然成。”

皮皮:“记得微信搜索公众号 [爱上游戏开发],回复 “资料”,免费领取 200G 学习资料!”

6.3 GameObject常用方法

GameObject是我们在Unity中最常打交道的一个类,所以我们需要熟悉它的接口和属性。

6.3.1 添加组件,AddComponent

GameObject可以理解为是组件的容器,通过AddComponent接口,可以动态给GameObject添加组件。

public Component AddComponent(Type componentType);
public T AddComponent<T>() where T : Component;

例:

BoxCollider boxCollider = gameObject.AddComponent<BoxCollider>();

皮皮:“这个小写g开头的gameObject又是哪里来的呀?”

我:“在MonoBehaviour(包括子类)脚本中,小写g开头的gameObject表示组件所挂的物体本身。”

6.3.2 获取组件,GetComponent

相应的,我们可以通过GetComponent来获取GameObject上的组件。

public Component GetComponent(string type);
public T GetComponent<T>();
public Component GetComponent(Type type);

参数为string类型的GetComponent接口尽量少用,因为它用到了反射,第一是反射执行效率低,第二是字符串容易写错。例:

BoxCollider boxCollider = gameObject.GetComponent<BoxCollider>();

这个接口是从自身节点获取某个组件,找到一个则立即返回。除此之外,还有如下一些接口:

| 接口 | 说明 |
| - | - |
| GetComponentInChildren | 从子节点获取某个组件,找到一个则立即返回 |
| GetComponentsInChildren | 从子节点获取某个组件,返回一个组件数组 |
| GetComponentInParent | 从父节点获取某个组件,找到一个则立即返回 |
| GetComponentsInParent | 从父节点获取某个组件,返回一个组件数组 |
| GetComponents | 从自身节点获取某个组件,返回一个组件数组 |

例:

BoxCollider[] boxColliderArray = gameObject.GetComponentsInChildren<BoxCollider>(true);

6.3.3 通过标签查找物体,FindWithTag

物体是可以打标签的,选中物体,在Inspector窗口中的Tag属性下拉框中即可设置。要新增Tag可以点击Add Tag...Tags框中点击+号,即可添加Tag,如下,添加了一个MyTag将物体的Tag设置为MyTagFindWithTag接口,通过标签在场景中查找物体,找到一个则立刻返回。

public static GameObject FindWithTag(string tag);

例:

GameObject target = GameObject.FindWithTag("MyTag");

如果有多个物体具有相同的Tag,我们想查找所有物体,则要用另一个接口:

public static GameObject[] FindGameObjectsWithTag(string tag);

皮皮:“我怎么通过代码获取物体的Tag呢?” 我:“GameObject提供了tag属性。”

string tag = gameObject.tag;

皮皮:“那我们可以通过tag属性设置物体的Tag吗?”

我:“可以的。不过前提是设置的Tag需要存在,不能设置一个不存在的Tag,否则会报错的。”

gameObject.tag = "MyTag";

我:“还有,虽然GameObject提供了这个tag属性,但也不要泛滥使用,只有少数必要的情况才会使用Tag,具体后面实战项目我再演示吧。”

皮皮:“记得微信搜索公众号 [爱上游戏开发],回复 “资料”,免费领取 200G 学习资料!”

6.3.4 通过名字查找物体,Find

通过名字在场景中查找物体,找到一个则立刻返回,所以如果有多个物体具有相同的名字,这个时候就不大好区分了。

public static GameObject Find(string name);

该方法建议少用,因为场景中同名的物体概率还是比较大的。另外,我们可以通过name属性获取当前物体的名字,如下:

string name = gameObject.name;

皮皮:“也可以通过name属性修改物体的名字,对吗?” 我:“聪明。”

gameObject.name = "NewName";

6.4.5 实例化游戏对象,Instantiate

这个接口应该不陌生了,实例化可以理解为一次深拷贝,或者叫克隆。

public static Object Instantiate(Object original);

这个接口是Object类的,因为GameObject是继承Object,所以就有这个接口了。

6.4.6 销毁游戏对象,Destroy

在拍戏的时候,演员的角色剧情演完之后就杀青了,游戏对象也类似,它完成了它的任务后,就要被销毁或者对象池回收。这个接口是Object类的,因为GameObject是继承Object,所以就有这个接口了。

public static void Destroy(Object obj);

皮皮:“什么是对象池,怎么回收游戏对象?”

我:“好奇猫,后面再教你,你先学好今天的内容。”


标题:学Unity的猫之探索GameObject游戏对象(六)
作者:shirlnGame
地址:https://mmzsblog.cn/articles/2021/01/06/1609938030024.html
-----------------------------
如未加特殊说明,此网站文章均为原创。
网站转载须在文章起始位置标注作者及原文连接,否则保留追究法律责任的权利。
公众号转载请联系网站首页的微信号申请白名单!

个人微信公众号 ↓↓↓                 

微信搜一搜爱上游戏开发