需要实现的功能是相机缓慢移动到目标点,并围绕目标点以一定的半径进行旋转。
使用的时候感觉手感不好:
1.已修改鼠标控制旋转的时候平滑处理。
2.已添加相机的放大和缩小功能
3.已添加功能,在已存在的固定点,矫正后沿着物体旋转
我的思路是:
1.先实现相机旋转
2.再实现相机平滑移动到目标点
我们需要把问题拆分一下,先从简单的功能入手
相机看向目标点并移动到目标点:
在这里会使用到数学中的向量,主要的用途是计算目标向量:
目标向量=(目标点-开始移动点).normalized
normalized目的是:为了后面数据处理的方便,其次是保证程序运行时收敛加快。
我们主要是实现相机看向目标点,所以我们需要求出旋转的Quaternion(四元素)或者Vector3,在这里我是用的时Quaternion。
在官方的Quaternion中提到过 Quaternion.LookRotation(目标向量)的返回值是旋转的Quaternion。
targetDir = (targetPos.position - mainCamera.position).normalized;
Rotation = Quaternion.LookRotation(targetDir);
相机位置移动到目标点:
mainCamera.position = targetPos.position ;
相机围绕目标点的以一定半径旋转:
这里我们需要知道相机在旋转时移动的轨迹是一个圆,所以在移动是需要通是调节相机的角度和位置。
这里主要是讲解:初始的半径(R)和初始角度(Vector3 InitRotation)
首先解决相机的初始位置:
当我们按照上面的写法,是直接到目标位置。我们只需要在这句代码加个差值就可以了。
计算差值:
这里需要用到公式:Quaternion*Vector3与Quaternion.eulerAngles ;
首先获取到目标向量:因为我们我们现在是把目标点看做开始点,在开始点为中心手动设置的目标点,所以目标向量=Vector3.forward;
Quaternion Rotation;
Vector3 second_Direction;
Rotation.eulerAngles = InitRotation; //初始化开始的旋转角度
second_Direction = Rotation * Vector3.forward;
end = targetPos.position - second_Direction * R;
鼠标控制目标的旋转:
首先需要获取鼠标的X轴和Y轴,同时需要控制X轴与Y轴的旋转速度
float x, y;
x += Input.GetAxis("Mouse X") * horizontalSPeed * Time.deltaTime;
y += Input.GetAxis("Mouse Y") * verticalSpeed * Time.deltaTime;
如果x, y等于0,来加移动的数值,这样有个问题:因为在开始时我们已经初始化了位置、和旋转的角度,所以要把初速的旋转角度赋值给x,y在进行相加。
然后把Vector3转换为四元素:
RotationA = Quaternion.Euler(y, x, 0);
这样旋转的位置已经有了,旋转的角度也有了
mainCamera.rotation = RotationA;
mainCamera.position = targetPos.position - second_Direction * R;
缓慢移动那个用个Dotween就可以了
private void CamreaMove()
{
mainCamera.DOKill();
targetDir = targetPos.position-end;
mainCamera.position = targetPos.position - targetDir.normalized * StartPosHeight;
mainCamera.localRotation = Rotation;
mainCamera.DOMove(end, durtion).OnComplete(()=> {
SetCamera(Rotation, end);
targetDir = Vector3.forward;
LimitCamreaRation = true;
});
}
Ration.gif
using UnityEngine;
using System.Collections;
//using DG.Tweening;
using System;
using Unity.Collections;
public class CameraRotateAround : MonoBehaviour
{
private Transform mainCamera;
[Header("目标点")] public Transform targetPos;
[Header("初始化角度")] public Vector3 InitRotation = new Vector3(45, 0, 0);
[Header("旋转速度")] public float RationSpeed = 10f;
[Header("旋转平滑速度")] public float rationSmoothSpeed = 10f;
[Header("位置平滑速度")] public float posSmoothSpeed = 20f;
[Header("滑轮的速度")] public float zoomSpeed = 40f;
[Header("滑轮移动的平滑速度")] public float zoomDampening = 5f;
[Header("最小的旋转")] public float LimitMinRationX = 20f;
[Header("最大的旋转")] public float LimitMaxRationX = 60f;
[Header("移动时间")] public float durtion = 2f;
[Header("开始位置的高度")] public float StartPosHeight = 500f;
[Header("旋转半径")] public float R = 240f;
[Header("滑轮的最小距离")] public float minR = 200f;
[Header("自动获取半径")] public bool AutoR = false;
[Header("旋转隐藏鼠标")] public bool CursorEnable = false;
private float currentR;
private float computeR;
private float x, y;
private float wheel;
private bool LimitCamreaRation = false; //限制鼠标控制相机旋转
private Vector3 targetDir; //向量方向
private Vector3 first_Direction; //开始移动时的方向
private Vector3 second_Direction; //当移动到目标位置后,通过方向算出的第二个方向
private Vector3 end;
private Vector3 computeEnd;
private Vector3 targetPosVector3;
private Quaternion Rotation; //自动获取的旋转
private Quaternion RotationA; //旋转变量A
private void Start()
{
mainCamera = Camera.main.transform;
}
private void LateUpdate()
{
if (Input.GetKeyDown(KeyCode.A))
{
InitCameraRotateAround();
}
if (Input.GetMouseButton(1) && LimitCamreaRation)
{
ControlCamrea();
}
else
{
Cursor.visible = true;
}
ContorlScroll();
}
private void InitCameraRotateAround()
{
LimitCamreaRation = false;
targetPosVector3 = targetPos.position;
if (InitRotation == Vector3.zero || AutoR)
{
Rotation = mainCamera.rotation;
x = Rotation.eulerAngles.y;
y = Rotation.eulerAngles.x;
}
else
{
Rotation.eulerAngles = InitRotation;
x = InitRotation.y;
y = InitRotation.x;
}
if (AutoR)
{
R = Vector3.Distance(targetPos.position, mainCamera.position);
}
else
{
targetDir = (targetPosVector3 - mainCamera.position).normalized;
}
currentR = R;
computeR = R;
RotationA = Rotation;
second_Direction = Rotation * Vector3.forward;
end = targetPosVector3 - second_Direction * currentR;
if (AutoR)
StartCoroutine("CorrectInitPos");
else
CamreaMove();
}
private void ControlCamrea()
{
if(CursorEnable)
Cursor.visible = false;
x += Input.GetAxis("Mouse X") * RationSpeed;
y -= Input.GetAxis("Mouse Y") * RationSpeed;
y = Mathf.Clamp(y, LimitMinRationX, LimitMaxRationX);
RotationA = Quaternion.Slerp(RotationA, Quaternion.Euler(y, x, 0), rationSmoothSpeed * Time.deltaTime);
first_Direction = RotationA * targetDir;
end = targetPosVector3 - first_Direction * currentR;
SetCamera(RotationA, Vector3.Slerp(end, (targetPosVector3 - first_Direction * currentR), posSmoothSpeed * 0.02F));
}
private void CamreaMove()
{
/* if (!AutoR)
{
mainCamera.DOKill();
targetDir = targetPos.position - end;
mainCamera.position = targetPos.position - targetDir.normalized * StartPosHeight;
mainCamera.localRotation = Rotation;
mainCamera.DOMove(end, durtion).OnComplete(() =>
{
SetCamera(Rotation, end);
});
}
else
{
// SetCamera(Rotation, end);
}*/
SetCamera(Rotation, end);
}
private void SetCamera(Quaternion Rotation, Vector3 end)
{
mainCamera.rotation = Rotation;
mainCamera.position = end;
targetDir = Vector3.forward;
LimitCamreaRation = true;
}
private void ContorlScroll()
{
wheel = Input.GetAxis("Mouse ScrollWheel");
if (wheel != 0 && LimitCamreaRation)
{
computeR -= (wheel > 0 ? 0.1F : -0.1F) * zoomSpeed;
computeR = Mathf.Clamp(computeR, minR, R);
}
if (Mathf.Abs(Mathf.Abs(computeR) - Mathf.Abs(currentR)) >= 0.1f)
{
currentR = Mathf.Lerp(currentR, computeR, Time.deltaTime * zoomDampening);
computeEnd = targetPosVector3 - (RotationA * Vector3.forward * currentR);
mainCamera.position = computeEnd;
}
}
private IEnumerator CorrectInitPos()
{
while (true)
{
if (Vector3.Distance(mainCamera.position, end) >= 0.01f)
{
mainCamera.rotation = Rotation;
mainCamera.position = Vector3.Lerp(mainCamera.position, end, 0.15f);
yield return null;
}
else
{
mainCamera.rotation = Rotation;
mainCamera.position = end;
targetDir = Vector3.forward;
LimitCamreaRation = true;
StopCoroutine("CorrectInitPos");
break;
}
}
}
}
网友评论