美文网首页
unity 相机围绕物体旋转

unity 相机围绕物体旋转

作者: WOTTOW | 来源:发表于2019-11-24 15:20 被阅读0次
  需要实现的功能是相机缓慢移动到目标点,并围绕目标点以一定的半径进行旋转。

使用的时候感觉手感不好:
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;
            }
        }
    }
}

http://www.voidcn.com/article/p-pxnnsefb-bn.html

相关文章

网友评论

      本文标题:unity 相机围绕物体旋转

      本文链接:https://www.haomeiwen.com/subject/fgtkwctx.html