游戏蛮牛学习群(纯技术交流,不闲聊):539178957
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

教程分享

关注:780

当前位置:游戏蛮牛 技术专区 教程分享

查看: 140|回复: 0

[自学总结] Unity中GameObject API解析

[复制链接]  [移动端链接]

31

主题

33

帖子

92

积分

Rank: 2Rank: 2

UID
24181
好友
0
蛮牛币
299
威望
0
注册时间
2014-5-7
在线时间
38 小时
最后登录
2018-8-7
发表于 2018-8-7 10:40:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

x
本文节选自洪流学堂公众号专栏《郑洪智的Unity2018课》,未经允许不可转载。
洪流学堂公众号回复专栏,查看更多专栏文章。

洪流学堂,让你快人几步。你好,我是郑洪智。
GameObject我们已经很了解了,它本身没有功能,它是组件的容器,很多时候我们需要在脚本中操作GameObject。今天我们就来看看如何实现这些需求。
GameObejct相关的文档位于:https://docs.unity3d.com/ScriptReference/GameObject.html
这一篇我们会采用问题+答案的形式,告诉你如何解决游戏中常见的需求。
如何在脚本中获取自身所在的GameObject?
我们知道脚本必须挂在一个GameObject上面才能执行,那么如何知道当前脚本所挂载的GameObject是哪一个呢?
这就需要用到gameObject属性了。
gameObject属性可以在所有继承MonoBehaviour的类中获取到,因为脚本必须要挂在到一个物体上才能执行,这个gameObject就是脚本挂到的物体。
using UnityEngine;public class Test : MonoBehaviour{    void Start ()    {        Debug.Log(gameObject.name, gameObject);    }}
上面的代码就会打印出脚本所挂物体的名字。
注意这里Debug.Log传入了两个参数,这是为什么呢?
遇到这种问题,我们首先查一下Unity的文档。
为什么要查Unity的文档呢?





从图中可以看到,将光标移到Debug上面时,显示Debug类是属于UnityEngine这个命名空间的,也就是Unity提供的API。
Debug.Log有两种形式:
public static void Log(object message);public static void Log(object message, Object context);
第二种形式中可以传入一个Object类型的参数,传入这个参数时,在Console中显示的log会与脚本所在的物体关联。点击Console中这条信息时,会在Hierarchy中高亮这一个物体。



Log关联GameObject.gif

如何通过物体名字查找物体?
GameObject类中有一个静态(static)方法Find,用于通过名字查找场景中的物体。
什么是静态方法?
静态方法是标记为static的方法。静态方法独立于实例对象存在。即使没有类的实例,仍然可以通过类名.静态方法调用。静态方法中不能访问实例成员,可以访问其他静态成员。
静态方法在定义时需要在返回值类型前面加上static修饰符,比如:
static void Walk(){    Debug.Log("Walking");}
访问时,可以直接通过类名.方法名调用。比如查找物体的方法就是GameObject.Find("cat")。
查找的名称字符串中可以包含“/”,比如GameObject.Find("animals/cat")就只会查到父物体名字为animals的cat物体。如果“/”字符在字符串中最开始的位置,那么会在根节点开始找,比如GameObject.Find("/animals/cat")就只会查到根节点为animals物体的子物体cat。
查找过后,一定要判断一下是否为空,因为Find有可能找不到你想找的物体。
特别注意1
这个方法的效率比较低,不要在Update中调用此方法,否则可能会造成游戏卡顿。一般的做法是,在Awake或Start方法中通过Find找到,然后保存到成员变量中。
比如:
using UnityEngine;public class Test : MonoBehaviour{    private GameObject cat;    void Start ()    {        cat = GameObject.Find("cat");        if(cat != null)            Debug.Log("找到了cat物体", cat);    }}
特别注意2
这个方法无法找到active为false的物体。
那么如何查找active为false的物体呢?
1、不要使用Find,直接在代码中通过public的变量关联物体。
2、不要设置物体的active为false,先在游戏最开始时通过代码找到物体,然后通过代码设为false
3、通过transform.Find,我们明天会讲到。
如何修改物体的active状态?
修改物体的active状态是一个快速隐藏/显示物体的方法。物体的active是false时,物体上所有的组件都不会执行,相当于将物体隐藏了。
gameObject.SetActive(false);
特别注意
这个方法只会改变物体自身的active属性。如果该物体有子物体,那么子物体也会被隐藏,但是active属性不会变。如果该物体的父物体的active是false,即使将该物体的active设置为true,该物体也不会显示出来。
物体的active可以通过两个属性来判断:
activeInHierarchy 物体是否在Hierarchy中是激活状态。这个属性为true时,该物体及其所有父物体的active都为true。
activeSelf 物体自身的active属性是否为true,即使该物体的父物体的active可能为false。
如何通过tag查找物体?
除了通过物体的name查找物体,通过物体的tag也可以查找。Tag即在Inspector上设置的一个标签,如下图所示:




一个物体只能有一个Tag,但是一个Tag可以被多个物体使用。
通过tag查找有两个方法:
public static GameObject FindWithTag(string tag);
返回第一个查找到的标签为tag的active为true的物体,如果没有找到则返回null。
tag必须在TagManager中设置过,否则会抛出异常。异常内容是:UnityException: Tag: cat is not defined.含义是:标签:cat 没有定义。
public static GameObject[] FindGameObjectsWithTag(string tag);
由于一个Tag可以被多个物体使用,所以这个方法可以找到所有使用该标签的active为true的物体,并返回对应的数组。如果没有找到,会返回一个空数组(长度为0的数组)。
tag必须在TagManager中设置过,否则会抛出异常。异常内容是:UnityException: Tag: xxx is not defined.含义是:标签:xxx 没有定义。
如何用代码创建空物体?
有时候为了组织Hierarchy的结构,需要动态创建空物体作为文件夹使用。
创建空物体可以使用如下代码:
GameObject go = new GameObject();go.name = "EmptyGameObject";GameObject dog = new GameObject("Puppy");
new的时候可以传入一个字符串作为GameObject的名字。也可以不传,默认名字是New Game Object。也可以创建后再修改空物体的名字。
如何用代码创建内置几何体?
通过代码也很容易创建Unity中的几种默认几何体。
public static GameObject CreatePrimitive(PrimitiveType type);
其中PrimitiveType是一个枚举(enum)类型,包括的类型有:Sphere、Capsule、Cylinder、Cube、Plane、Quad。
具体的用法如下:
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
上面的代码可以创建一个Cube,和通过菜单栏GameObject > 3D Object > Cube创建出来的Cube一致。
什么是枚举?
枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。
C# 枚举是值类型。换句话说,枚举包含自己的值,且不能继承或传递继承。
声明枚举的一般语法:
enum <enum_name>{     enumeration list };
其中,
enum_name 指定枚举的类型名称。
enumeration list 是一个用逗号分隔的标识符列表。
枚举列表中的每个符号代表一个整数值,一个比它前面的符号大的整数值。默认情况下,第一个枚举符号的值是 0.例如:
enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
使用时,可以使用Days.Sun来表示星期日。
总结
本文讲解了和GameObject类相关的常见问题及API的用法。
但是由于GameObject类中还有一些不常用API,建议自行查阅GameObject文档获得更全面的了解:https://docs.unity3d.com/ScriptReference/GameObject.html
今日思考题
在Unity中通过代码尝试下讲到的和没讲到的API~
欢迎在留言区分享你的收获,和大家一起讨论。
别忘了分享给你学Unity的朋友,也许能够帮到他。
洪流学堂公众号回复专栏,查看更多专栏文章。



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

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