Unity中GameObject API解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhenghongzhi6/article/details/81476620

本文节选自洪流学堂公众号专栏《郑洪智的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的朋友,也许能够帮到他。

洪流学堂公众号回复专栏,查看更多专栏文章。



《郑洪智的Unity2018课》,倾尽我8年的开发经验,结合最新的Unity2018,带你从入门到精通。

猜你喜欢

转载自blog.csdn.net/zhenghongzhi6/article/details/81476620
今日推荐