刚开始学习unity的时候很容易对众多的API搞糊涂,特别是博客里很多博主的写作思路十分混乱,完全不能看懂,看了书之后感觉清晰了很多,总结一下。
如果你还分不清世界坐标系和Self坐标系,建议先去看下基础,
(虽然希望录多一点,但是由于图片大小限制,只能这样,,,)可以在Scene里看到,没有限制四周的方向,限制了上下的视野。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseLook : MonoBehaviour
{
//注意枚举的使用,可以用名称设置值,而不是用魔术数字,这样有利于代码的理解和阅读,是良好的习惯
public enum RotationAxes
{
MouseXAndY = 0,
MouseX = 1,
MouseY = 2
}
public float sensitivityHor = 9.0f;//水平旋转速度
public float sensitivityVert = 9.0f; //垂直旋转速度,灵敏度
public float minimumVert = -45.0f;
public float maximumVert = 45.0f;
private float _rotationX = 0;//为垂直角度声明一个变量
public RotationAxes axes = RotationAxes.MouseXAndY; //使得变量暴露在组件里,可以在Unity里可视化更改
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(axes == RotationAxes.MouseX)
{
transform.Rotate(0,Input.GetAxis("Mouse X") * sensitivityHor, 0);
//水平旋转,所以固定了z轴,绕着z轴在四周旋转。
}
else if (axes == RotationAxes.MouseY)
{ //垂直方向旋转的代码
_rotationX -= Input.GetAxis("Mouse Y") * sensitivityVert; //基于鼠标增加垂直角度
_rotationX = Mathf.Clamp(_rotationX, minimumVert, maximumVert); //限制上下看的范围
float rotationY = transform.localEulerAngles.y;//保持y的角度
transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0); //使用新的值存储固定了的旋转前的水平旋转信息并增加上下方向旋转的移动
}
else
{
// 同时可以水平和垂直方向的旋转
_rotationX -= Input.GetAxis("Mouse Y") * sensitivityVert;
_rotationX = Mathf.Clamp(_rotationX, minimumVert, maximumVert);
float delta = Input.GetAxis("Mouse X") * sensitivityHor; //delta是旋转的变化量,一般数学上也会把变化量协作delta
float rotationY = transform.localEulerAngles.y+ delta;
transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0);
}
}
}
第一人称视角的编写,也就是所谓的MouseLook(视野跟着鼠标的方向移动)首先要理清旋转的概念。
例如:下面这个略倾斜的立方体(略倾斜是为了使得世界World坐标系
和自身sELF坐标系
不一样)
transform.Rotate(speed, 0, 0,Space.Self);
transform.Rotate(speed, 0, 0,Space.World);
1.沿着World坐标
旋转时,是沿着世界坐标系(右上角的那个坐标)在旋转,整体的旋转方向垂直于屏幕
2,沿着Self坐标
旋转时,可以看出,是沿着自身的x轴在旋转,红色的轴没有变动,
Rotate()的实际含义是 ”增加当前的旋转“,由于在水平方向的旋转我们的确需要增加就行了,所以可以用Rotate,
而我们的垂直方向的旋转需要限制旋转的范围,
所以,显然Rotate就不合适了,因为即使限制了旋转的增加的幅度,,也会导致角度的增加,
会导致莫名奇妙的翻车
:
所以受限制的垂直方向上的旋转需要使用其他的方法”——写死增加的值,固定住需要旋转的角度的幅度。
Rotate可以理解为增加,transform.localEulerAngles
可以理解为设置角度为XX度。
1.利用Input.GetAxis("Mouse Y")
来获取在垂直方向上的鼠标的位移,乘上一个灵敏度,免得过度灵敏,
得到的这个角度只是一个固定值,但是还没有和原有角度组合应用,所以需要将过去的值减去变化值 --->当前值
private float _rotationX = 0;//为垂直角度声明一个变量
_rotationX -= Input.GetAxis("Mouse Y") * sensitivityVert; //基于鼠标增加垂直角度
_rotationX = Mathf.Clamp(_rotationX, minimumVert, maximumVert); //限制上下看的范围,Math.Clamp限制了取值范围,防止了过度旋转,
2.然后获取当前的y轴的角度,因为在进行受限制的垂直视角变换时,其实水平方向上是不变的,所以需要写死增加的值,固定住需要旋转的角度的幅度的时候,水平角度固定住。
float rotationY = transform.localEulerAngles.y;//获取y的角度
transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0); //使用新的值存储固定了的旋转前的水平旋转信息并增加上下方向旋转的移动
3.最后,结合水平方向上无限制和垂直方向上受到限制的控制和变化,
利用 transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0);
来自己定义角度变化,
注意,由于垂直角度被限制了,导致了水平旋转也不能用Rotate去增加了(因为最后都必须用transform.localEulerAngles
来进行设置),所以只能老实地求值了。
// 同时可以水平和垂直方向的旋转
_rotationX -= Input.GetAxis("Mouse Y") * sensitivityVert;
_rotationX = Mathf.Clamp(_rotationX, minimumVert, maximumVert);
float delta = Input.GetAxis("Mouse X") * sensitivityHor; //delta是旋转的变化量,一般数学上也会把变化量协作delta
float rotationY = transform.localEulerAngles.y+ delta;
transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0);
1.我们需要创建新的Vector3, 而不是修改Transform已经存在的值,因为transform里的值是只读的
,这是常犯的错误。
2.记住。Rotate是增加角度!!
3.对玩家进行禁止物理旋转: 当玩家是刚体,和其他碰撞体进行接触时,轻微的碰撞也会导致玩家被反弹,跌倒等等,这种碰撞的行为显然不符合预期(我们假设人是柔软的),
所以我们需要加入:
void Start()
{
//.....其他代码
Rigidbody body = GetComponent<Rigidbody>();
if(body!= null)
{
body.freezeRotation = true; //设置物理旋转无效。
}
//...其他代码
}