Unity | FPS 第一人称视角的人物控制

FPS movement in Unity (youtube)

Two ways to create Character
这里只介绍第一种,使用人物控制组件Character Controller 制作
两种人物控制的制作方法
做一个FPS需要注意的所有问题
做一个FPS需要注意的所有问题


0 准备工作

创建Character Controller 组件

创建一个空对象 First Person Player,加入 Character Controller 组件,设置 radiusheight(胶囊的半径和高度)

设置相机,将 Main Camera 相机移动到 First Person Player

为了更好地看到效果,在空对象下挂载子对象cylinder,移动位置,让相机在物体内(这样视野中不会看到 cylinder

Camera 的效果
对象的层级设置
(灰色部分之后会用到,可以先不用管)


1 Camera 视角移动

首先分析一下鼠标的移动对于视角的影响

鼠标在屏幕的两个方向 X/Y 上移动
X 方向控制左右旋转,Y 方向控制上下旋转

*注意,上下的视角移动限制在一定角度内
使用 Mathf.Clamp 完成

鼠标在两个轴上移动

获取鼠标的移动输入

在导航栏 edit -> project settings -> input 中查看鼠标左右移动对应的输入名称
查看鼠标左右移动对应的输入名称
First Person Player上创建脚本 MouseLook.cs

Camera 脚本设置

variables 变量设置

public float mouseSensitivity = 100f;
public Transform playerBody;
float xRotation = 0f;

获取鼠标的移动
float mouseX = Input.GetAxis("Mouse X")
float mouseY = Input.GetAxis("Mouse Y")

设置鼠标灵敏度
public float mouseSensitivity = 100f

获取 FirstPersonPlayertransform 组件(相机为子对象,跟随人物旋转视角 )

在这里插入图片描述

修改后:

float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;

左右方向转动

变量设置
public Transform playerBody;
绑定为 First Person Player

*注意,不是Camera,相机为子对象,随人物移动,不需要再移动相机
(Vector3.up 为竖直向上的单位向量)

playerBody.Rotate(Vector3.up * mouseX);

上下方向转动

设置基于 X 轴的转动(X对应左右,Y对应垂直,Z对应前后,需要在YOZ平面移动,所以对应X)
float xRotation = 0f ; //初始角度为0f

xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);// limit the angle
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);

设置鼠标锁定不可视的效果

void Start(){
	Cursor.lockState = CursorLockMode.Locked;
}

完整版

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseLook : MonoBehaviour
{

    public float mouseSensitivity = 100f;

    public Transform playerBody;

    float xRotation = 0f;

    // Start is called before the first frame update
    void Start()
    {
        // lock and hide the cursor
        Cursor.lockState = CursorLockMode.Locked;
    }

    // Update is called once per frame
    void Update()
    {
        float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
        float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;

        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, -90f, 90f);// limit the angle

        // rotate the camera within Y axis
        transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
        // rotate the player within X axis
        playerBody.Rotate(Vector3.up * mouseX);
    }
}

2 PlayerMovement 人物移动

首先,默认方向键对应的名称及数值如下,可以在 Edit -> Project Settings -> Input Manager 中查看
默认方向键对应的名称及数值
First Person Player 添加脚本 PlayerMovement.cs

public class PlayerMovement : MonoBehaviour
{
    public CharacterController controller;

    public float speed = 12f;
    // Update is called once per frame
    void Update()
    {
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");

        //Vector3 move = new Vector3(x, 0f, z);// × global movement, we dont want
        Vector3 move = transform.right * x + transform.forward * z;// move along the local coordinates right and forward

        controller.Move(move * speed * Time.deltaTime);
    }
}

*注意,移动需要沿着玩家当前的位置进行移动
所以需要获取当前物体的局部坐标系对应世界坐标的方向向量

常用的三个:

  • transform.right
  • transform.forward
  • transform.up
Vector3 move = transform.right * x + transform.forward * z;

stairs

调整 step offset,代表能踏上距离地面多高范围内的台阶

设置Step Offset


测试

楼梯效果


Gravity 重力模拟

重力影响下的速度和位移的曲线图
重力影响下的速度和位移的曲线图


variables 变量设置

public Transform groundCheck;
public float groundDistance = 0.4f;// radius
public LayerMask groundMask;

bool isGrounded;

重力对 y 方向上速度的影响

在地面上我们不希望有任何 y 方向的速度,所以在接触地面时要清空 y 方向上的速度


GroundCheck 用来监测地面的空对象

在人物的最下方,添加一个空对象,用来监测与地面距离
GroundCheck 位置摆放


CheckSphere

Physics.CheckSphere 用来监测一定距离内是否有 collider

可以探测物体是否接触地面,这时候就要用到 GroundCheck


CheckSphere(position, radius, mask)

Returns true if there are any colliders overlapping the sphere defined by position and radius in world coordinates.


Ground Mask

添加一个层级蒙版变量,用来检测接触到的物体是否为地面而非其他物体


添加和修改层级

添加层级
修改地面物体的层级,应用于所有子对象
修改Ground的层级


设置脚本的 Ground MaskGround
设置脚本的 Ground Mask


Jump

最后加上跳跃的效果

跳跃高度与速度的物体公式为
v = 2 h g v = \sqrt{2hg} v=2hg
由于设置了重力为负,所以修改为
v = − 2 h g v = \sqrt{-2hg} v=2hg

variables 设置变量

public float jumpHight = 2f;// 跳跃高度

脚本设置

jump

if(Input.GetButtonDown("Jump") && isGrounded)
{
    velocity.y = Mathf.Sqrt(-2f * jumpHight * gravity);
}

最后再检查一遍脚本的对象挂载
Player Movement 的对象挂载


测试

跳跃效果测试

完成!


Pro 提升

真实情况下,一般人物在空中是无法左右移动的,所以人物在空中时,加上对左右移动的限制效果

限制人物空中改变方向

Vector3 move 设置为类成员变量,只有接触到地面才能改变方向

float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");

if(isGrounded)
{
    move = transform.right * x + transform.forward * z;
}
controller.Move(move * speed * Time.deltaTime);

测试

空中人物移动方向锁定


小结

使用 CharacterController 控制人物移动,需要划分 视角移动 以及 人物移动

视角移动

视角的上下旋转为相机的自我旋转,限定一个范围 [-90,90]
左右旋转为人物的旋转,相机随人物旋转

人物移动

人物方向移动依靠 HorizontalVertical 方向键控制
需要注意坐标轴为局部坐标轴 transform.right transform.forward

重力根据重力公式修改 velocity.y 的速度,需要检测地面,在人物底面添加 CheckGround 空对象来探测

跳跃根据公式模拟,修改物体速度即可

  • 10
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
根据提供的引用内容,我无法找到关于Unity实现第三人称视角的具体信息。但是,我可以为您提供一些关于Unity实现第三人称视角的一般步骤和示例代码。 1. 创建摄像机: - 在Unity中创建一个摄像机对象。 - 将摄像机放置在合适的位置和角度,以便能够正确显示第三人称视角。 2. 跟随主角: - 将摄像机对象设置为跟随主角对象。 - 使用脚本或代码来实现摄像机的跟随功能,使其始终保持在主角的后方或适当的位置。 3. 视角控制: - 实现视角控制功能,使玩家能够通过鼠标或其他输入设备来控制摄像机的旋转和移动。 - 使用脚本或代码来处理输入,并将其应用于摄像机对象,以实现第三人称视角的旋转和移动。 以下是一个简单的示例代码,演示了如何在Unity中实现第三人称视角: ```csharp using UnityEngine; public class ThirdPersonCamera : MonoBehaviour { public Transform target; // 主角对象 public float distance = 5f; // 摄像机与主角的距离 public float height = 2f; // 摄像机与主角的高度 public float rotationDamping = 3f; // 旋转阻尼 private void LateUpdate() { if (target != null) { // 计算摄像机的目标位置 Vector3 targetPosition = target.position - target.forward * distance + Vector3.up * height; // 平滑地旋转摄像机 Quaternion targetRotation = Quaternion.LookRotation(target.position - transform.position, target.up); transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, rotationDamping * Time.deltaTime); // 平滑地移动摄像机 transform.position = Vector3.Lerp(transform.position, targetPosition, rotationDamping * Time.deltaTime); } } } ``` 请注意,这只是一个简单的示例代码,您可能需要根据您的具体需求进行修改和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值