335 lines
11 KiB
C#
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);
|
|
}
|
|
}
|