
200+篇教程总入口,欢迎收藏:
放牛的星星:[教程汇总+持续更新]Unity从入门到入坟——收藏这一篇就够了zhuanlan.zhihu.com

本文重点:
1、为形状创建一个工厂
2、保存和加载形状的id
3、支持多个材质和随机颜色
4、启用GPU实例化
这是关于对象管理系列的第二篇教程。在这一部分中,我们将添加对不同材质和颜色的多种形状的支持,同时保持游戏向后兼容,即兼容游戏的前一个版本。
本教程使用Unity 2017.4.1f1编写。

1 形状工厂
本教程的目标是让我们的游戏更有趣,通过允许创建其他的形状,而不仅仅是白色的立方体。就像位置、旋转和缩放一样,我们将在玩家每次生成一个新形状时随机创建形状。
1.1 形状类
我们需要具体说明游戏会生成什么样的东西。游戏本身只会产生形状,而不是通常的可持久化对象。因此应该创建一个新的Shape类,它表示几何3D形状。目前来说它只是继承自PersistableObject,尚没有添加任何新东西。

从Cube预制件中删除PersistableObject组件,并为其提供Shape组件。它不能同时具有两者,因为我们为PersistableObject提供了DisallowMultipleComponent属性,该属性也会作用于Shape。

但这破坏了游戏对象对预制件的引用。但因为Shape也是一个PersistableObject,所以我们可以重新分配它。

1.2 多个不同的形状
创建一个默认的球体和胶囊对象,给它们每人一个Shape组件,并把它们也变成预制件。这些是我们的游戏将支持的其他形状。

那圆柱体呢?
当然,你还可以添加一个圆柱体对象,但我省略了它,因为圆柱体没有自己的碰撞器类型。相反,他们使用的是一个胶囊碰撞器,但并不适合。这虽然不是现在的问题,但以后可能会成为问题。
1.3 工厂Asset
当前,Game只能生成一件事,因为它仅具有对预制件的引用。要支持所有三种形状,将需要三个预制引用。这需要三个字段,但这并不灵活。更好的方法是使用数组。当然,也许以后我们会想出另一种方式来创建形状。但这只会让Game变得更加复杂,因为它还需要负责用户输入,跟踪对象并触发保存和加载等。
为了简化Game,我们将在他们自己的类中支持形状的创建。此类就像工厂一样,按需创建形状,而其用户不必知道如何制作这些形状,甚至不必知道有多少种不同的选择。我们将此类命名为ShapeFactory。

工厂的唯一责任是交付形状实例。它不需要位置,旋转或缩放,也不需要Update方法来更改其状态。因此,它不必是组件,不需要将其附加到游戏对象上。相反,它可以单独存在,不是作为特定场景的一部分,而是作为项目的一部分。换句话说,它是一种资产。可以继承自ScriptableObject而不是MonoBehaviour。

我们现在有了一个自定义资产类型。为了将这样的资产添加到我们的项目中,我们必须为它添加一个条目到Unity的菜单中。最简单的方法是将CreateAssetMenu属性添加到类中。

不现在可以通过资产创建形状工厂来创建我们的工厂。但只需要一个。

为了让我们的工厂了解形状预制件,可以给它一个shape[]预制件数组字段。我们不希望这个字段是公开的,因为它的内部工作不应该公开给其他类。所以要保密。为了让数组在检查器中显示并被Unity保存,可以添加SerializeField属性给它。

字段出现在检查器中之后,将所有三个形状预置拖放到它上面,这样对它们的引用就会被添加到数组中。确保立方体是第一个元素。第二个元素使用球体,第三个元素使用胶囊。

1.4 获取形状
要使工厂发挥作用,必须有一种方法可以从它获得shape实例。给它一个公共Get方法。客户端可以通过形状标识符参数指出它想要的形状类型。为此,我们将简单地使用一个整数。

为什么不使用枚举?
这当然是可以的,所以你可以这样做。但是我们并不真正关心在代码中确定确切的形状类型&#