开始
下载开始项目 BlockBuster,解压缩,用 Unity 打开文件夹。
打开后是这个样子:
看一下场景视图。有一个小的竞技场,这是游戏的主战场,以及一个相机和一盏
灯。如果你的布局和上图不同,请点击右上角的下拉框并选择 2 by 3。
主角都没有叫什么游戏?你的第一个任务就是创建一个代表玩家的 GameObje
ct。
创建玩家角色
在结构视图中,点解 Create 按钮,选择 3D Object\Sphere。将球体放到 (X:
0, Y:0.5, Z:0) 然后命名为 Player。
Unity 用全组件式系统来构建 GameObject。也就是说所有的 GameObject 都
是由组件构成,这些组件会给游戏对象赋予行为和特性。这是几个 Unity 的内
置组件:
Transforme: 每个 GameObject 都有这个组件。它保存了 GameObject
的位置、角度和比例。
Box Collider:一种立方形的碰撞体,用于检测碰撞。
Mesh Filter:用于显示 3D 模型的网格数据。
Player 游戏对象需要和场景中的其它对象发生碰撞反应。要实现这一点,请在
结构视图中选择 Player,然后点击检视器窗口中的 Add Component 按钮。在
弹出菜单中选择 Physics > Rigidbody,这就为 Player 添加了一个刚体组件,
这样它就能够使用 Unity 的物理引擎了。
修改这个刚性体的属性为:Drag 设为 1,Angular Drag 为 0,勾选 Freeze
Position 旁边的 Y。
这将保证玩家角色不会被上下移动,同时在转动时不添加阻尼系数。
编写玩家移动的脚本
玩家角色创建好之后,准备创建接收键盘输入以及移动玩家的脚本。
在项目窗口中,点击 Create Button\Folder。命名文件夹为 Scripts,然后在下
面创建一个 Player 子文件夹。
在 Player 文件夹中,点击 Create 按钮,选择 C# Script。新脚本命名为 Pla
yerMovement。这个样子:
注意:创建这些文件夹有利于将文件安装各自的职能进行组织,避免混乱。你将为 Player 创
建多个脚本,因此单独用一个文件夹会更好。
双击 PlayerMovement.cs 脚本。这会用你喜欢的代码编辑器打开这个脚本。U
nity 内置了 MonoDevelop,它支持所有平台,在安装器运行时,Windows 用
户可以安装 Visual Studio 来取代它。
本教程假设你使用 MonoDevelop,但 Visual Studo 用户也不会有任何问题。
当代码编辑器打开,你会看到:
这是 Unity 在新脚本中生成的默认的类。它继承了 MonoBehaviour 基类,这
样脚本才能够在游戏中运行,同时还有一些特殊的方法对特定事件作出响应。如
果你是一个 iOS 开发者,这个类就好比 UIViewCotnroller。Unity 会在运行脚
本时以特定顺序调用多个方法。最常见的几个方法包括:
Start(): 这个方法在脚本第一次 update 时调用。
Update(): 当游戏正在运行,同时脚本是可用的,这个方法会在每帧刷新时
调用。
OnDestroy(): 在这个脚本所附着的 GameObject 被销毁之前调用。
OnCollisionEnter(): 当这个脚本所附着的碰撞体或刚体和其它碰撞体或刚
体发生接触时调用。
完整的事件列表,请参考 Unity 的 MonoBehaviours 文档。
在 Start() 方法前,添加两行代码:
public float acceleration;
public float maxSpeed;
脚本看起来是这个样子:
1
2
这是公共变量声明,这意味着这两个变量能够在检视器中看到并修改,而无需在
脚本和编辑器中来回切换。
acceleration 表示玩家的速度随着时间递增。maxSpeed 则表示速度的上限。
在它们后面声明这几个变量:
private Rigidbody rigidBody;
private KeyCode[] inputKeys;
private Vector3[] directionsForKeys;
1
2
3
私有变量无法用检视器来设置,它的初始化由开发者在某个时机负责。
rigidBody 用于保存一个对刚体组件的引用,即附着在 Player GameObject 上
的刚体组件。
inputKeys 是一个键盘码的数组,用于检查输入。
directionsForKeys 用于保存一个 Vector3 变量数组,这些变量表示方向数据。
将 Start() 方法修改为:
void Start () {
inputKeys = new KeyCode[] { KeyCode.W, KeyCode.A, KeyCode.S, KeyCode.D
};
directionsForKeys = new Vector3[] { Vector3.forward, Vector3.left, Vec
tor3.back, Vector3.right };
rigidBody = GetComponent();
}
1
2
3
4
5
这段代码将按键对应到方向,比如 W 是向前。最后一行获得了一个对所附着的
刚体组件的引用,将它保存到 rigidBody 变量以便使用。
要真正移动玩家的角色,还需要处理键盘输入。
将 Update() 修改为 FixedUpdate() 并加入以下代码:
// 1
void FixedUpdate () {
for (int i = 0; i < inputKeys.Length; i++){
var key = inputKeys[i];
// 2
if(Input.GetKey(key)) {
// 3
Vector3 movement = directionsForKeys[i] * acceleration * Time.delta
Time;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
有几个地方需要注意一下:
1. FixedUpdate() 是不依赖于帧率的,它和刚体一起使用。和以尽量快的速
度运行不同,这个方法会以固定的间隔执行。
2. 这个循环检测哪个按键被按下。
3. 获取被按下的键所表示的方向,乘以加速度和上一帧耗费的秒数。最终算
出一个方向向量(在 x,y 和 z 轴上的速度),你就可以用它来移动 Pl
ayer 对象了。
如果你是编程新手,你可能奇怪为什么要乘以 Time.detalTime。游戏是在帧率
(帧/秒)下运行的,帧率是取决于硬件和它运行压力,这样在性能好的机器上
帧率快,而在性能差的机器上帧率慢,从而导致不可预知的结果。通常的办法是,
当需要按每帧执行一个动作时,都乘上 Time.deltaTime。
在 FixedUpdate() 方法后添加:
void movePlayer(Vector3 movement) {
if(rigidBody.velocity.magnitude * acceleration > maxSpeed) {
rigidBody.AddForce(movement * -1);
} else {
rigidBody.AddForce(movement);
}