Unity | FPS 第一人称视角的人物控制
FPS movement in Unity (youtube)
Two ways to create Character
这里只介绍第一种,使用人物控制组件Character Controller
制作
做一个FPS需要注意的所有问题
创建Character Controller 组件
创建一个空对象 First Person Player
,加入 Character Controller
组件,设置 radius
和 height
(胶囊的半径和高度)
设置相机,将 Main Camera
相机移动到 First Person Player
中
为了更好地看到效果,在空对象下挂载子对象cylinder
,移动位置,让相机在物体内(这样视野中不会看到 cylinder
)
(灰色部分之后会用到,可以先不用管)
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
获取 FirstPersonPlayer
的 transform
组件(相机为子对象,跟随人物旋转视角 )
修改后:
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,相机为子对象,随人物移动,不需要再移动相机
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);
}
}
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
,代表能踏上距离地面多高范围内的台阶
测试
Gravity 重力模拟
重力影响下的速度和位移的曲线图
variables 变量设置
public Transform groundCheck;
public float groundDistance = 0.4f;// radius
public LayerMask groundMask;
bool isGrounded;
重力对 y 方向上速度的影响
在地面上我们不希望有任何 y
方向的速度,所以在接触地面时要清空 y
方向上的速度
GroundCheck 用来监测地面的空对象
在人物的最下方,添加一个空对象,用来监测与地面距离
CheckSphere
Physics.CheckSphere
用来监测一定距离内是否有 collider
可以探测物体是否接触地面,这时候就要用到 GroundCheck
CheckSphere(position, radius, mask)
Returns true if there are any colliders overlapping the sphere defined by
position
andradius
in world coordinates.
Ground Mask
添加一个层级蒙版变量,用来检测接触到的物体是否为地面而非其他物体
添加和修改层级
修改地面物体的层级,应用于所有子对象
设置脚本的 Ground Mask
为 Ground
Jump
最后加上跳跃的效果
跳跃高度与速度的物体公式为
由于设置了重力为负,所以修改为
variables 设置变量
public float jumpHight = 2f;// 跳跃高度
脚本设置
jump
if(Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(-2f * jumpHight * gravity);
}
最后再检查一遍脚本的对象挂载
测试
完成!
提升
真实情况下,一般人物在空中是无法左右移动的,所以人物在空中时,加上对左右移动的限制效果
限制人物空中改变方向
将 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]
左右旋转为人物的旋转,相机随人物旋转
人物移动
人物方向移动依靠 Horizontal
和 Vertical
方向键控制
需要注意坐标轴为局部坐标轴 transform.right
transform.forward
重力根据重力公式修改 velocity.y
的速度,需要检测地面,在人物底面添加 CheckGround
空对象来探测
跳跃根据公式模拟,修改物体速度即可