using System; using System.Collections; using System.Collections.Generic; using AibisDream.Kit; using Cinemachine; using DG.Tweening; using DG.Tweening.Core; using DG.Tweening.Plugins.Options; using UnityEngine; using UnityEngine.Rendering.Universal; using Yarn.Unity; namespace AibisDream.Framework { public class CameraKit : SingletonBase { private const int LowPriority = 1; private const int HighPriority = 10; #region 相机组件 private CinemachineBrain _cameraBrain; private readonly Dictionary _virtualCameraDict = new(); private readonly Dictionary _camInitStateDict = new(); private CameraEnum _curCameraEnum; private CamState _curInitState; public Camera uiCamera; private struct CamState { public Vector3 pos; public float initOrthoSize; } #endregion private CameraKit() { } public override void OnSingletonInit() { _cameraBrain = Camera.main?.GetComponent(); _curCameraEnum = CameraEnum.Default; // 获取UICamera if (Camera.main && Camera.main.TryGetComponent(out var cameraData)) { // 获取Stack Cameras var stackCameras = cameraData.cameraStack; // 获取UICamera uiCamera = stackCameras.Find(cam => cam && cam.name == "UI Camera"); } } #region 相机信息注册 /// /// 添加UI相机 /// public void AddUICamera(Camera camera) { if (Camera.main && Camera.main.TryGetComponent(out var cameraData)) { cameraData.cameraStack.Add(camera); } } public void RemoveUICamera(Camera camera) { if (Camera.main && Camera.main.TryGetComponent(out var cameraData)) { cameraData.cameraStack.Remove(camera); } } public void RegisterCamera(CameraEnum camType, ICinemachineCamera virtualCamera) { _virtualCameraDict[camType] = virtualCamera; var initState = new CamState { pos = virtualCamera.VirtualCameraGameObject.transform.localPosition, initOrthoSize = virtualCamera.VirtualCameraGameObject.gameObject .GetComponent().m_Lens.OrthographicSize }; _camInitStateDict[camType] = initState; } public void UnRegisterCamera(CameraEnum camType, ICinemachineCamera virtualCamera) { if (!_virtualCameraDict.TryGetValue(camType, out var curCam)) return; if (virtualCamera == curCam) { _virtualCameraDict.Remove(camType); _camInitStateDict.Remove(camType); } } public void UnRegisterCamera(CameraEnum camType) { _virtualCameraDict.Remove(camType); _camInitStateDict.Remove(camType); } public void RemoveAllCam() { _virtualCameraDict.Clear(); _camInitStateDict.Clear(); } #endregion /// /// 检查当前是否需要切相机 /// /// /// 是就不用切相机 public bool EqualToCameraState(CameraEnum targetCameraState) { return _curCameraEnum == targetCameraState; } /// /// 切换相机 /// /// public IEnumerator SwitchCamera(CameraEnum camType) { Debug.Log("Camera Type is:"+camType); if (_curCameraEnum == camType) { yield break; } if (!_virtualCameraDict.ContainsKey(camType)) { Debug.Log($"{camType.ToString()}相机未注册"); yield break; } foreach (var camPair in _virtualCameraDict) { if (camPair.Key == camType) camPair.Value.Priority = HighPriority; if (camPair.Key != camType) camPair.Value.Priority = LowPriority; } _curInitState = _camInitStateDict[camType]; yield return new WaitForSeconds(_cameraBrain.m_DefaultBlend.BlendTime); } public Tween TransCamera(Vector3 targetPos, float targetOrthographicSize, float duration) { // 寻找现在正在激活的相机 var curCamera = _cameraBrain.ActiveVirtualCamera; var sq = DOTween.Sequence(); // 移动 sq.Join(curCamera.DOLocalMove(targetPos, duration)); // 缩放 sq.Join(curCamera.DOOrthoSize(targetOrthographicSize, duration)); return sq; } public Tween ReturnInitCamera(float duration) { return TransCamera(_curInitState.pos, _curInitState.initOrthoSize, duration); } public IEnumerator TransCameraAsync(Vector3 targetPos, float duration) { var curCamera = _cameraBrain.ActiveVirtualCamera; yield return curCamera.DOLocalMove(targetPos, duration).WaitForCompletion(); } public IEnumerator TransCameraAsync(Vector3 targetPos, float targetOrthographicSize, float duration) { yield return TransCamera(targetPos, targetOrthographicSize, duration).WaitForCompletion(); } public IEnumerator ReturnInitCameraAsync(float duration) { yield return ReturnInitCamera(duration).WaitForCompletion(); } // 方法已废弃,后面改成用Cinemachine的Shake [Obsolete] public IEnumerator ShakeCamera(float duration, float strength, int vibrate) { var curCamera = _cameraBrain.ActiveVirtualCamera; yield return curCamera.VirtualCameraGameObject.transform .DOShakePosition(duration, strength, vibrate, 90, false, false) .WaitForCompletion(); } } public static class CinemachineExtension { public static TweenerCore DOLocalMove(this ICinemachineCamera camera, Vector3 targetPos, float duration) { var transform = camera.VirtualCameraGameObject.gameObject.transform; return transform.DOLocalMove(targetPos, duration); } public static TweenerCore DOOrthoSize(this ICinemachineCamera camera, float endValue, float duration) { var virtualCamera = camera.VirtualCameraGameObject.gameObject.GetComponent(); var currentOrthoSize = virtualCamera.m_Lens.OrthographicSize; return DOTween.To(() => currentOrthoSize, x => currentOrthoSize = x, endValue, duration) .OnUpdate(() => virtualCamera.m_Lens.OrthographicSize = currentOrthoSize); } } public static class CameraCommand { [YarnCommand("return_init_camera")] public static IEnumerator ReturnInitCamera(float duration = 1f) { return CameraKit.Instance.ReturnInitCameraAsync(duration); } [YarnCommand("trans_camera")] public static IEnumerator TransCameraAsync(float x, float y, float targetOrthographicSize, float duration) { Vector3 targetPos = new Vector3(x, y, -10); return CameraKit.Instance.TransCameraAsync(targetPos, targetOrthographicSize, duration); } [YarnCommand("trans_camera_pos")] public static IEnumerator TransCameraAsync(float x, float y, float duration) { Vector3 targetPos = new Vector3(x, y, -10); return CameraKit.Instance.TransCameraAsync(targetPos, duration); } [YarnCommand("shake_camera")] public static IEnumerator ShakeCamera(float duration, float strength, int vibrate = 10) { return CameraKit.Instance.ShakeCamera(duration, strength, vibrate); } [YarnCommand("switch_camera")] public static IEnumerator SwitchCamera(string targetStateStr) { // 字符串转枚举 if (!Enum.TryParse(targetStateStr, out var targetState)) { Debug.Log($"{targetStateStr}不在FixState枚举中"); yield break; } yield return CameraKit.Instance.SwitchCamera(targetState); } } public enum CameraEnum { Default, Clinic, CoolingMachine, BodyModule, Memory, Eye, UF, Expression, Engine, Gear, EyeDeep, } }