Unity 3D\2D手机游戏开发:从学习到产品(第3版)
上QQ阅读APP看书,第一时间看更新

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 第一人称视角