U1L5——最小单位GameObject

GameObject

在Unity编辑器中:游戏对象__是 Unity Editor 中最重要的概念。游戏中的每个对象(从角色和可收集物品到光源、摄像机和特效)都是__游戏对象。但是,游戏对象本身无法执行任何操作;需要向游戏对象提供属性,然后游戏对象才能成为角色、环境或特效。

重要的类 - GameObject - Unity 手册

而在脚本中:Unity 的 GameObject 类用于表示任何可以存在于场景中的事物。

本章代码关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
gameObject                                        //获取该MonoBehaviour派生类对应的GameObject类的实例化对象
//GameObject的成员变量
gameObject.name //脚本所挂载的游戏对象的名字
gameObject.activeSelf //脚本所挂载的游戏对象的激活状态(bool)
gameObject.isStatic //脚本所挂载的游戏对象的是否是静态的(bool)
gameObject.layer //脚本所挂载的游戏对象的层级
gameObject.tag //脚本所挂载的游戏对象的标签
gameObject.transform //脚本所挂载的游戏对象的Transform类的实例化对象
//GameObject中的静态方法
GameObject.CreatePrimitive(PrimitiveType.几何体) //创建自带几何体
GameObject.Find("对象名") //通过对象名遍历在场景中的所有对象去查找激活的对象
GameObject.FindGameObjectWithTag("tag名") //通过tag查找单个对象
GameObject.FindGameObjectsWithTag("tag名") //通过tag查找多个对象,返回数组
GameObject.FindObjectOfType<>() //找到场景中挂载的某一个脚本对象
GameObject.Instantiate(克隆对象) //根据克隆对象创建一个一模一样的对象
GameObject.Destroy(, ) //删除对象,也可以删除脚本,第二个参数可以填延迟删除时间
GameObject.DestroyImmediate() //立即删除对象或脚本而不等到下一帧更新
GameObject.DontDestroyOnLoad(); //使自己依附的GameObject对象,过场景不被删除
//GameObject中的成员方法
new GameObject() //创建空物体
.AddComponent<>() //为对象添加脚本
this.gameObject.CompareTag() //游戏对象的标签比较
.SetActive() //设置游戏对象的激活失活
this.gameObject.SendMessage() //通知自己执行什么行为
this.gameObject.BroadcastMessage(); //广播行为让自己和自己的子对象执行
this.gameObject.SendMessageUpwards("函数名"); //向父对象和自己发送信息,并执行

GameObject中的成员变量

主要的成员变量有:name​(名字)、activeSelf​(是否激活)、isStatic​(是否是静态)、layer​(层级)、tag​(标签)、transform

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//名字
print(this.gameObject.name);
this.gameObject.name = "Lesson4SevenL改名";
print(this.gameObject.name);
//是否激活
print(this.gameObject.activeSelf);
//是否是静态
print(this.gameObject.isStatic);
//层级
print(this.gameObject.layer);
//标签
print(this.gameObject.tag);
//transform(使改变信息)
print(this.gameObject.transform.position); //等同于this.gameObject.transform,不过一个是通过gameObject获得,一个通过Mono获得

GameObject中的静态方法

注意!Unity里面的Object 不是指的万物之父Object
Unity里的Object 命名空间在UnityEngine中的 Object类 也是集成万物之父的一个自定义类
C#中的Object 命名空间是在System中的

创建自带几何体

只要得到了一个GameObject​对象 就可以得到它身上挂载的任何脚本信息,通过obj.GetComponent​来得取

1
2
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
obj.name = "SevenL创建的立方体";

查找对象

注意!以下的所有的方法无法找到失活的对象,只能找到激活的对象

查找单个对象

注意!如果场景中存在多个满足条件的对象,我们无法准确确定找到的是谁
得到某一个单一对象目前就有两种方式了:

  1. 是public从外部面板拖 进行关联

  2. 通过API去找

  3. 通过对象名查找

    注意!这个方法查找效率低下,性能损耗大,不建议使用,因为它会遍历在场景中的所有对象去查找

    1
    2
    3
    4
    5
    6
    7
    8
    9
    GameObject obj2 = GameObject.Find("SevenL");
    if (obj2 != null)
    {
    print(obj2.name);
    }
    else
    {
    print("没有找到所需对象");
    }
  4. 2.通过tag来查找对象

    以上方法 在有重名或者有多个对象为同一tag的情况下 无法查找指定的对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    GameObject obj3 = GameObject.FindWithTag("Player");
    //该方法与上面的方法 效果是一样的 只是名字不一样而已
    GameObject obj3 = GameObject.FindGameObjectWithTag("Player");
    if (obj3 != null)
    {
    print("根据tag找到的对象" + obj3.name);
    }
    else
    {
    print("根据tag没有找到对应对象");
    }

查找多个对象

找多个对象的API 只能是通过tag去找多个 通过名字 是没有找多个的方法的

1
2
GameObject[] objs =  GameObject.FindGameObjectsWithTag("Player");
print("找到tag为Player的个数" + objs.Length);

查找某个脚本

还有几个查找对象相关是用的比较少的方法 是GameObject父类 Object提供的方法
它可以找到场景中挂载的某一个脚本对象(效率比直接查找对象名的方法更差,因为不仅要遍历对象,还要遍历对象的脚本)

1
2
Lesson4 o = GameObject.FindObjectOfType<Lesson4>();
print(o.gameObject.name);

实例化对象(克隆对象)的方法

实例化(克隆)对象,它的作用是:根据一个GameObject对象,创建出一个和它一模一样的对象

1
GameObject obj5 = GameObject.Instantiate(myobj);

以后学了更多的知识点 就可以在这里操作obj
如果你继承了 MonoBehaviour​ 其实可以不用写GameObject​一样可以使用
因为这个方法是Unity里面的Object基类提供给我们的 所以可以直接用

删除对象的方法

第一个参数是对象或者脚本,第二个参数是延迟几秒删除,可以不填,不仅可以删除对象 还可以删除脚本

注意!该方法不能用于没有运行Unity程序的编辑器状态下,因为该方法是在运行模式下的下一帧删除,
在没有运行Unity程序的编辑器状态下是无法删除且报错的

1
2
3
4
5
GameObject.Destroy(myobj2);
//第二个参数代表延迟几秒
GameObject.Destroy(obj5, 5);
//Destroy()不仅可以删除对象 还可以删除脚本
GameObject.Destroy(this);

删除对象有两种作用

  1. 是删除指定的一个游戏对象
  2. 是删除一个指定的脚本对象

注意:这个Destroy()不会马上移除对象 只是给这个对象加了一个移除标识,一般情况下 它会在下一帧把这个对象移除并从内存中移除


立即删除游戏对象的方法

以下的方法会立刻将对象移除,但是如果没有特殊的需要马上移除一个对象的情况下
建议用上面的 Destroy​ 方法 因为是异步的 降低卡顿的概率

但如果是没有运行Unity程序的编辑器模式下,要删除场景上的对象必须使用该方法,而不能使用 Destroy​ 方法

1
GameObject.DestroyImmediate();

如果是继承MonoBehaviour​的类一样不用写GameObject因为这个方法是Unity里面的Object基类提供给我们的, 所以可以直接用


GameObject中的成员方法

创建空物体

new一个GameObject就是在创建一个空物体
第一个参数是对象的名字,后面的参数可以填多个控件(脚本)以添加脚本

1
2
3
GameObject obj6 = new GameObject();
GameObject obj7 = new GameObject("SevenL创建的空物体");
GameObject obj8 = new GameObject("加了脚本的空物体", typeof(Lesson2), typeof(Lesson1));

为对象添加脚本

继承了MonoBehaviour的脚本 是不能去new的
如果想要动态的添加MonoBehaviour的脚本 在某个对象上
直接使用GameObject提供的方法即可
有两种方法,更推荐泛型方法,因为不需要as,更加方便

1
2
3
Lesson1 les1 = obj6.AddComponent(typeof(Lesson1)) as Lesson1;
//上下两者是等同的,但是更推荐下面的泛型方法 因为不需要as 更加方便
Lesson2 les2 = obj6.AddComponent<Lesson2>();

标签比较

顾名思义、通过比较传入的标签名来确认是否为该标签

1
2
3
4
5
6
7
8
9
if (this.gameObject.CompareTag("Player"))
{
print("对象的标签是Player");
}
//上下两者是一样的
if (this.gameObject.tag == "Player")
{
print("对象的标签 是 Player");
}

设置激活或失活

false 失活、true 激活

1
2
3
obj6.SetActive(false);
obj7.SetActive(false);
obj8.SetActive(false);

次要的成员方法

了解即可 不建议使用 效率较差
通过广播或者发送信息的形式 让自己或者别人 执行某些行为方法

通知自己执行某个行为

命令自己 去执行这个TestFun这个函数 会在自己身上挂载所有脚本去找这个名字的函数
该对象会去找到 自己身上所有的脚本 有这个名字的函数去执行

1
2
this.gameObject.SendMessage("TestFun");
this.gameObject.SendMessage("TestFun2", 199);

对子对象广播

广播行为 让自己和自己的子对象执行

1
this.gameObject.BroadcastMessage("函数名");

对父对象广播

向父对象和自己发送信息,并执行

1
this.gameObject.SendMessageUpwards("函数名");

总结

GameObject的常用内容

基本成员变量
名字 失活激活状态 标签 层级 等等

静态方法相关
创建自带几何体
查找场景中的对象
实例化对象
删除对象
过场景不移除

成员方法
设置激活失活状态
和MonoBehaviour中相同的 得到脚本相关的方法