3.3 主角
因为是第一人称射击游戏,所以主角是不可见的,但在屏幕上可以看到主角手中拿的枪,尽管如此,我们还是需要为主角创建碰撞体并控制其移动。
3.3.1 角色控制器
步骤 01 在菜单栏中选择【GameObject】→【Create Empty】,创建一个空的游戏体,将它的Tag设为Player,它便是我们的主角。
步骤 02 在菜单栏中选择【Component】→【Physics】→【Character Controller】,为主角添加一个角色控制器组件,使用这个组件提供的功能,可以实现在控制主角移动的同时与场景的碰撞产生交互,比如在行走时不会穿到墙里面去。
步骤 03 为主角再添加一个Rigidbody组件,取消选中【Use Gravity】复选框去掉重力模拟,并选中【Is Kinematic】复选框使其不受物理演算影响,这样才能使用脚本控制其移动。在【Character Controller】组件中需要调整碰撞体的位置和大小,如图3-3所示。
图3-3 设置组件
步骤 04 创建脚本Player.cs:
using UnityEngine; using System.Collections; public class Player : MonoBehaviour { public Transform m_transform; // 角色控制器组件 CharacterController m_ch; // 角色移动速度 float m_movSpeed = 3.0f; // 重力 float m_gravity = 2.0f; // 生命值 public int m_life = 5; void Start() { m_transform = this.transform; // 获取角色控制器组件 m_ch = this.GetComponent<CharacterController>(); } void Update() { // 如果生命值为0,什么也不做 if (m_life <= 0) return; Control(); } void Control() // 控制主角移动代码 { // 定义三个值控制移动 float xm = 0, ym = 0, zm = 0; // 重力运动 ym-=m_gravity*Time.deltaTime; // 上下左右运动 if(Input.GetKey(KeyCode.W)) // 按W键 { zm+=m_movSpeed*Time.deltaTime; } else if(Input.GetKey(KeyCode.S)) // 按S键 { zm-=m_movSpeed*Time.deltaTime; } if(Input.GetKey(KeyCode.A)) // 按A键 { xm -= m_movSpeed * Time.deltaTime; } else if(Input.GetKey(KeyCode.D)) // 按D键 { xm += m_movSpeed * Time.deltaTime; } // 使用角色控制器提供的Move函数进行移动 它会自动检测碰撞 m_ch.Move(m_transform.TransformDirection(new Vector3(xm, ym, zm))); } // 在编辑器中为主角显示一个图标 void OnDrawGizmos() { Gizmos.DrawIcon(this.transform.position, "Spawn.tif"); } }
这里的代码主要是控制主角前后左右移动。
① 在Start函数中,我们先获取了CharacterController组件,然后在Control函数中,通过键盘操作获得X和Y方向上的移动方向,最后使用CharacterController组件提供的Move函数移动主角。使用CharacterController提供的功能进行移动,在移动的同时会自动计算移动体与场景之间的碰撞。
② 在OnDrawGizmos函数中,用一个图标来显示主角,主要是为了观察方便。
③ 将Player.cs脚本指定给主角的游戏体。运行游戏,按W、S、A、D键可以控制主角前后左右移动,但可能不易观察到,这是因为摄像机还没有与主角的游戏体关联起来。
3.3.2 摄像机
接下来,我们将在Player.cs脚本中添加一些代码,使摄像机伴随着主角移动。
步骤 01 打开Player.cs,添加用于控制摄像机的属性:
// 摄像机Transform Transform m_camTransform; // 摄像机旋转角度 Vector3 m_camRot; // 摄像机高度(即表示主角的身高) float m_camHeight = 1.4f;
步骤 02 修改Start函数,初始化摄像机的位置和旋转角度,并锁定鼠标:
void Start () { m_transform = this.transform; // 获取角色控制器组件 m_ch = this.GetComponent<CharacterController>(); // 获取摄像机 m_camTransform = Camera.main.transform; // 设置摄像机初始位置(使用TransformPoint获取Player在Y轴偏移一定高度的位置) m_camTransform.position = m_transform.TransformPoint(0, m_camHeight, 0); // 设置摄像机的旋转方向与主角一致 m_camTransform.rotation = m_transform.rotation; m_camRot = m_camTransform.eulerAngles; //锁定鼠标 Screen.lockCursor = true; }
步骤 03 在Control函数中旋转摄像机,在移动主角后使摄像机位置与主角位置保持一致:
//获取鼠标移动距离 float rh = Input.GetAxis("Mouse X"); float rv = Input.GetAxis("Mouse Y"); // 旋转摄像机 m_camRot.x -= rv; m_camRot.y += rh; m_camTransform.eulerAngles = m_camRot; // 使主角的面向方向与摄像机一致 Vector3 camrot = m_camTransform.eulerAngles; camrot.x = 0; camrot.z = 0; m_transform.eulerAngles = camrot; // 控制主角移动代码…(此处略) // 更新摄像机位置(始终与Player一致) m_camTransform.position = m_transform.TransformPoint(0, m_camHeight, 0);
我们通过控制鼠标旋转摄像机方向,使主角跟随摄像机的Y轴旋转方向,在移动主角时,又使摄像机跟随主角运动。运行游戏,已经可以自由地在场景中行走。
3.3.3 武器
下面我们将武器绑定到摄像机上,使其随着主角移动。
步骤 01 将摄像机的位置和旋转角度都设为0。
步骤 02 将摄像机的Clipping Planes/ Near设为0.1,使其可以看到更近处的物体。
步骤 03 在Project窗口的Prefabs文件夹中找到M16.Prefab,这是预设好的武器Prefab,它只是个简单的枪支模型,将其拖入场景。
步骤 04 在Hierarchy窗口中选择武器的Prefab(名字是M16),设置位置和旋转均为0,并置于摄像机层级下方,使其成为摄像机的子物体。然后选择武器Prefab下一级层级中的枪模型weapon,并调整它的位置和角度,在Camera Preview中预览效果,直到对效果满意为止,如图3-4所示。
图3-4 设置武器位置
步骤 05 运行游戏,效果如图3-5所示。
图3-5 第一人称视角