Unity 基于Cinemachine的OrbitCameraControl

using Cinemachine;
using SFramework;
using UnityEngine;

[RequireComponent(typeof(CinemachineVirtualCamera))]
public class OrbitCameraControl : MonoBehaviour
{
    [Space]
    public Vector3 startPosition;
    public Vector2 startRotation = new Vector2(60, 0);
    public float startDistance = 20;
    [Space]
    public float rotationSpeed = 2f;
    public float rotationDamping = 5f;
    public Vector2 rotationClamp = new Vector2(5, 85);
    [Space]
    public float zoomSpeed = 10f;
    public float zoomDamping = 5f;
    public Vector2 zoomClamp = new Vector2(5, 100);
    [Space]
    public Transform target;
    public Vector3 targetPosition;
    public float moveDamping = 5f;
    [Space]
    public bool autoRotate;

    private CinemachineVirtualCamera vcamera;
    protected Transform cameraTarget;
    private Cinemachine3rdPersonFollow _3rd;

    private float currentRotationX, currentRotationY, currentDistance;
    private float lerpDistance;
    protected bool canControl = true;
    protected virtual void Start()
    {
        vcamera = GetComponent<CinemachineVirtualCamera>();
        _3rd = vcamera.AddCinemachineComponent<Cinemachine3rdPersonFollow>();

        if (cameraTarget == null)
        {
            cameraTarget = new GameObject("Camera Target").transform;
            cameraTarget.position = startPosition;
            cameraTarget.eulerAngles = startRotation;
            vcamera.Follow = cameraTarget;
            _3rd.CameraDistance = startDistance;
            currentDistance = startDistance;
        }
        currentRotationX = startRotation.x;
        currentRotationY = startRotation.y;
    }
    protected virtual void Update()
    {
        var axis = OnGetAxis();

        if (canControl)
        {
            rotation(axis);
            zoom(axis);
            move();
        }
    }
    protected virtual void LateUpdate()
    {
        if (autoRotate)
        {
            OnAutoRotateEvent();
        }
    }
    private void rotation(Vector3 axis)
    {
        currentRotationX += axis.x * rotationSpeed;
        currentRotationY += axis.y * rotationSpeed;
        currentRotationX = Mathf.Clamp(currentRotationX, rotationClamp.x, rotationClamp.y);
        if (currentRotationY > 180)
        {
            currentRotationY -= 360;
        }
        else if (currentRotationY < -180)
        {
            currentRotationY += 360;
        }

        var targetRotation = Quaternion.Euler(currentRotationX, currentRotationY, 0.0f);
        cameraTarget.rotation = Quaternion.Lerp(cameraTarget.rotation, targetRotation, Time.deltaTime * rotationDamping);
    }
    private void zoom(Vector3 axis)
    {
        currentDistance += axis.z * zoomSpeed;
        currentDistance = Mathf.Clamp(currentDistance, zoomClamp.x, zoomClamp.y);
        lerpDistance = Mathf.Lerp(lerpDistance, currentDistance, Time.deltaTime * zoomDamping);
        _3rd.CameraDistance = lerpDistance;
    }
    private void move()
    {
        if (target != null)
        {
            targetPosition = target.position;
        }
        cameraTarget.position = Vector3.Lerp(cameraTarget.position, targetPosition, Time.deltaTime * moveDamping);
    }

    public void SetRotation(Vector3 rotation)
    {
        currentRotationX = rotation.x;
        currentRotationY = rotation.y;
    }
    public void SetDistance(float dis)
    {
        currentDistance = dis;
    }
    public void SetTarget(Transform _target)
    {
        target = _target;
    }
    public void SetPosition(Vector3 position)
    {
        targetPosition = position;
    }
    public void SetControlActive(bool control)
    {
        canControl = control;
        if (control)
        {
            currentRotationX = cameraTarget.eulerAngles.x;
            currentRotationY = cameraTarget.eulerAngles.y;
        }
    }
    protected virtual Vector3 OnGetAxis()
    {
        if (UIManager.IsUITrigger())
        {
            return Vector3.zero;
        }

        float x = 0f;
        float y = 0f;
        float z = 0f;

        if (Input.GetMouseButton(0))
        {
            x = Input.GetAxis("Mouse X");
            y = -Input.GetAxis("Mouse Y");
        }
        z = -Input.GetAxis("Mouse ScrollWheel");
        return new Vector3(y, x, z);
    }

    #region AutoRotate

    protected Vector3 startMousePos;
    protected float pressTime;
    protected bool tempAutoRotate;
    protected bool isInvoke1, isInvoke2;
    protected virtual void OnAutoRotateEvent()
    {
        if (Input.GetMouseButtonDown(0))
        {
            startMousePos = Input.mousePosition;
        }
        if (Input.GetMouseButton(0))
        {
            pressTime = Time.time;
            if (Vector3.Distance(Input.mousePosition, startMousePos) > 50f)
            {
                tempAutoRotate = false;
                if (!isInvoke2)
                {
                    SetControlActive(true);
                    isInvoke2 = true;
                    isInvoke1 = false;
                }
            }
        }
        if (Time.time - pressTime > 5f)
        {
            tempAutoRotate = true;
        }

        if (tempAutoRotate)
        {
            cameraTarget.eulerAngles += new Vector3(0, -10f * Time.deltaTime, 0);

            if (!isInvoke1)
            {
                SetControlActive(false);
                isInvoke1 = true;
                isInvoke2 = false;
            }
        }
    }
    #endregion
}


LeanTouch控制

using Lean.Touch;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LeanTouchOrbitCameraControl : OrbitCameraControl
{
    public float touchRotationSpeed = 0.05f;
    protected override void Start()
    {
        base.Start();

        LeanTouch.OnFingerDown += LeanTouch_OnFingerDown;
    }

    protected override Vector3 OnGetAxis()
    {
        //当前是否在UI上
        if (LeanTouch.Fingers.Count > 0 && LeanTouch.Fingers[0].StartedOverGui)
        {
            return Vector3.zero;
        }
        float x = 0, y = 0, z = 0;
        // 单指旋转
        if (LeanTouch.Fingers.Count == 1)
        {
            LeanFinger finger = LeanTouch.Fingers[0];

            if (finger.ScreenDelta.x != 0 || finger.ScreenDelta.y != 0)
            {
                y = finger.ScreenDelta.x * touchRotationSpeed;
                x = -finger.ScreenDelta.y * touchRotationSpeed;
            }
        }
        // 两指缩放
        if (LeanTouch.Fingers.Count >= 1)
        {
            z = LeanGesture.GetPinchScale() - 1f;
        }
        return new Vector3(x, y, -z);
    }
    private void LeanTouch_OnFingerDown(LeanFinger obj)
    {
        startMousePos = Input.mousePosition;
    }
    protected override void OnAutoRotateEvent()
    {
        if (LeanTouch.Fingers.Count > 0)
        {
            LeanFinger finger = LeanTouch.Fingers[0];
            if (finger.StartedOverGui) return;

            if (finger.IsActive)
            {
                pressTime = Time.time;
                if (Vector3.Distance(Input.mousePosition, startMousePos) > 50f)
                {
                    tempAutoRotate = false;
                    if (!isInvoke2)
                    {
                        SetControlActive(true);
                        isInvoke2 = true;
                        isInvoke1 = false;
                    }
                }
            }
        }
        if (Time.time - pressTime > 5f)
        {
            tempAutoRotate = true;
        }

        if (tempAutoRotate)
        {
            cameraTarget.eulerAngles += new Vector3(0, -10f * Time.deltaTime, 0);

            if (!isInvoke1)
            {
                SetControlActive(false);
                isInvoke1 = true;
                isInvoke2 = false;
            }
        }
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Unity Cinemachine 是一个在 Unity 引擎中使用的强大的摄像机控制和管理工具。它可以帮助游戏开发者轻松地创建高质量的摄像机动画,并对摄像机进行复杂的控制和调整。下面我将针对 Unity Cinemachine 的使用案例进行介绍。 首先,Unity Cinemachine 可以用于创建多种类型的摄像机效果。比如在第三人称射击游戏中,我们可以使用 Cinemachine 来实现自由的跟随和旋转功能,让玩家可以在角色周围自由观察环境。此外,在平台游戏中,我们可以利用 Cinemachine 实现镜头跟随和平滑的镜头移动,并且可以在不同的场景中切换不同的摄像机角度,增加游戏的视觉效果和沉浸感。 其次,Unity Cinemachine 还可以帮助游戏开发者在过渡和剪辑摄像机之间创建流畅的过渡效果。通过 Cinemachine 的轨迹系统,开发者可以轻松地创建复杂的镜头移动路径,并且可以在不同的路径之间无缝切换,实现视角的流畅转换和视差效果。 最后,Unity Cinemachine 还可以与其他 Unity 引擎中的组件集成,比如与动画系统、碰撞检测和触发器等进行结合,实现更加复杂的摄像机行为和交互效果。这样,开发者可以更加灵活地控制游戏中的摄像机系统,实现更加丰富的游戏体验。 总之,Unity Cinemachine 是一个非常强大的摄像机控制工具,可以帮助游戏开发者轻松地创建高品质的摄像机动画和效果,为游戏增加更多的视觉和沉浸体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呼呼突突

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值