FPS movement in Unity (youtube)
Two ways to create Character
这里只介绍第一种,使用人物控制组件Character Controller
制作
做一个FPS需要注意的所有问题
创建一个空对象 First Person Player
,加入 Character Controller
组件,设置 radius
和 height
(胶囊的半径和高度)
设置相机,将 Main Camera
相机移动到 First Person Player
中
为了更好地看到效果,在空对象下挂载子对象cylinder
,移动位置,让相机在物体内(这样视野中不会看到 cylinder
)
首先分析一下鼠标的移动对于视角的影响
鼠标在屏幕的两个方向 X/Y
上移动
X
方向控制左右旋转,Y
方向控制上下旋转
*注意,上下的视角移动限制在一定角度内
使用 Mathf.Clamp 完成
在导航栏 edit -> project settings -> input
中查看鼠标左右移动对应的输入名称
在First Person Player
上创建脚本 MouseLook.cs
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,相机为子对象,随人物移动,不需要再移动相机
(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);
}
}
首先,默认方向键对应的名称及数值如下,可以在 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;
调整 step offset
,代表能踏上距离地面多高范围内的台阶
variables 变量设置
public Transform groundCheck;
public float groundDistance = 0.4f;// radius
public LayerMask groundMask;
bool isGrounded;
在地面上我们不希望有任何 y
方向的速度,所以在接触地面时要清空 y
方向上的速度
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.
添加一个层级蒙版变量,用来检测接触到的物体是否为地面而非其他物体
最后加上跳跃的效果
跳跃高度与速度的物体公式为
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);
}
完成!
真实情况下,一般人物在空中是无法左右移动的,所以人物在空中时,加上对左右移动的限制效果
将 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
空对象来探测
跳跃根据公式模拟,修改物体速度即可