330 lines
11 KiB
C#
330 lines
11 KiB
C#
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 Yarn.Unity;
|
|
|
|
namespace AibisDream.Framework
|
|
{
|
|
public class CameraKit : SingletonBase<CameraKit>
|
|
{
|
|
private const int LowPriority = 1;
|
|
private const int HighPriority = 10;
|
|
|
|
#region 相机组件
|
|
|
|
private static Camera _mainCam;
|
|
|
|
private CinemachineBrain _orthoCameraBrain;
|
|
private CinemachineBrain _perspectiveCameraBrain;
|
|
private readonly Dictionary<CameraEnum, ICinemachineCamera> _virtualCameraDict = new();
|
|
private readonly Dictionary<CameraEnum, CamState> _camInitStateDict = new();
|
|
|
|
private CameraEnum _curCameraEnum;
|
|
private CamState _curInitState;
|
|
private Camera _orthoMainCamera;
|
|
private Camera _perspectiveMainCamera;
|
|
|
|
private struct CamState
|
|
{
|
|
public Vector3 pos;
|
|
public float initOrthoSize;
|
|
public bool isPerspective;
|
|
}
|
|
|
|
#endregion
|
|
|
|
private CameraKit()
|
|
{
|
|
}
|
|
|
|
public override void OnSingletonInit()
|
|
{
|
|
// 获取正交相机
|
|
_orthoMainCamera = Camera.main;
|
|
_orthoCameraBrain = _orthoMainCamera?.GetComponent<CinemachineBrain>();
|
|
|
|
// 获取透视相机
|
|
_perspectiveMainCamera = GameObject.Find("PerspectiveMainCamera")?.GetComponent<Camera>();
|
|
_perspectiveCameraBrain = _perspectiveMainCamera?.GetComponent<CinemachineBrain>();
|
|
|
|
_curCameraEnum = CameraEnum.Default;
|
|
|
|
if (_orthoMainCamera && _perspectiveMainCamera)
|
|
{
|
|
// 默认激活正交相机,禁用透视相机
|
|
_orthoMainCamera.gameObject.SetActive(true);
|
|
_perspectiveMainCamera.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
#region 相机信息注册
|
|
|
|
public void RegisterCamera(CameraEnum camType, ICinemachineCamera virtualCamera, bool isPerspective = false)
|
|
{
|
|
_virtualCameraDict[camType] = virtualCamera;
|
|
|
|
var initState = new CamState
|
|
{
|
|
pos = virtualCamera.VirtualCameraGameObject.transform.localPosition,
|
|
initOrthoSize = virtualCamera.VirtualCameraGameObject.gameObject
|
|
.GetComponent<CinemachineVirtualCamera>().m_Lens.OrthographicSize,
|
|
isPerspective = isPerspective
|
|
};
|
|
_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
|
|
|
|
/// <summary>
|
|
/// 检查当前是否需要切相机
|
|
/// </summary>
|
|
/// <param name="targetCameraState"></param>
|
|
/// <returns>是就不用切相机</returns>
|
|
public bool EqualToCameraState(CameraEnum targetCameraState)
|
|
{
|
|
return _curCameraEnum == targetCameraState;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 切换相机
|
|
/// </summary>
|
|
/// <param name="camType"></param>
|
|
public IEnumerator SwitchCamera(CameraEnum camType)
|
|
{
|
|
var switchDuration = SwitchCameraSync(camType);
|
|
yield return new WaitForSeconds(switchDuration);
|
|
}
|
|
|
|
public float SwitchCameraSync(CameraEnum camType)
|
|
{
|
|
Debug.Log("Camera Type is:" + camType);
|
|
if (_curCameraEnum == camType)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (!_virtualCameraDict.ContainsKey(camType))
|
|
{
|
|
Debug.Log($"{camType.ToString()}相机未注册");
|
|
return 0;
|
|
}
|
|
|
|
// 切换主相机
|
|
bool isPerspective = _camInitStateDict[camType].isPerspective;
|
|
_orthoMainCamera.gameObject.SetActive(!isPerspective);
|
|
// _perspectiveMainCamera.gameObject.SetActive(isPerspective);
|
|
var activeBrain = isPerspective ? _perspectiveCameraBrain : _orthoCameraBrain;
|
|
|
|
// 设置虚拟相机优先级
|
|
foreach (var camPair in _virtualCameraDict)
|
|
{
|
|
if (camPair.Key == camType) camPair.Value.Priority = HighPriority;
|
|
if (camPair.Key != camType) camPair.Value.Priority = LowPriority;
|
|
}
|
|
|
|
_curInitState = _camInitStateDict[camType];
|
|
var lastCamEnum = _curCameraEnum;
|
|
_curCameraEnum = camType;
|
|
|
|
// 切完之后记得复原
|
|
ActionKit.Delay(activeBrain.m_DefaultBlend.BlendTime, () => ResetVirCam(lastCamEnum)).StartGlobal();
|
|
|
|
return activeBrain.m_DefaultBlend.BlendTime;
|
|
}
|
|
|
|
private void ResetVirCam(CameraEnum cameraEnum)
|
|
{
|
|
if (cameraEnum == CameraEnum.Default)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var virCam = _virtualCameraDict[cameraEnum];
|
|
var camState = _camInitStateDict[cameraEnum];
|
|
virCam.VirtualCameraGameObject.transform.localPosition = camState.pos;
|
|
var camObj = virCam.VirtualCameraGameObject.GetComponent<CinemachineVirtualCamera>();
|
|
camObj.m_Lens.OrthographicSize = camState.initOrthoSize;
|
|
}
|
|
|
|
public Tween TransCamera(Vector3 targetPos, float targetOrthographicSize, float duration)
|
|
{
|
|
// 寻找现在正在激活的相机
|
|
var curCamera = _orthoCameraBrain.ActiveVirtualCamera;
|
|
|
|
var sq = DOTween.Sequence();
|
|
// 移动
|
|
sq.Join(curCamera.DOLocalMove(targetPos, duration));
|
|
// 缩放
|
|
sq.Join(curCamera.DOOrthoSize(targetOrthographicSize, duration));
|
|
|
|
return sq;
|
|
}
|
|
|
|
private Tween ReturnInitCamera(float duration)
|
|
{
|
|
return TransCamera(_curInitState.pos, _curInitState.initOrthoSize, duration);
|
|
}
|
|
|
|
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 = _orthoCameraBrain.ActiveVirtualCamera;
|
|
yield return curCamera.VirtualCameraGameObject.transform
|
|
.DOShakePosition(duration, strength, vibrate, 90, false, false)
|
|
.WaitForCompletion();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取当前激活的相机
|
|
/// </summary>
|
|
public Camera GetCurrentCamera()
|
|
{
|
|
return _camInitStateDict.TryGetValue(_curCameraEnum, out var state) && state.isPerspective ?
|
|
_perspectiveMainCamera :
|
|
_orthoMainCamera;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取鼠标在世界中的位置
|
|
/// </summary>
|
|
/// <param name="mousePoint">鼠标界面位置</param>
|
|
/// <returns>世界位置</returns>
|
|
public static Vector3 GetMouseWorldPos(Vector3 mousePoint)
|
|
{
|
|
if (!_mainCam) _mainCam = Camera.main;
|
|
|
|
return _mainCam.ScreenToWorldPoint(mousePoint);
|
|
}
|
|
|
|
public static Vector3 GetScreenPos(Vector3 worldPos)
|
|
{
|
|
if (!_mainCam) _mainCam = Camera.main;
|
|
|
|
worldPos.z = 0;
|
|
return _mainCam.WorldToScreenPoint(worldPos);
|
|
}
|
|
}
|
|
|
|
public static class CinemachineExtension
|
|
{
|
|
public static TweenerCore<Vector3, Vector3, VectorOptions> DOLocalMove(this ICinemachineCamera camera,
|
|
Vector3 targetPos, float duration)
|
|
{
|
|
var transform = camera.VirtualCameraGameObject.gameObject.transform;
|
|
return transform.DOLocalMove(targetPos, duration);
|
|
}
|
|
|
|
public static TweenerCore<float, float, FloatOptions> DOOrthoSize(this ICinemachineCamera camera,
|
|
float endValue, float duration)
|
|
{
|
|
var virtualCamera = camera.VirtualCameraGameObject.GetComponent<CinemachineVirtualCamera>();
|
|
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("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<CameraEnum>(targetStateStr, out var targetState))
|
|
{
|
|
Debug.Log($"{targetStateStr}不在FixState枚举中");
|
|
yield break;
|
|
}
|
|
|
|
yield return CameraKit.Instance.SwitchCamera(targetState);
|
|
}
|
|
}
|
|
|
|
public enum CameraEnum
|
|
{
|
|
Default,
|
|
Clinic,
|
|
CoolingMachine,
|
|
BodyModule,
|
|
BodyModuleCenter,
|
|
Memory,
|
|
Logic,
|
|
Eye,
|
|
UF,
|
|
Expression,
|
|
Engine,
|
|
Gear,
|
|
EyeDeep,
|
|
ExpressionDeep,
|
|
Emo,
|
|
EmoDeep,
|
|
Op,
|
|
CutEmo,
|
|
CutMemory,
|
|
CutLogic,
|
|
CutEmoDeep,
|
|
CutMemoryDeep,
|
|
CutLogicDeep,
|
|
BreakCamera,
|
|
DreamCamera,
|
|
}
|
|
} |