实现第一人称移动之前,我是将摄像机作为主角(游戏物体)的子物体,并设置好了合适的位置及高度。
1:第一人称移动
移动主要是通过position累加改变实现
//第一人称移动
public void Move()
{
float x = Input.GetAxis("Horizontal"); //输入水平,左右
float z = Input.GetAxis("Vertical"); //输入纵向,前后
Vector3 fwd = transform.forward;
Vector3 f = new Vector3(fwd.x, 0, fwd.z).normalized;
Vector3 r = transform.right;
Vector3 move = f * z + r * x;
transform.position += move * 20.0f * Time.deltaTime;
}
2:第一人称旋转
//第一人称旋转
public void MouseLook()
{
float mx = Input.GetAxis("Mouse X");
float my = -Input.GetAxis("Mouse Y");
Quaternion qx = Quaternion.Euler(0, mx, 0);
Quaternion qy = Quaternion.Euler(my, 0, 0);
/*
镜头水平旋转实际上是沿世界坐标系的y轴旋转,而镜头俯仰旋转则是围绕角色的局部坐标系的x轴旋转
注意四元数乘以向量时,必须四元数在前,向量在后——世界坐标系.
四元数相乘不符合交换律,相乘顺序不同会影响结果
通过交换四元数相乘的顺序,可以让物体沿不同坐标系的坐标轴进行旋转。
*/
transform.rotation = qx * transform.rotation; //世界坐标系旋转
transform.rotation = transform.rotation * qy; //局部坐标系旋转
float angle = transform.eulerAngles.x;
/*
用四元数表示的旋转角度是唯一的,但转成欧拉角就不唯一了,导致有时候是-1°,有时候又突然变成359°。
如果angle是359°,那么后续判断就全乱套了。
解决方案就是通过巧妙的方式判断angle的范围,如果超出-180~180,
就要加上或减去一个周期(360°),以控制angle的取值范围。
*/
if (angle > 180) angle -= 360;
if (angle < -180) angle += 360;
if (angle >80)
{
transform.eulerAngles = new Vector3(80, transform.eulerAngles.y, 0);
}
if (angle <-80)
{
transform.eulerAngles = new Vector3(-80, transform.eulerAngles.y, 0);
}
}
3:完整代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FPSCharacter : MonoBehaviour
{
void Start()
{
//隐藏鼠标
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
void Update()
{
Move();
MouseLook();
}
public void Move()
{
float x = Input.GetAxis("Horizontal"); //输入水平,左右
float z = Input.GetAxis("Vertical"); //输入纵向,前后
Vector3 fwd = transform.forward;
Vector3 f = new Vector3(fwd.x, 0, fwd.z).normalized;
Vector3 r = transform.right;
Vector3 move = f * z + r * x;
transform.position += move * 20.0f * Time.deltaTime;
}
public void MouseLook()
{
float mx = Input.GetAxis("Mouse X");
float my = -Input.GetAxis("Mouse Y");
Quaternion qx = Quaternion.Euler(0, mx, 0);
Quaternion qy = Quaternion.Euler(my, 0, 0);
/*
镜头水平旋转实际上是沿世界坐标系的y轴旋转,而镜头俯仰旋转则是围绕角色的局部坐标系的x轴旋转
注意四元数乘以向量时,必须四元数在前,向量在后——世界坐标系.
四元数相乘不符合交换律,相乘顺序不同会影响结果
通过交换四元数相乘的顺序,可以让物体沿不同坐标系的坐标轴进行旋转。
*/
transform.rotation = qx * transform.rotation; //世界坐标系旋转
transform.rotation = transform.rotation * qy; //局部坐标系旋转
float angle = transform.eulerAngles.x;
/*
用四元数表示的旋转角度是唯一的,但转成欧拉角就不唯一了,导致有时候是-1°,有时候又突然变成359°。
如果angle是359°,那么后续判断就全乱套了。
解决方案就是通过巧妙的方式判断angle的范围,如果超出-180~180,
就要加上或减去一个周期(360°),以控制angle的取值范围。
*/
if (angle > 180) angle -= 360;
if (angle < -180) angle += 360;
if (angle >80)
{
transform.eulerAngles = new Vector3(80, transform.eulerAngles.y, 0);
}
if (angle <-80)
{
transform.eulerAngles = new Vector3(-80, transform.eulerAngles.y, 0);
}
}
}