TaiZhouCangChu_VRanime/Assets/GameAssets/Camera Orbit/Scripts/CameraOrbit.cs

335 lines
11 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// 摄像机围绕旋转脚本
/// </summary>
public class CameraOrbit : CameraBase
{
[Header("开关")]
[Tooltip("是否可控.关闭则无法控制摄像机")]
public bool controlable = true;
[Tooltip("观察的目标")]
public Transform target;
[Tooltip("摄像机与目标之间的距离")]
public float Distance = 5f;
[Header("限制")]
[Tooltip("摄像机与目标之间的距离限制")]
public Vector2 distanceClamp = new Vector2(1.5f, 5);
public Vector2 yLimitClamp = new Vector2(-20, 80);
public Vector2 xLimitClamp = new Vector2(360, 360);
public Vector2 speedAxis = new Vector2(100, 100);
[Header("控制参数")]
[Tooltip("鼠标滚轮灵敏度")]
[Range(1, 10)]
public float scrollSensitivity = 5;
[Range(1, 25)]
public float zoomSpeed = 7;
[Range(1, 25)]
public float lerpSpeed = 7;
[Range(0.1f, 15)]
public float inputLerp = 7;
[Range(0.001f, 0.07f)]
public float inputMultiplier = 0.02f;
[Tooltip("切换目标时黑屏时间")]
[Range(0.01f, 5f)]
public float swichtSpeed = 2;
[Header("Movement")]
public CameraMovementType movementType = CameraMovementType.Normal;
public CameraMouseInputType rotateInputKey = CameraMouseInputType.RightMouse;
private float x, y;
private float horizontal;
private float vertical;
private float lastHorizontal = 0;
private float distance = 0;
private Vector3 zoomVector;
private Vector3 currentPosition;
private Quaternion currentRotation;
private float initXRotation;
private bool isSwitchingTarget = false;
private float fadeAlpha = 0;
[SerializeField]
private Texture2D fadeTexture = null;
public bool Controlable
{
get { return controlable; }
set { controlable = value; }
}
public bool CanRotate { get; set; } = true;
private void Start()
{
Init();
}
private void LateUpdate()
{
if (target == null)
{
Debug.LogWarning("Target is not assigned to orbit camera!", this);
return;
}
if (isSwitchingTarget)
return;
if (EventSystem.current.currentSelectedGameObject && EventSystem.current.currentSelectedGameObject.name.Equals("mask"))
{
}
if (CanRotate)
{
ZoomControl(false);
OrbitControl();
}
else
{
ZoomControl(true);
}
}
/// <summary>
/// 初始化
/// </summary>
private void Init()
{
distance = Distance;
Vector3 eulerAngles = Transform.eulerAngles;
x = eulerAngles.y;
y = eulerAngles.x;
initXRotation = eulerAngles.y;
horizontal = x;
vertical = y;
}
/// <summary>
/// 旋转控制
/// </summary>
private void OrbitControl()
{
if (controlable)
{
if (IsInputKeyRotate)
{
horizontal += (speedAxis.x * inputMultiplier) * AxisX;
vertical -= (speedAxis.y * inputMultiplier) * AxisY;
lastHorizontal = AxisX;
}
}
float delta = Time.deltaTime;
vertical = MathfUtils.ClampAngle(vertical, yLimitClamp.x, yLimitClamp.y);
if (xLimitClamp.x < 360 && yLimitClamp.y < 360)
{
horizontal = MathfUtils.ClampAngle(horizontal, (initXRotation - xLimitClamp.y), (xLimitClamp.x + initXRotation));
}
x = Mathf.Lerp(x, horizontal, Time.deltaTime * inputLerp);
y = Mathf.Lerp(y, vertical, Time.deltaTime * inputLerp);
y = MathfUtils.ClampAngle(y, yLimitClamp.x, yLimitClamp.y);
currentRotation = Quaternion.Euler(y, x, 0f);
currentPosition = ((currentRotation * zoomVector)) + target.position;
switch (movementType)
{
case CameraMovementType.Dynamic:
Transform.position = Vector3.Lerp(Transform.position, currentPosition, (lerpSpeed) * delta);
Transform.rotation = Quaternion.Lerp(Transform.rotation, currentRotation, (lerpSpeed * 2) * delta);
break;
case CameraMovementType.Normal:
Transform.position = currentPosition;
Transform.rotation = currentRotation;
break;
case CameraMovementType.Towars:
Transform.position = Vector3.MoveTowards(Transform.position, currentPosition, lerpSpeed);
Transform.rotation = Quaternion.RotateTowards(Transform.rotation, currentRotation, lerpSpeed);
break;
}
}
/// <summary>
/// 距离控制
/// </summary>
/// <param name="autoApply"></param>
private void ZoomControl(bool autoApply)
{
float delta = Time.deltaTime;
distance = Mathf.Clamp(distance - (MouseScrollWheel * scrollSensitivity), distanceClamp.x, distanceClamp.y);
distance = (distance < 0.1f) ? .1f : distance;
Distance = Mathf.SmoothStep(Distance, distance, delta * zoomSpeed);
zoomVector = new Vector3(0, 0, -Distance);
if (autoApply)
{
currentPosition = (currentRotation * zoomVector) + target.position;
switch (movementType)
{
case CameraMovementType.Dynamic:
Transform.position = Vector3.Lerp(Transform.position, currentPosition, (lerpSpeed) * delta);
Transform.rotation = Quaternion.Lerp(Transform.rotation, currentRotation, (lerpSpeed * 2) * delta);
break;
case CameraMovementType.Normal:
Transform.position = currentPosition;
Transform.rotation = currentRotation;
break;
case CameraMovementType.Towars:
Transform.position = Vector3.MoveTowards(Transform.position, currentPosition, lerpSpeed);
Transform.rotation = Quaternion.RotateTowards(Transform.rotation, currentRotation, lerpSpeed);
break;
}
}
}
private bool IsInputKeyRotate
{
get
{
switch (rotateInputKey)
{
case CameraMouseInputType.All:
return (Input.GetKey(KeyCode.Mouse0) || Input.GetKey(KeyCode.Mouse1) || Input.GetKey(KeyCode.Mouse2) || Input.GetMouseButton(0));
case CameraMouseInputType.LeftAndRight:
return (Input.GetKey(KeyCode.Mouse0) || Input.GetKey(KeyCode.Mouse1));
case CameraMouseInputType.LeftMouse:
return (Input.GetKey(KeyCode.Mouse0));
case CameraMouseInputType.RightMouse:
return (Input.GetKey(KeyCode.Mouse1));
case CameraMouseInputType.MouseScroll:
return (Input.GetKey(KeyCode.Mouse2));
case CameraMouseInputType.MobileTouch:
return (Input.GetMouseButton(0) || Input.GetMouseButton(1));
default:
return (Input.GetKey(KeyCode.Mouse0));
}
}
}
public void SetTarget(Transform newTarget)
{
StopCoroutine("TranslateTarget");
StartCoroutine("TranslateTarget", newTarget);
}
IEnumerator TranslateTarget(Transform newTarget)
{
isSwitchingTarget = true;
while (fadeAlpha < 1)
{
transform.position = Vector3.Lerp(transform.position, transform.position + new Vector3(0, 2, -2), Time.deltaTime);
fadeAlpha += Time.smoothDeltaTime * swichtSpeed;
yield return null;
}
target = newTarget;
isSwitchingTarget = false;
while (fadeAlpha > 0)
{
fadeAlpha -= Time.smoothDeltaTime * swichtSpeed;
yield return null;
}
}
public void SetViewPoint(int side)
{
if (side == 0)//top
{
vertical = 90;
horizontal = 0;
}
else if (side == 1)//front
{
vertical = 0;
horizontal = 0;
}
else if (side == 2)//right
{
vertical = 0;
horizontal = -90;
}
else if (side == 3)//left
{
vertical = 0;
horizontal = 90;
}
else if (side == 4)//back
{
vertical = 0;
horizontal = 180;
}
else if (side == 5)//
{
vertical = 0;
horizontal = -45;
}
else if (side == 6)//
{
vertical = 0;
horizontal = 45;
}
else if (side == 7)//
{
vertical = 0;
horizontal = 135;
}
else if (side == 8)//
{
vertical = 0;
horizontal = -135;
}
}
/// <summary>
///
/// </summary>
/// <param name="value"></param>
public void SetStaticZoom(float value)
{
distance += value;
}
/// <summary>
///
/// </summary>
public float Horizontal
{
get
{
return horizontal;
}
set
{
horizontal += value;
lastHorizontal = horizontal;
}
}
public void SetPos(float horizontal_, float vertical_, float distance_,Vector3 targetpos)
{
horizontal = horizontal_;
vertical = vertical_;
distance = distance_;
GetComponent<CameraOrbit>().enabled = true;
target.position = targetpos;
}
/// <summary>
///
/// </summary>
public float Vertical
{
get
{
return vertical;
}
set
{
vertical += value;
}
}
private void OnGUI()
{
if (isSwitchingTarget)
{
GUI.color = new Color(1, 1, 1, fadeAlpha);
if (fadeTexture != null)
GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), fadeTexture, ScaleMode.StretchToFill);
return;
}
}
void OnDrawGizmosSelected()
{
Gizmos.color = new Color32(0, 221, 221, 255);
if (target != null)
{
Gizmos.DrawLine(transform.position, target.position);
Gizmos.matrix = Matrix4x4.TRS(target.position, transform.rotation, new Vector3(1f, 0, 1f));
Gizmos.DrawWireSphere(target.position, Distance);
Gizmos.matrix = Matrix4x4.identity;
}
Gizmos.DrawCube(transform.position, new Vector3(1, 0.2f, 0.2f));
Gizmos.DrawCube(transform.position, Vector3.one / 2);
}
}