using System.Collections; using UnityEngine; using UnityEngine.EventSystems; /// /// 摄像机围绕旋转脚本 /// 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.MobileTouch; 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 (CanRotate) { ZoomControl(false); OrbitControl(); } else { ZoomControl(true); } //if (CanRotate && !EventSystem.current.IsPointerOverGameObject()) //{ // ZoomControl(false); // OrbitControl(); //} //else //{ // ZoomControl(true); //} } /// /// 初始化 /// private void Init() { distance = Distance; Vector3 eulerAngles = Transform.eulerAngles; x = eulerAngles.y; y = eulerAngles.x; initXRotation = eulerAngles.y; horizontal = x; vertical = y; } /// /// 旋转控制 /// 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; } } /// /// 距离控制 /// /// private void ZoomControl(bool autoApply) { float delta = Time.deltaTime; distance = Mathf.Clamp(distance - (MouseScrollWheel * scrollSensitivity), distanceClamp.x, distanceClamp.y); // distance = (distance < 1) ? 1 : 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); //target = 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; } } /// /// /// /// public void SetStaticZoom(float value) { distance += value; } /// /// /// public float Horizontal { get { return horizontal; } set { horizontal += value; lastHorizontal = horizontal; } } /// /// /// 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); } }