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