123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- using System.Collections.Generic;
- using UnityEngine;
- using DG.Tweening;
- using UnityEngine.EventSystems;
- using UnityEngine.UIElements;
- using QFramework;
- /// <summary>
- /// 漫游视角 相机控制脚本
- /// </summary>
- public class RoamCameraController : MonoSingleton<RoamCameraController>
- {
- /// <summary>
- /// 相机状态类
- /// </summary>
- private class CameraState
- {
- /// <summary>
- /// 坐标x值
- /// </summary>
- public float posX;
- /// <summary>
- /// 坐标y值
- /// </summary>
- public float posY;
- /// <summary>
- /// 坐标z值
- /// </summary>
- public float posZ;
- /// <summary>
- /// 旋转x值
- /// </summary>
- public float rotX;
- /// <summary>
- /// 旋转y值
- /// </summary>
- public float rotY;
- /// <summary>
- /// 旋转z值
- /// </summary>
- public float rotZ;
- //活动区域限制
- private readonly float xMinValue;
- private readonly float xMaxValue;
- private readonly float yMinValue;
- private readonly float yMaxValue;
- private readonly float zMinValue;
- private readonly float zMaxValue;
- /// <summary>
- /// 默认构造函数
- /// </summary>
- public CameraState()
- {
- xMinValue = float.MinValue;
- xMaxValue = float.MaxValue;
- yMinValue = float.MinValue;
- yMaxValue = float.MaxValue;
- zMinValue = float.MinValue;
- zMaxValue = float.MaxValue;
- }
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="xMinValue"></param>
- /// <param name="xMaxValue"></param>
- /// <param name="yMinValue"></param>
- /// <param name="yMaxValue"></param>
- /// <param name="zMinValue"></param>
- /// <param name="zMaxValue"></param>
- public CameraState(float xMinValue, float xMaxValue, float yMinValue, float yMaxValue, float zMinValue, float zMaxValue)
- {
- this.xMinValue = xMinValue;
- this.xMaxValue = xMaxValue;
- this.yMinValue = yMinValue;
- this.yMaxValue = yMaxValue;
- this.zMinValue = zMinValue;
- this.zMaxValue = zMaxValue;
- }
- /// <summary>
- /// 根据Transform组件更新状态
- /// </summary>
- /// <param name="t">Transform组件</param>
- public void SetFromTransform(Transform t)
- {
- posX = t.position.x;
- posY = t.position.y;
- posZ = t.position.z;
- rotX = t.eulerAngles.x;
- rotY = t.eulerAngles.y;
- rotZ = t.eulerAngles.z;
- }
- /// <summary>
- /// 移动
- /// </summary>
- public void Translate(Vector3 translation)
- {
- Vector3 rotatedTranslation = Quaternion.Euler(rotX, rotY, rotZ) * translation;
- posX += rotatedTranslation.x;
- posY += rotatedTranslation.y;
- posZ += rotatedTranslation.z;
- posX = Mathf.Clamp(posX, xMinValue, xMaxValue);
- posY = Mathf.Clamp(posY, yMinValue, yMaxValue);
- posZ = Mathf.Clamp(posZ, zMinValue, zMaxValue);
- }
- /// <summary>
- /// 根据目标状态插值运算
- /// </summary>
- /// <param name="target">目标状态</param>
- /// <param name="positionLerpPct">位置插值率</param>
- /// <param name="rotationLerpPct">旋转插值率</param>
- public void LerpTowards(CameraState target, float positionLerpPct, float rotationLerpPct)
- {
- posX = Mathf.Lerp(posX, target.posX, positionLerpPct);
- posY = Mathf.Lerp(posY, target.posY, positionLerpPct);
- posZ = Mathf.Lerp(posZ, target.posZ, positionLerpPct);
- rotX = Mathf.Lerp(rotX, target.rotX, rotationLerpPct);
- rotY = Mathf.Lerp(rotY, target.rotY, rotationLerpPct);
- rotZ = Mathf.Lerp(rotZ, target.rotZ, rotationLerpPct);
- }
- /// <summary>
- /// 根据状态刷新Transform组件
- /// </summary>
- /// <param name="t">Transform组件</param>
- public void UpdateTransform(Transform t)
- {
- t.position = new Vector3(posX, posY, posZ);
- t.rotation = Quaternion.Euler(rotX, rotY, rotZ);
- }
- }
- #region Private Variables
- //控制开关
- [SerializeField]
- public bool toggle = true;
- //是否限制活动范围
- [SerializeField]
- private bool isRangeClamped;
- //限制范围 当isRangeClamped为true时起作用
- [SerializeField]
- private float xMinValue = -100f; //x最小值
- [SerializeField]
- private float xMaxValue = 100f; //x最大值
- [SerializeField]
- private float yMinValue = 0f; //y最小值
- [SerializeField]
- private float yMaxValue = 100f; //y最大值
- [SerializeField]
- private float zMinValue = -100f; //z最小值
- [SerializeField]
- private float zMaxValue = 100f; //z最大值
- //移动速度
- [SerializeField]
- private float translateSpeed = 10f;
- public float TranslateSpeed
- {
- get { return translateSpeed; }
- set { translateSpeed = value; }
- }
- //加速系数 Shift按下时起作用
- [SerializeField]
- private float boost = 3.5f;
- //插值到目标位置所需的时间
- [Range(0.01f, 1f), SerializeField]
- private float positionLerpTime = 1f;
- //插值到目标旋转所需的时间
- [Range(0.01f, 1f), SerializeField]
- private float rotationLerpTime = 1f;
- //鼠标运动的灵敏度
- [Range(0.1f, 10f), SerializeField]
- private float mouseMovementSensitivity = 1f;
- //鼠标滚轮运动的速度
- [SerializeField]
- private float mouseScrollMoveSpeed = 10f;
- public float MouseScrollMoveSpeed
- {
- get { return mouseMovementSensitivity; }
- set { mouseMovementSensitivity = value; }
- }
- //用于鼠标滚轮移动 是否反转方向
- [SerializeField]
- private bool invertScrollDirection = false;
- //视角旋转是否反转y反向
- [SerializeField]
- private bool invertY = false;
- //用于限制垂直方向上旋转的最大值
- [SerializeField]
- private float verticalLimitMax = 60f;
- //用于限制垂直方向上旋转的最小值
- [SerializeField]
- private float verticalLimitMin = -60f;
- //移动量
- private Vector3 translation = Vector3.zero;
- //Tween动画
- private Tween tween;
- private CameraState initialCameraState;
- private CameraState targetCameraState;
- private CameraState interpolatingCameraState;
- #endregion
- #region Private Methods
- private void Awake()
- {
- //初始化
- if (isRangeClamped)
- {
- initialCameraState = new CameraState(xMinValue, xMaxValue, yMinValue, yMaxValue, zMinValue, zMaxValue);
- targetCameraState = new CameraState(xMinValue, xMaxValue, yMinValue, yMaxValue, zMinValue, zMaxValue);
- interpolatingCameraState = new CameraState(xMinValue, xMaxValue, yMinValue, yMaxValue, zMinValue, zMaxValue);
- }
- else
- {
- initialCameraState = new CameraState();
- targetCameraState = new CameraState();
- interpolatingCameraState = new CameraState();
- }
- interpolatingCameraState.SetFromTransform(transform);
- targetCameraState.SetFromTransform(transform);
- }
- private void OnEnable()
- {
- initialCameraState.SetFromTransform(transform);
- targetCameraState.SetFromTransform(transform);
- interpolatingCameraState.SetFromTransform(transform);
- }
- private void LateUpdate()
- {
- if (!toggle) return;
- //关闭UI移动
- if (EventSystem.current.IsPointerOverGameObject()) return;
- OnRotateUpdate();
- OnTranslateUpdate();
- OnResetUpdate();
- }
- private void OnRotateUpdate()
- {
- #if ENABLE_INPUT_SYSTEM
- bool pressed = Mouse.current.rightButton.isPressed;
- #else
- bool pressed = Input.GetMouseButton(1);
- #endif
- if (pressed)
- {
- #if ENABLE_INPUT_SYSTEM
- Vector2 input = Mouse.current.delta.ReadValue();
- #else
- Vector2 input = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
- #endif
- input.y *= invertY ? 1 : -1;
- //float mouseSensitivityFactor = mouseRotationSensitivityCurve.Evaluate(input.magnitude);
- targetCameraState.rotY += input.x * mouseMovementSensitivity;
- targetCameraState.rotX += input.y * mouseMovementSensitivity;
- targetCameraState.rotX = Mathf.Clamp(targetCameraState.rotX, verticalLimitMin, verticalLimitMax);
- }
- }
- private void OnResetUpdate()
- {
- #if ENABLE_INPUT_SYSTEM
- bool uPressed = Keyboard.current.uKey.wasPressedThisFrame;
- #else
- bool uPressed = Input.GetKeyDown(KeyCode.U);
- #endif
- //U键按下重置到初始状态
- if (uPressed)
- {
- ResetCamera();
- }
- }
- private void OnTranslateUpdate()
- {
- float timeDelatime = 0.02f;
- if (Time.timeScale == 1) timeDelatime = Time.deltaTime;
- translation = GetInputTranslation() * timeDelatime * translateSpeed;
- targetCameraState.Translate(translation);
- float positionLerpPct = 1f - Mathf.Exp(Mathf.Log(1f - .99f) / positionLerpTime * timeDelatime);
- float rotationLerpPct = 1f - Mathf.Exp(Mathf.Log(1f - .99f) / rotationLerpTime * timeDelatime);
- interpolatingCameraState.LerpTowards(targetCameraState, positionLerpPct, rotationLerpPct);
- interpolatingCameraState.UpdateTransform(transform);
- }
- //移动启动时间
- private float MoveKeyStartLerp;
- //获取输入
- private Vector3 GetInputTranslation()
- {
- Vector3 ts = new Vector3();
- //键盘W、A、S、D、Q、E控制运动方向
- #if ENABLE_INPUT_SYSTEM
- if (Keyboard.current.wKey.isPressed) ts += Vector3.forward;
- if (Keyboard.current.sKey.isPressed) ts += Vector3.back;
- if (Keyboard.current.aKey.isPressed) ts += Vector3.left;
- if (Keyboard.current.dKey.isPressed) ts += Vector3.right;
- if (Keyboard.current.qKey.isPressed) ts += Vector3.down;
- if (Keyboard.current.eKey.isPressed) ts += Vector3.up;
- #else
- //初始按键移动的时候移动速度渐增
- if (!Input.GetKey(KeyCode.W)
- && !Input.GetKey(KeyCode.S)
- && !Input.GetKey(KeyCode.A)
- && !Input.GetKey(KeyCode.D)
- && !Input.GetKey(KeyCode.Q)
- && !Input.GetKey(KeyCode.E))
- MoveKeyStartLerp = 0;
- if (Input.GetKey(KeyCode.W)
- || Input.GetKey(KeyCode.S)
- || Input.GetKey(KeyCode.A)
- || Input.GetKey(KeyCode.D)
- || Input.GetKey(KeyCode.Q)
- || Input.GetKey(KeyCode.E))
- {
- MoveKeyStartLerp += Time.deltaTime/2;
- MoveKeyStartLerp = Mathf.Clamp(MoveKeyStartLerp, 0, 1);
- }
- if (Input.GetKey(KeyCode.W)) ts += Vector3.forward;
- if (Input.GetKey(KeyCode.S)) ts += Vector3.back;
- if (Input.GetKey(KeyCode.A)) ts += Vector3.left;
- if (Input.GetKey(KeyCode.D)) ts += Vector3.right;
- if (Input.GetKey(KeyCode.Q)) ts += Vector3.down;
- if (Input.GetKey(KeyCode.E)) ts += Vector3.up;
- ts = ts * MoveKeyStartLerp;
- #endif
- #if ENABLE_INPUT_SYSTEM
- //读取鼠标滚轮滚动值
- float wheelValue = Mouse.current.scroll.ReadValue().y;
- #else
- float wheelValue = Input.GetAxis("Mouse ScrollWheel");
- #endif
- ts += (wheelValue == 0
- ? Vector3.zero
- : (wheelValue > 0 ? Vector3.forward : Vector3.back) * (invertScrollDirection ? -1 : 1)) * mouseScrollMoveSpeed;
- #if ENABLE_INPUT_SYSTEM
- //左Shift键按下时加速
- if (Keyboard.current.leftShiftKey.isPressed) ts *= boost;
- #elif ENABLE_INPUT_SYSTEM
- if (Input.GetKey(KeyCode.LeftShift)) ts *= boost;
- #else
- if (Input.GetMouseButton(2))
- {
- ts.y = -Input.GetAxis("Mouse Y");
- ts.x = -Input.GetAxis("Mouse X");
- }
- #endif
- return ts;
- }
- #if UNITY_EDITOR
- private void OnDrawGizmos()
- {
- //如果限制活动范围 将区域范围绘制出来
- if (isRangeClamped)
- {
- Gizmos.color = Color.red;
- Vector3[] points = new Vector3[8]
- {
- new Vector3(xMinValue, yMinValue, zMinValue),
- new Vector3(xMaxValue, yMinValue, zMinValue),
- new Vector3(xMaxValue, yMinValue, zMaxValue),
- new Vector3(xMinValue, yMinValue, zMaxValue),
- new Vector3(xMinValue, yMaxValue, zMinValue),
- new Vector3(xMaxValue, yMaxValue, zMinValue),
- new Vector3(xMaxValue, yMaxValue, zMaxValue),
- new Vector3(xMinValue, yMaxValue, zMaxValue)
- };
- for (int i = 0; i < 4; i++)
- {
- int start = i % 4;
- int end = (i + 1) % 4;
- Gizmos.DrawLine(points[start], points[end]);
- Gizmos.DrawLine(points[start + 4], points[end + 4]);
- Gizmos.DrawLine(points[start], points[i + 4]);
- }
- }
- }
- #endif
- #endregion
- #region Public Methods
- /// <summary>
- /// 设置相机可移动与否
- /// </summary>
- /// <param name="state"></param>
- public void SetCameraMoveState(bool state)
- {
- if (state)
- {
- interpolatingCameraState.SetFromTransform(transform);
- targetCameraState.SetFromTransform(transform);
- }
- toggle = state;
- }
- /// <summary>
- /// 重置摄像机到初始状态
- /// </summary>
- public void ResetCamera()
- {
- initialCameraState.UpdateTransform(transform);
- targetCameraState.SetFromTransform(transform);
- interpolatingCameraState.SetFromTransform(transform);
- }
- /// <summary>
- /// 聚焦
- /// </summary>
- /// <param name="position">目标位置</param>
- /// <param name="rotation">目标旋转</param>
- /// <param name="duration">时长</param>
- public void Focus(Vector3 position, Vector3 rotation, float duration, bool _toggle = true)
- {
- tween?.Kill();
- toggle = false;
- transform.DORotate(rotation, duration);
- tween = transform.DOMove(position, duration).Play()
- .OnKill(() =>
- {
- if (UIKit.GetPanel<CameraPoseSetPanel>())
- {
- toggle = true;
- }
- else
- {
- toggle = _toggle;
- }
- interpolatingCameraState.SetFromTransform(transform);
- targetCameraState.SetFromTransform(transform);
- tween = null;
- });
- }
- public void SetCameraState(Vector3 position, Vector3 rotation)
- {
- if (position == Vector3.zero) return;
- transform.eulerAngles = rotation;
- transform.position = position;
- interpolatingCameraState.SetFromTransform(transform);
- targetCameraState.SetFromTransform(transform);
- }
- public void ChangeIsRangeClamped()
- {
- isRangeClamped = !isRangeClamped;
- }
- #endregion
- }
|