看到不少同学都想写一个CameraController,但是又各种转来转去出错的,今天就得空写一个例子,分享一下这其中需要了解的知识。
首先要了解向量的基本操作,向量旋转:四元素×向量。
举个简单例子:定义一个初始值为(0,0,1)的向量:
private Vector3 targetPos = Vector3.forward;
为了清楚的看清向量的旋转,我们将此向量画出来:
Debug.DrawLine(Vector3.zero, targetPos);
OK,从Unity的Top视角来看,应该是这样的:
接下来我们将此向量绕Y轴顺时针旋转45度:
Quaternion qua1 = Quaternion.Euler(0, 45, 0);
targetPos = qua1 * Vector3.forward;
得到的向量是这样的:
当然,你也可以任性的乘N个:
OK,有了以上基础,我们来实现摄像机的控制。想想一下,如果玩家站在原点,我们来转动一个点,最后把Camera放到我们旋转后的位置,最后让Camera看向玩家,是不是有点思路了。
当然这个时候运行代码,玩家只能站在原点,因为你会发现如果不在原点摄像机就乱转了。其实原因很简单,那是因为我们始终是把一个点绕着(0,0,0)点来转,而不是玩家。那么如果我们知道了玩家的位置,是不是就可以绕玩家来转了。那玩家的位置是又是什么呢。我想你几乎可以脱口而出,不就是player.position嘛。
好了,思路就是这样,自己加了一些其他的小细节。当然,万变不离其宗,上代码:
<span style="font-family:KaiTi_GB2312;font-size:18px;">using UnityEngine;
public class CameraController : MonoBehaviour {
/// <summary>
/// 跟随目标
/// </summary>
public Transform Target;
/// <summary>
/// Distance between target and me
/// </summary>
public float Dis = 5;
/// <summary>
/// 最大转动速度
/// </summary>
public int MaxRotSpeed = 100;
/// <summary>
/// Y轴转动角度范围
/// </summary>
public float YMaxAngel = 30f;
public float YMinAngel = -60f;
/// <summary>
/// 转动阻尼
/// </summary>
public int RotDamping = 5;
/// <summary>
/// Y轴跟随阻尼
/// </summary>
public int YFollowDamping = 3;
/// <summary>
/// 默认绕X旋转角度
/// </summary>
private int DefaultX = -8;
/// <summary>
/// 高度偏移
/// </summary>
public Vector3 OffHeight = new Vector3(0, 1, 0);
/// <summary>
/// 注视目标点
/// </summary>
public Vector3 TargetPos {
get {
return Target.position + OffHeight;
}
}
/// <summary>
/// 角速度
/// </summary>
private float XRotSpeed;
private float YRotSpeed;
/// <summary>
/// 转动角度
/// </summary>
private float xRot;
private float yRot;
private Transform myTrans;
public void Start() {
myTrans = transform;
//Camera初始位置在target的后方
Vector3 originDir = -Target.forward;
Quaternion qua = Quaternion.LookRotation(originDir);
yRot = qua.eulerAngles.y;
xRot = DefaultX;
}
private Quaternion qua;
private Vector3 newPos;
public void Update() {
CameraMove();
}
private void CameraMove() {
//获取旋转速度
XRotSpeed = Mathf.Lerp(XRotSpeed, Input.GetAxis("Mouse Y") * MaxRotSpeed, 1f / RotDamping);
YRotSpeed = Mathf.Lerp(YRotSpeed, Input.GetAxis("Mouse X") * MaxRotSpeed, 1f / RotDamping);
//计算旋转角度
xRot += XRotSpeed * Time.deltaTime;
yRot += YRotSpeed * Time.deltaTime;
//限制范围
xRot = Mathf.Clamp(xRot, YMinAngel, YMaxAngel);
yRot = Mathf.Repeat(yRot, 360);
qua = Quaternion.Euler(new Vector3(xRot, yRot, 0));
//向量Vector3.forward * Dis旋转qua后,+ TargetPos,即为最终Camera的位置
newPos = TargetPos + qua * Vector3.forward * Dis;
//Y轴延迟跟随
newPos.y = Mathf.Lerp(myTrans.position.y, newPos.y, 1f / YFollowDamping);
//更新Camera位置并看向目标
myTrans.position = newPos;
myTrans.LookAt(TargetPos);
}
public void SetTarget(Transform tgt) {
Target = tgt;
}
}</span>
将此脚本挂在Camera上,然后选择要观察的物体
Target,点击运行就可以看效果啦!
可以看到,核心的一步就是:
newPos = TargetPos + qua * Vector3.forward * Dis;
也就是我们今天讲的一个知识点,是不是很简单呢。OK,注释已经很详细了,这里就不多做解释。有问题可以留言讨论哦!