290 lines
9.7 KiB
C#
290 lines
9.7 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using MyFrameworkPure;
|
|
using UnityEngine;
|
|
|
|
#if STEAMVR
|
|
using HTC.UnityPlugin.Vive;
|
|
#endif
|
|
|
|
namespace CommonScript
|
|
{
|
|
public enum MouseButton
|
|
{
|
|
Left = 0,
|
|
Right,
|
|
Middle,
|
|
}
|
|
/// <summary>
|
|
/// 相机旋转的通用脚本
|
|
/// </summary>
|
|
public class CameraRotator : MonoBehaviour
|
|
{
|
|
[Header("鼠标输入")]
|
|
[SerializeField] private bool enableMouseInput = true;
|
|
|
|
[SerializeField] private MouseButton mouseButton = MouseButton.Left;
|
|
[SerializeField] private float mouseRotSpeed = 5;
|
|
|
|
[Header("触屏输入")]
|
|
[SerializeField] private bool enableTouchInput = true;
|
|
|
|
#if STEAMVR
|
|
[Header("Vive输入")]
|
|
[SerializeField] private bool enableViveInput = true;
|
|
[SerializeField] private ViveRoleProperty viveRoleProperty = ViveRoleProperty.New(HandRole.RightHand);
|
|
[SerializeField] private float viveRotSpeed = 30;
|
|
#endif
|
|
|
|
[Header("其他参数")]
|
|
[SerializeField] private Transform cameraTransform;
|
|
[SerializeField] private Transform target;
|
|
[SerializeField] private bool lookatTarget = true;
|
|
[SerializeField] private bool allowZoom = true;
|
|
[SerializeField] private float zoomSpeed = 50;
|
|
[SerializeField] private float farestToTarget = 3000f;
|
|
[SerializeField] private float nearestToTarget = 0f;
|
|
|
|
[SerializeField] private bool clampEuler = true;
|
|
[SerializeField] private float minEulerX = 0;
|
|
[SerializeField] private float maxEulerX = 180;
|
|
[SerializeField] private float minEulerY = -180;
|
|
[SerializeField] private float maxEulerY = 180;
|
|
public Transform target_yinyong;
|
|
private Vector3 lastMousePos;
|
|
private Vector2 lastTouchPos;
|
|
|
|
private Vector3 lastCameraPos;
|
|
private Vector3 lastCameraRot;
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
cameraTransform = cameraTransform != null?cameraTransform:transform;
|
|
SetTarget(target);
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
if (enableMouseInput)
|
|
HandleMouseInput();
|
|
if (enableTouchInput)
|
|
HandleTouchInput();
|
|
//if (enableViveInput)
|
|
// HandleViveInput();
|
|
if (clampEuler)
|
|
ClampEuler();
|
|
if (lookatTarget && target)
|
|
{
|
|
cameraTransform.LookAt(target);
|
|
}
|
|
|
|
if (allowZoom && target)
|
|
{
|
|
ClameDistanceToTarget();
|
|
}
|
|
|
|
RecordCameraTransform();
|
|
}
|
|
|
|
public void SetTarget(Transform target)
|
|
{
|
|
//校验目标物合法性
|
|
if (target)
|
|
{
|
|
float distance = Vector3.Distance(cameraTransform.position, target.position);
|
|
if (allowZoom && (distance > farestToTarget || distance < nearestToTarget))
|
|
{
|
|
Debug.LogError("相机初始位置不满足要求!");
|
|
return;
|
|
}
|
|
Vector3 euler = VectorTool.ConvertToEuler180(cameraTransform.eulerAngles);
|
|
if (clampEuler && (euler.x < minEulerX || euler.x > maxEulerX))
|
|
{
|
|
Debug.LogError("相机旋转X分量不满足要求");
|
|
return;
|
|
}
|
|
if (clampEuler && (euler.y < minEulerY || euler.y > maxEulerY))
|
|
{
|
|
Debug.LogError("相机旋转Y分量不满足要求");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (allowZoom || lookatTarget)
|
|
{
|
|
Debug.LogError("开启相机缩放或朝向目标开关,要求目标物不能为空!");
|
|
return;
|
|
}
|
|
}
|
|
|
|
this.target = target;
|
|
RecordCameraTransform();
|
|
target_yinyong = target;
|
|
}
|
|
|
|
void HandleMouseInput()
|
|
{
|
|
if (Input.GetMouseButtonDown((int)mouseButton))
|
|
{
|
|
lastMousePos = Input.mousePosition;
|
|
}
|
|
if (Input.GetMouseButton((int)mouseButton))
|
|
{
|
|
Vector3 delta = Input.mousePosition - lastMousePos;
|
|
if (target)
|
|
{
|
|
cameraTransform.RotateAround(target.position,-cameraTransform.right, delta.y * mouseRotSpeed * Time.deltaTime);
|
|
ClampPosFromEulerX();
|
|
|
|
cameraTransform.RotateAround(target.position,Vector3.up,delta.x * mouseRotSpeed * Time.deltaTime);
|
|
ClampPosFromEulerY();
|
|
}
|
|
else
|
|
{
|
|
cameraTransform.Rotate(Vector3.left * delta.y * mouseRotSpeed * Time.deltaTime, Space.Self);
|
|
cameraTransform.Rotate(Vector3.up * delta.x * mouseRotSpeed * Time.deltaTime, Space.World);
|
|
}
|
|
lastMousePos = Input.mousePosition;
|
|
}
|
|
|
|
if (allowZoom)
|
|
{
|
|
float mouseScroll = Input.GetAxis("Mouse ScrollWheel");
|
|
cameraTransform.Translate(Vector3.forward * mouseScroll * zoomSpeed * Time.deltaTime);
|
|
}
|
|
}
|
|
|
|
void HandleTouchInput()
|
|
{
|
|
if(Input.touchCount == 0)
|
|
return;
|
|
Touch touch = Input.GetTouch(0);
|
|
if (touch.phase == TouchPhase.Began)
|
|
{
|
|
lastTouchPos = touch.position;
|
|
}
|
|
else if(touch.phase == TouchPhase.Moved)
|
|
{
|
|
Vector3 delta = touch.position - lastTouchPos;
|
|
if (target)
|
|
{
|
|
cameraTransform.RotateAround(target.position, -cameraTransform.right, delta.y * mouseRotSpeed * Time.deltaTime);
|
|
ClampPosFromEulerX();
|
|
|
|
cameraTransform.RotateAround(target.position, Vector3.up, delta.x * mouseRotSpeed * Time.deltaTime);
|
|
ClampPosFromEulerY();
|
|
}
|
|
else
|
|
{
|
|
cameraTransform.Rotate(Vector3.left * delta.y * mouseRotSpeed * Time.deltaTime, Space.Self);
|
|
cameraTransform.Rotate(Vector3.up * delta.x * mouseRotSpeed * Time.deltaTime, Space.World);
|
|
}
|
|
|
|
lastTouchPos = touch.position;
|
|
}
|
|
}
|
|
|
|
void HandleViveInput()
|
|
{
|
|
#if STEAMVR
|
|
Vector2 pressPos = HTC.UnityPlugin.Vive.ViveInput.GetPadPressAxis(viveRoleProperty);
|
|
if(Vector2.Distance(Vector2.zero,pressPos) < 0.01f)
|
|
return;
|
|
//将触摸板位置划分上下左右四块区域
|
|
float angle = Vector2.SignedAngle(Vector2.right, pressPos);
|
|
if (angle > -45 && angle <= 45)
|
|
{
|
|
pressPos = Vector2.right;
|
|
}
|
|
else if(angle > 45 && angle <=135)
|
|
{
|
|
pressPos = Vector2.up;
|
|
}
|
|
else if(angle > 135 || angle < -135)
|
|
{
|
|
pressPos = Vector2.left;
|
|
}
|
|
else
|
|
{
|
|
pressPos = Vector2.down;
|
|
}
|
|
|
|
if (target)
|
|
{
|
|
cameraTransform.RotateAround(target.position, -cameraTransform.right, pressPos.y * viveRotSpeed * Time.deltaTime);
|
|
ClampPosFromEulerX();
|
|
|
|
cameraTransform.RotateAround(target.position, Vector3.up, pressPos.x * viveRotSpeed * Time.deltaTime);
|
|
ClampPosFromEulerY();
|
|
}
|
|
else
|
|
{
|
|
cameraTransform.Rotate(Vector3.left * pressPos.y * viveRotSpeed * Time.deltaTime, Space.Self);
|
|
cameraTransform.Rotate(Vector3.up * pressPos.x * viveRotSpeed * Time.deltaTime, Space.World);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 限制相机旋转角度
|
|
/// </summary>
|
|
void ClampEuler()
|
|
{
|
|
Vector3 euler = VectorTool.ConvertToEuler180(cameraTransform.eulerAngles);
|
|
euler = new Vector3(Mathf.Clamp(euler.x,minEulerX,maxEulerX),Mathf.Clamp(euler.y,minEulerY,maxEulerY),0);
|
|
cameraTransform.eulerAngles = euler;
|
|
}
|
|
|
|
void ClampPosFromEulerX()
|
|
{
|
|
Vector3 euler = VectorTool.ConvertToEuler180(cameraTransform.eulerAngles);
|
|
if (euler.x < minEulerX || euler.x > maxEulerX)
|
|
{
|
|
RestoreCameraTransform();
|
|
}
|
|
}
|
|
|
|
void ClampPosFromEulerY()
|
|
{
|
|
Vector3 euler = VectorTool.ConvertToEuler180(cameraTransform.eulerAngles);
|
|
if (euler.y < minEulerY || euler.y > maxEulerY)
|
|
{
|
|
RestoreCameraTransform();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 限制相机到目标的距离
|
|
/// </summary>
|
|
void ClameDistanceToTarget()
|
|
{
|
|
float distance = Vector3.Distance(cameraTransform.position, target.position);
|
|
if (distance < nearestToTarget || distance > farestToTarget)
|
|
{
|
|
RestoreCameraTransform();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 记录相机的变换信息
|
|
/// </summary>
|
|
void RecordCameraTransform()
|
|
{
|
|
lastCameraPos = cameraTransform.transform.position;
|
|
lastCameraRot = cameraTransform.transform.eulerAngles;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 恢复相机变换到上一帧
|
|
/// </summary>
|
|
void RestoreCameraTransform()
|
|
{
|
|
cameraTransform.position = lastCameraPos;
|
|
cameraTransform.eulerAngles = lastCameraRot;
|
|
}
|
|
}
|
|
}
|
|
|