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;
            }
        }
    }

}


你可能感兴趣的:(unity,游戏引擎)