前言:上一篇实现了角色简单的移动控制,但是实际游戏中玩家的视角是可以转动的,并根据转动后视角调整移动正前方。本篇实现玩家第一人称视角转动和移动,觉得有帮助的话可以点赞收藏支持一下!
修复小问题-武器反向
上一篇文章武器模型的方向反了,武器模型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。
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进行限制。
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()函数部分加入鼠标锁定代码。
Cursor.lockState = CursorLockMode.Locked;
移动控制更新
会发现视角变了后,但是移动的方向的前后左右并没有跟随视角,需要对移动控制的代码进行更新。
原先是直接在X、Y和Z分量上直接加入输入的值,我们为计算的加入Transformer的方向重新计算输入的值到不同的分量的值。
修改后的PlayerMovement()代码如下:
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代码,实现了玩家视角移动和转动的所有代码。
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旋转
}
}
效果
补充知识
鼠标设置
可见性
Cursor.visible = true; //设置鼠标可见
Cursor.visible = false; //设置鼠标不可见
锁定
Cursor.lockState = CursorLockMode.None;//不锁定,自由移动状态
Cursor.lockState = CursorLockMode.Locked;//锁定状态,第一人称常用
Cursor.lockState = CursorLockMode.Confined;//限制状态,鼠标只能在游戏界面内移动
形状
菜单-Edit-Project Settings-Player,可以设置鼠标图标。