Unity3D学习FPS游戏(3)玩家第一人称视角转动和移动

前言:上一篇实现了角色简单的移动控制,但是实际游戏中玩家的视角是可以转动的,并根据转动后视角调整移动正前方。本篇实现玩家第一人称视角转动和移动,觉得有帮助的话可以点赞收藏支持一下!

玩家第一人称视角

修复小问题-武器反向

上一篇文章武器模型的方向反了,武器模型Y方向旋转180度就好了。

玩家视角转动和移动

视角转动

思路分析

FPS游戏中玩家可以通过移动鼠标来旋转视角。

最简单的思路就是,获取鼠标移动的值,然后修改玩家Player对象的Rotation。

但是直接修改Player的Rotation不对!!!

为什么?

  • 修改Player的Rotation的值后,移动控制会根据当前视角为前方移动,会存在朝着斜上方走的情况。
  • 如果是带有玩家模型的话,直接Rotation属性来旋转整个Player,垂直方向旋转的时候就会让玩家的模型也垂直转动,会很诡异。一般都是枪支和手才会参与所有的旋转,玩家的身体模型是不会参与垂直。

怎么办?

  • 水平Rotation修改Player的;
  • 垂直Rotation修改Camera的;
  • Player挂载Camera,Camera挂载Weapon武器(有手的话也挂载在相机下面)。

这样Player水平旋转带动玩家模型、相机还有武器(和手),但是相机垂直旋转只会带动武器(和手)。

调整Player挂载

Player挂载Camera,Camera挂载Weapon。

视角移动

补充在我们PlayerController代码中,添加两个新的变量用来记录鼠标移动X和Y的累计偏移,还有一个Transform变量playerCamera来获取和控制相机的Rotation。

csharp 复制代码
private float x_RotationOffset = 0;// 累计x旋转
private float y_RotationOffset = 0;// 累计y旋转
public Transform playerCamera;// 这个在Unity中把Camera拖到变量就行
private void PlayerRotation()
{
    // 获取鼠标移动
    x_RotationOffset += Input.GetAxis("Mouse X")* Time.deltaTime * mouseSensitivity;// 水平方向
    y_RotationOffset += Input.GetAxis("Mouse Y")* Time.deltaTime * mouseSensitivity;// 垂直方向
    // 旋转
    transform.rotation = Quaternion.Euler(new Vector3(0, x_RotationOffset, 0));// Player旋转
    playerCamera.localRotation= Quaternion.Euler(new Vector3(y_RotationOffset, playerCamera.localEulerAngles.y, playerCamera.localEulerAngles.z));// Camera旋转
}

视角角度限制

把PlayerRotation()添加到Update中运行后,可以发现视角会随着偏移。但是玩家会随着鼠标偏移无限制的旋转视角,尤其是垂直视角,这并不符合我们FPS游戏体验。

需要对旋转的范围做出一个限制,修改PlayerRotation(),对垂直视角添加Mathf.Clamp进行限制。

csharp 复制代码
private void PlayerRotation()
{
    // 获取鼠标移动
    x_RotationOffset += Input.GetAxis("Mouse X")* Time.deltaTime * mouseSensitivity;// 水平方向
    y_RotationOffset += Input.GetAxis("Mouse Y")* Time.deltaTime * mouseSensitivity;// 垂直方向
    // 限制垂直旋转角度
    y_RotationOffset = Mathf.Clamp(y_RotationOffset, -45f, 45f);
    // 旋转
    transform.rotation = Quaternion.Euler(new Vector3(0, x_RotationOffset, 0));// Player旋转
    playerCamera.localRotation= Quaternion.Euler(new Vector3(y_RotationOffset, playerCamera.localEulerAngles.y, playerCamera.localEulerAngles.z));// Camera旋转
}

鼠标锁定

前面虽然实现了随着鼠标转动视角,但是会发现没法像真正游戏的第一视角锁定鼠标(移动了之后鼠标还是在中间),反而会离开屏幕。

在Start()函数部分加入鼠标锁定代码。

csharp 复制代码
Cursor.lockState = CursorLockMode.Locked;

移动控制更新

会发现视角变了后,但是移动的方向的前后左右并没有跟随视角,需要对移动控制的代码进行更新。

原先是直接在X、Y和Z分量上直接加入输入的值,我们为计算的加入Transformer的方向重新计算输入的值到不同的分量的值。

修改后的PlayerMovement()代码如下:

cpp 复制代码
public void PlayerMovement()
{
    // CharacertController的Move函数需要输入一个三维的向量
    // 每个分量表示三维不同方向前进多少
    Vector3 moveDirection = Vector3.zero;
    // 获取键盘输入
    // Horizontal左右移动;Vertical前后移动
    // 加入自身tranform方向
    moveDirection = Vector3.zero;
    moveDirection += transform.forward  * Input.GetAxis("Vertical");
    moveDirection += transform.right * Input.GetAxis("Horizontal");

    m_Controller.Move(moveDirection * Time.deltaTime*speed);
}

完整代码

PlayerController代码,实现了玩家视角移动和转动的所有代码。

csharp 复制代码
public class PlayerController : MonoBehaviour
{
    public CharacterController m_Controller;
    public Transform playerCamera;

    public float moveSpeed = 6.0F;
    public float mouseSensitivity = 1000.0F;
    private float x_RotationOffset = 0;// 累计x旋转
    private float y_RotationOffset = 0;// 累计y旋转


    void Start()
    {
        m_Controller = this.GetComponent<CharacterController>();
        Cursor.lockState = CursorLockMode.Locked;// 鼠标锁定
    }

    
    void Update()
    {
        PlayerRotation();
        PlayerMovement();
    }

    // 控制角色移动
    public void PlayerMovement()
    {
        Vector3 moveDirection = Vector3.zero;
        // 获取键盘输入:Horizontal左右移动;Vertical前后移动
        // 加入自身tranform方向
        moveDirection = Vector3.zero;
        moveDirection += transform.forward  * Input.GetAxis("Vertical");
        moveDirection += transform.right * Input.GetAxis("Horizontal");
        // 移动
        m_Controller.Move(moveDirection * Time.deltaTime*moveSpeed);
    }

    // 控制角色视角
    private void PlayerRotation()
    {
        // 获取鼠标移动
        x_RotationOffset += Input.GetAxis("Mouse X")* Time.deltaTime * mouseSensitivity;// 水平方向
        y_RotationOffset += Input.GetAxis("Mouse Y")* Time.deltaTime * mouseSensitivity;// 垂直方向
        // 限制垂直旋转角度
        y_RotationOffset = Mathf.Clamp(y_RotationOffset, -45f, 45f);
        // 旋转
        transform.rotation = Quaternion.Euler(new Vector3(0, x_RotationOffset, 0));// Player旋转
        playerCamera.localRotation= Quaternion.Euler(new Vector3(y_RotationOffset, playerCamera.localEulerAngles.y, playerCamera.localEulerAngles.z));// Camera旋转
    }
}

效果

补充知识

鼠标设置

可见性

csharp 复制代码
Cursor.visible = true;   //设置鼠标可见
Cursor.visible = false;  //设置鼠标不可见

锁定

csharp 复制代码
Cursor.lockState = CursorLockMode.None;//不锁定,自由移动状态
Cursor.lockState = CursorLockMode.Locked;//锁定状态,第一人称常用
Cursor.lockState = CursorLockMode.Confined;//限制状态,鼠标只能在游戏界面内移动

形状

菜单-Edit-Project Settings-Player,可以设置鼠标图标。

相关推荐
天人合一peng10 小时前
unity 生成标记根据背景色标记变色
unity·游戏引擎
数据皮皮侠AI13 小时前
中国城市可再生能源数据集(2005-2021)|顶刊 Sci Data 11 种能源面板
大数据·人工智能·笔记·能源·1024程序员节
天人合一peng14 小时前
unity 生成标记根据背景色变色为明显的颜色
unity·游戏引擎
魔士于安15 小时前
Unity 超市总动员 超市收银台 超市货架 超市购物手推车 超市常见商品
游戏·unity·游戏引擎·贴图·模型
CandyU215 小时前
Unity —— 数据持久化
unity·游戏引擎
zh路西法15 小时前
【Unity实现Oneshot胶卷显形】游戏窗口化与Win32API的使用
游戏·unity·游戏引擎
凡情19 小时前
android隐私合规检测
android·unity
小贺儿开发20 小时前
Unity3D 本地 Stable Diffusion 文生图效果演示
人工智能·unity·stable diffusion·文生图·ai绘画·本地化
mxwin1 天前
Unity Shader 半透明物体为什么不能写入深度缓冲?
unity·游戏引擎·shader
晚枫歌F2 天前
三层时间轮的实现
网络·unity·游戏引擎