熟悉一下 Unity 的 workflow 并记录下来吧。毕竟之前学的早就已经忘光了。
Part1 项目初始化
首先是将当前的 Scene 另存为到 Scene 文件夹下。
随后新建了两个 3D Object ,分别是平台 Ground 和玩家操控的小球 Player 。我们可以修改它们的 Transform ,来设定它们的空间位置、朝向,或进行缩放。
默认情况下,右侧是红色的 轴,前方是蓝色的 轴,正上方是绿色的 轴。
新建 Materials 文件夹,在里面新建一个名为 Background 的 material ,在 Main Maps 中,修改 Albedo 为 (0, 12, 64) 即深蓝色。随后我们可以直接将这个 material 拖动到平台上。
我们可以调整 Directional Light 的方向让平台被照亮,更亮一些。
Part2 移动小球
选中 Player ,在 Component->Physics 菜单中给它附加 Rigidbody. 也可以通过 Inspector 最下面的 Add Component 按钮来附加 Component .
Run 一下,由于默认具有 Gravity ,可以看到小球已经落下来了。
通过 Add Component->New Script ,来添加一个新的名为 PlayerController 的 C# 脚本到 Player 上。为了方便管理,我们新建一个 Scripts 文件夹并将这个脚本放在 Script 文件夹中。
打开这个脚本,可以看到这是一个继承了 MonoBehaviour 的 PlayerController 类,你可以重载 Start, Update, FixedUpdate 函数,分别代表…
后面讲了一大堆怎么看 Unity 文档,分别查了 Input 和 Rigidbody . 为啥 Visual Studio 就没有查文档快捷键啊?
我们要在 PlayerController 中,通过 Rigidbody 的 AddForce 方法去控制 Player 的 Rigidbody. 于是需要将 Player 的 Rigidbody 像参数一样传给 PlayerController , 或者说绑定到 PlayerController 上。我们的做法是:
给 PlayerController 里面加一个私有成员:
1 | private Rigidbody rb; |
直接在 Start 中:
1 | rb = GetComponent<Rigidbody>(); |
这样就能获取脚本所属的 Object 的其他 Component 了。
给 PlayerController 里面加一个公有成员
1 | public float speed; |
以此来在脚本编辑器外部,也即在 Unity 中修改其数值来控制速度。
Part3 控制 Camera
首先设置 Main Camera 的位置,其次我们可以通过设置 Rotation 来调整 Camera 绕 轴旋转的角度。
相机的默认向前的方向为 。经过旋转之后向前的方向也会发生变化。
事实上,我们调高相机,然后绕着 轴旋转 度。
我们希望相机随着小球一起动,但是将相机作为小球的 Child 是不行的;因此当小球滚动时,相机也会绕着它滚动,但这不是我们想要的,我们希望相机始终保持在一个 平面上。
思路是记录下 position 的 offset 并根据这个更新保持这个 offset 不变,而相机的 rotation 则一直不变。
控制相机的脚本 CameraController 需要获取 Player 的 Object ,我们在脚本中开公有成员 GameObject player , 并在 Unity Editor 中将 Player 拖到脚本设置中即可。
Part4 设置围栏
新建一个空的 GameObject 命名为 Wall 并将其作为一个组进行管理。我们让四面围墙都作为他的 Child 。
所谓的围墙也就是新建一个 Cube 并修改其各项属性将其放到平台边缘即可。
我们可以使用 Duplicate ,快捷键 Ctrl+D 来复制一个 Object 。
Part5 创建收集品
新建一个 Cube 名为 PickUp 作为收集品。通过脚本让它周期性旋转。
新建 Prefabs 文件夹,直接从 Hierarchy 中将对应的 GameObject 拖拽到这个文件夹中,这样我们就有了一个 PickUp 的模板。
新建一个空 Object 名为 PickUps 管理所有的 PickUp 。
接下来是调整 PickUps 的位置。可以通过调整右上角的 Gizmo 来调整视角。点击一下 y 轴从而可以自上而下进行观察。
此时拖动 PickUp ,但是发现 坐标还是会变化的。将上面的 Toggle Tool Handle Rotation 从 Local 修改为 Global 即可。
使用 Ctrl + D 复制很多这样的 PickUps 。然后通过修改 Prefab 的 Material 来修改所有 PickUps 的配色。
Part6 处理碰撞
开始接触物理引擎啦!
重载 Player 的 onTriggerEnter 函数,当碰撞物体的 Tag 为 “PickUp” 的时候,将碰撞物体 Disable 。
这里我们直接在 Prefab 中修改 Tag ,我们要新建自己的 Tag 。
但是运行起来的时候我们发现碰到 PickUp 的时候 Player 会被弹开,就像撞墙一样。我们要将 PickUp Prefab 中 Box Collider 中的 Is Trigger enable ,这样的话碰撞时只计算是否碰撞而不会产生物理效果。这是 Collider 和 Trigger 的区别。
这里逻辑已经没问题了。但是出于性能优化,我们要给 PickUp Prefab 添加一个 Rigidbody 。理由是如果只有 Collider 这个 Component ,Unity 会认为它是静止不动的(如墙、地板等等),会将其缓存。但是我们的 PickUp 实际上每一帧都在变化,这样反而会频繁更新缓存大大降低性能。我们只需给它添加一个 Rigidbody Component ,这样 Unity 就会认为它会动从而不会将其加入缓存。
加了 Rigidbody 之后 PickUp 会掉下去,因为我们 enable 了 Gravity 。我们 enable Is Kinematic 使它不受到任何作用力的影响来解决这一问题。
Part7 文本 UI
新建 UI -> Text ,注意到同时新建了 Canvas 和 EventSystem , 每个 UI 必须是 Canvas 的孩子。
修改 CountText 在 Canvas 的位置为左上角,感觉按 Alt 修改位置即可,不涉及旋转的话不必修改 Pivot 。
之后的话就都很简单了。