Files
JJBB/Assets/Project/Script/Player/Controller/CameraController.cs

1087 lines
38 KiB
C#
Raw Normal View History

2024-08-23 15:49:34 +08:00
/********************************************************************************
* CameraController.cs
* \Script\Player\CameraController.cs
*
* 2013-11-05
*
*
*
*
*
*********************************************************************************/
using Games.Events;
using Games.GlobeDefine;
using Games.LogicObj;
using GCGame.Table;
using Module.Log;
using System.Collections.Generic;
using Games.Scene;
using UnityEngine;
using UnityEngine.Events;
public sealed class CameraController : MonoBehaviour
{
// ******** 基础参数 ********
public const string cameraIgnoreLayer = "MainCameraIgnore";
public const string skyBoxLayer = "Skybox";
public static readonly string[] hideFromCameraLayers = { "UICameraTexture", "UI","MapPoint", cameraIgnoreLayer };
public Camera MainCamera { get; private set; }
public Camera OverrideCamera { get; private set; }
private readonly List<MonoBehaviour> _cameraEffectList = new List<MonoBehaviour>();
private Animation _animation;
private string _shakeAnimName;
// 暂时使用掩码处理多重动态雾效关闭的条件
private static int _forceNoFog;
// 隐藏摄像机的多重掩码0为EnableCamera1为UiCopyCamera2为SceneMovie3为OverrideCamera, 4为过场动画
private int _hideCamera;
public static bool UseDepthTexture
{
get { return _useDepthTexture; }
set
{
if (_useDepthTexture != value)
{
_useDepthTexture = value;
if (SceneLogic.CameraController != null)
SceneLogic.CameraController.ToggleDepthTexture();
}
}
}
private static bool _useDepthTexture = true;
private CameraLowRes _cameraLowRes;
private bool _fruntumDirty;
private Plane[] _fruntumPlanes;
// ******** 基础移动参数 ********
// 默认摄像机焦点偏移数值
public static readonly Vector3 defaultOffset = Vector3.up * 0.9f;
// 默认摄像机剔除距离
public const float cameraCullDistance = 45f;
public const float skyBoxCullDistance = 1000f;
// 同当前锁定目标的距离
public float Distance { get; set; }
// 摄像机仰角和水平方向。不考虑
public float Pitch { get; set; }
public float Yaw { get; set; }
// FieldOfView调整
public float FoVMin { get; private set; }
public float FoVMax { get; private set; }
private float _fovScale;
public float FoVScale
{
get { return _fovScale; }
set
{
if (_fovScale != value)
{
_fovScale = value;
UpdateFoV();
}
}
}
// 摄像机就不做多个Override的排序处理了
private float _fovOverride = -1f;
public float FoVOverride
{
get { return _fovOverride; }
set
{
if (_fovOverride != value)
{
_fovOverride = value;
UpdateFoV();
}
}
}
private float _fovValue = -1f;
public float FoVValue
{
get { return _fovValue; }
set
{
if (_fovValue != value)
{
_fovValue = value;
UpdateFoV();
}
}
}
private bool _noCullByDist;
private void UpdateFoV()
{
if (_fovValue > 0)
{
MainCamera.fieldOfView = _fovValue;
}
else
{
var fovScale = _fovOverride < 0 ? _fovScale : _fovOverride;
MainCamera.fieldOfView = Mathf.Lerp(FoVMin, FoVMax, fovScale);
}
}
// 当前锁定目标为空时视为锁定在Vector3.zero位置
private Transform FocusObj { get; set; }
// 当前目标丢失时自动锁定到的目标GUID
public ulong FocusObjGuid { get; private set; }
// 当前锁定目标点偏移值
public Vector3 FocusOffset { get; private set; }
// 当前摄像同锁定目标高度偏移值,锁定目标丢失时,保持最后一次赋值
public float CameraHeight { get; private set; }
// ******** 震屏参数 ********
// 处于delay阶段的震屏表
private readonly List<CameraShakeData> _delayShakeData = new List<CameraShakeData>();
private readonly List<CameraShakeData> _activeShakeData = new List<CameraShakeData>();
private CameraShakeData _currentShake;
private readonly List<CameraShakeTableData> _cameraShakeData = new List<CameraShakeTableData>();
// ******** 运动覆盖参数 ********
public CameraMovementOverrider MoveOverrider { get; private set; }
public void ChangeFocusObj(Obj obj)
{
if (obj == null)
{
FocusObj = null;
FocusObjGuid = GlobeVar.INVALID_GUID;
EventDispatcher.Instance.SendMessage(Games.Events.EventId.MainCameraFocusValid);
}
else
{
FocusObj = obj.transform;
FocusObjGuid = obj.GUID;
}
}
public bool IsCurrFocus(Obj obj)
{
if (FocusObj == null || obj == null)
return false;
else
return obj.transform == FocusObj;
}
public T AddCameraEffect<T>(UnityAction<T> createFunc = null) where T : MonoBehaviour
{
T result = null;
for (var i = 0; i < _cameraEffectList.Count; i++)
{
var effect = _cameraEffectList[i] as T;
if (effect != null)
{
result = effect;
result.enabled = true;
}
else
_cameraEffectList[i].enabled = false;
}
if (result == null)
{
result = MainCamera.gameObject.EnsureComponent<T>();
if (createFunc != null)
createFunc.Invoke(result);
_cameraEffectList.Add(result);
}
return result;
}
public void RemoveCameraEffect<T>() where T : MonoBehaviour
{
for (var i = 0; i < _cameraEffectList.Count; i++)
if (_cameraEffectList[i] is T)
{
_cameraEffectList[i].enabled = false;
break;
}
}
public void ModifyFocusOffset(Vector3 offset)
{
FocusOffset = defaultOffset + offset;
}
/// <summary>
/// 替换当前主摄像机
/// </summary>
public void SetOverrideCamera(Camera overrideCamera)
{
if (OverrideCamera != overrideCamera)
{
OverrideCamera = overrideCamera;
_fruntumDirty = true;
SetHideCamera(3, overrideCamera != null);
}
}
public void SetCameraParameterListener(bool isOn)
{
if (ProcessInput.Instance != null && ProcessInput.Instance.inputModule != null &&
ProcessInput.Instance.inputModule.processCamera != null)
{
var cameraInput = ProcessInput.Instance.inputModule.processCamera;
cameraInput.onCameraAngle -= MoveCameraAngle;
cameraInput.onCameraDistance -= MoveCameraDistance;
if (isOn)
{
cameraInput.onCameraAngle += MoveCameraAngle;
cameraInput.onCameraDistance += MoveCameraDistance;
}
}
}
public void MoveCameraAngle(Vector2 delta)
{
Pitch = Mathf.Clamp(Pitch - delta.y * GlobeVar.pitchPerDpi, GlobeVar.minPitch, GlobeVar.maxPitch);
Yaw = Yaw + delta.x * GlobeVar.yawPerDpi;
}
private void MoveCameraDistance(float delta)
{
Distance = Mathf.Clamp(Distance - delta * GlobeVar.distancePerDpi, GlobeVar.minDistance, GlobeVar.maxDistance);
}
public Plane[] GetFrustumPlanes()
{
if (_fruntumDirty)
{
_fruntumDirty = false;
var currentCamera = OverrideCamera ? OverrideCamera : MainCamera;
_fruntumPlanes = currentCamera == null || !currentCamera.isActiveAndEnabled ? null : GeometryUtility.CalculateFrustumPlanes(currentCamera);
}
return _fruntumPlanes;
}
public static void ForceNoFog(bool isNoFog, int mask)
{
var temp = _forceNoFog.ReplaceFlag(mask.ToFlag(), isNoFog);
var update = _forceNoFog > 0 != temp > 0;
_forceNoFog = temp;
if (update)
{
if (SceneLogic.CameraController != null)
SceneLogic.CameraController.OnFogSettingUpdate(null);
}
}
public void ChangeFocusId(ulong guid)
{
if (guid != GlobeVar.INVALID_GUID)
{
FocusObjGuid = guid;
FocusObj = null;
}
}
private void Awake()
{
MainCamera = transform.GetComponentInChildren<Camera>();
FocusObjGuid = GlobeVar.INVALID_GUID;
_animation = MainCamera.gameObject.EnsureComponent<Animation>();
ToggleDepthTexture();
ResetLayerMask();
EventDispatcher.Instance.Add(Games.Events.EventId.FogSettingUpdate, OnFogSettingUpdate);
EventDispatcher.Instance.Add(Games.Events.EventId.CameraSpaceBlurMax, OnCameraSpaceBlurMax);
EventDispatcher.Instance.Add(Games.Events.EventId.SceneMovie, OnSceneMovie);
EventDispatcher.Instance.Add(Games.Events.EventId.UiCameraCopy, OnUiCameraCopy);
EventDispatcher.Instance.Add(Games.Events.EventId.LowResolution, OnLowResToggle);
GameManager.AddLateUpdate(UpdateCamera, GameManager.cameraControllerUpdateOrder);
EnableSceneCamera(true);
OnLowResToggle(null);
}
private void Start()
{
SetCameraParameterListener(true);
}
public void DestroyCamera()
{
Clean();
EventDispatcher.Instance.Remove(Games.Events.EventId.FogSettingUpdate, OnFogSettingUpdate);
EventDispatcher.Instance.Remove(Games.Events.EventId.CameraSpaceBlurMax, OnCameraSpaceBlurMax);
EventDispatcher.Instance.Remove(Games.Events.EventId.SceneMovie, OnSceneMovie);
EventDispatcher.Instance.Remove(Games.Events.EventId.UiCameraCopy, OnUiCameraCopy);
EventDispatcher.Instance.Remove(Games.Events.EventId.LowResolution, OnLowResToggle);
GameManager.RemoveLateUpdate(UpdateCamera, GameManager.cameraControllerUpdateOrder);
Destroy(gameObject);
}
private void OnLowResToggle(object args)
{
var lowResComponent = MainCamera.GetComponent<CameraLowRes>();
if (PlayerPreferenceData.useLowResolution)
{
if (lowResComponent == null)
lowResComponent = MainCamera.gameObject.AddComponent<CameraLowRes>();
else
lowResComponent.enabled = true;
}
else if (lowResComponent != null)
lowResComponent.enabled = false;
}
public void EnableSceneCamera(bool isEnable)
{
if (isEnable)
{
var sceneId = GameManager.gameManager.RunningScene;
Tab_SceneCameraStartPos sceneData = null;
var sceneDatas = TableManager.GetSceneCameraStartPosByID(sceneId);
if (sceneDatas != null)
for (var i = 0; i < sceneDatas.Count; i++)
if (sceneData == null || sceneDatas[i].Force == GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.Force)
sceneData = sceneDatas[i];
SetHideCamera(0, false);
if (sceneData == null)
LogModule.ErrorLog(string.Format("副本场景{0}在SceneCameraStartPos表中无法获得", sceneId));
else if (sceneData.Pitch != Pitch || sceneData.Yaw != Yaw || sceneData.Distance != Distance ||
sceneData.ViewMax != FoVMax || sceneData.ViewMin != FoVMin)
{
SetCameraParameters(sceneData.Pitch, sceneData.Yaw, sceneData.Distance, sceneData.ViewMin,
sceneData.ViewMax);
}
OnFogSettingUpdate(null);
}
else
SetHideCamera(0, true);
}
public void Clean()
{
MoveOverrider = null;
_delayShakeData.Clear();
_activeShakeData.Clear();
FocusObj = null;
FocusObjGuid = GlobeVar.INVALID_GUID;
}
private void OnFogSettingUpdate(object args)
{
RenderSettings.fog = PlayerPreferenceData.SystemQualityFog && _forceNoFog <= 0;
MainCamera.clearFlags = CameraClearFlags.SolidColor;
MainCamera.backgroundColor = RenderSettings.fogColor;
//// 注主相机在有雾情况下使用短距离Cull然后SolidColor衔接雾效颜色
//if (RenderSettings.fog)
//{
// MainCamera.clearFlags = CameraClearFlags.SolidColor;
// MainCamera.backgroundColor = RenderSettings.fogColor;
// cullDistance = Math.Max(cameraCullDistanceMin, RenderSettings.fogEndDistance);
//}
//// 主相机无雾效情况下使用长距离Cull
//// 计划使用不清空但是在某些场景和某些PC上会有保存上一帧Depth的问题因此强制清空一次
//else
//{
// MainCamera.clearFlags = CameraClearFlags.Depth;
// cullDistance = cameraCullDistanceMax;
//}
SetCameraCull();
}
public void SetNoCullByDist(bool isNoCull)
{
if (_noCullByDist != isNoCull)
{
_noCullByDist = isNoCull;
SetCameraCull();
}
}
private void SetCameraCull()
{
var skyBox = LayerMask.NameToLayer(skyBoxLayer);
var cameraCullDistances = MainCamera.layerCullDistances;
for (var i = 0; i < cameraCullDistances.Length; i++)
cameraCullDistances[i] = skyBox == i || _noCullByDist ? skyBoxCullDistance : cameraCullDistance;
MainCamera.layerCullDistances = cameraCullDistances;
}
private void ToggleDepthTexture()
{
if (MainCamera != null)
MainCamera.depthTextureMode = UseDepthTexture ? DepthTextureMode.Depth : DepthTextureMode.None;
}
/// <summary>
/// 从基本摄像机Layer配置中移除部分Layer
/// </summary>
public void RemoveLayerMask(int layerMask)
{
if (MainCamera != null)
{
var cameraMask = MainCamera.cullingMask;
cameraMask &= ~layerMask;
MainCamera.cullingMask = cameraMask;
}
}
/// <summary>
/// 恢复摄像机到基本Layer
/// </summary>
public void ResetLayerMask()
{
if (MainCamera != null)
{
var cameraMask = int.MaxValue;
cameraMask &= ~LayerMask.GetMask(hideFromCameraLayers);
MainCamera.cullingMask = cameraMask;
}
}
private void SetCameraParameters(float pitch, float yaw, float distance, float minFieldOfView, float maxFieldOfView)
{
Pitch = pitch;
Yaw = yaw;
Distance = distance;
FoVMin = minFieldOfView;
FoVMax = maxFieldOfView;
FoVScale = 1f;
// 2019.05.10 Hack对应主角OnMountCreate和OnMountDestroy
// 暂时不使用事件驱动这个过程
var mainPlayer = ObjManager.Instance.MainPlayer;
if (mainPlayer != null &&
mainPlayer.mountModel.model != null)
ModifyFocusOffset(Vector3.up * mainPlayer.mount_DeltaHeigh);
else
ModifyFocusOffset(Vector3.zero);
}
//更新场景摄像机
private void UpdateCamera()
{
if (!LoadingWindow._IsLoadingScene)
{
_fruntumDirty = true;
if (OverrideCamera == null)
CameraMove();
// ******** 更新Post Camera Movement ********
PostCameraMovement();
}
}
private void CameraMove()
{
// ******** 更新摄像机位置 ********
// 检测是否使用重载方式执行移动
if (MoveOverrider == null || !MoveOverrider.MoveByOverride(this))
{
if (FocusObj == null)
{
if (FocusObjGuid != GlobeVar.INVALID_GUID)
{
var player = Singleton<ObjManager>.Instance.FindOtherPlayerByGuid(FocusObjGuid);
if (player != null && !player.IsDie())
FocusObj = player.transform;
}
else
{
var mainPlayer = ObjManager.Instance.MainPlayer;
if (mainPlayer != null)
{
FocusObj = mainPlayer.ObjTransform;
FocusObjGuid = mainPlayer.GUID;
}
}
}
if (FocusObj != null)
{
var focusPos = FocusObj.position + FocusOffset;
var rotation = Quaternion.Euler(Pitch, Yaw, 0f);
transform.position = focusPos + rotation * Vector3.back * Distance;
transform.rotation = rotation;
CameraHeight = transform.position.y - focusPos.y;
}
}
// ******** 更新震屏 ********
for (var i = _delayShakeData.Count - 1; i >= 0; i--)
if (_delayShakeData[i].startTime + _delayShakeData[i].data.delayTime < Time.time)
{
WakeOneShakeData(_delayShakeData[i]);
_delayShakeData.RemoveAt(i);
}
// 注WakeOneShakeData已经保证了优先度排序因此无需做更多检测
CameraShakeData nextShake = null;
for (var i = _activeShakeData.Count - 1; i >= 0; i--)
{
var currentShakeData = _activeShakeData[i];
if (currentShakeData.startTime + currentShakeData.data.delayTime + currentShakeData.data.animLength < Time.time)
_activeShakeData.RemoveAt(i);
else
{
nextShake = currentShakeData;
break;
}
}
if (nextShake != _currentShake)
{
_currentShake = nextShake;
var shakeAnimName = _currentShake == null ? string.Empty : _currentShake.data.animName;
if (shakeAnimName != _shakeAnimName)
{
_shakeAnimName = shakeAnimName;
if (string.IsNullOrEmpty(_shakeAnimName))
_animation.Stop();
else
{
var clip = _animation.GetClip(_shakeAnimName);
if (clip == null)
{
var newClip = CommonUtility.LoadFromResources<AnimationClip>(_shakeAnimName);
if (newClip != null)
{
_animation.AddClip(newClip, _shakeAnimName);
_animation.Play(_shakeAnimName);
}
}
else
_animation.Play(_shakeAnimName);
}
}
}
if (_currentShake == null)
{
MainCamera.transform.localPosition = Vector3.zero;
MainCamera.transform.localRotation = Quaternion.identity;
}
else if (string.IsNullOrEmpty(_currentShake.data.animName))
{
Vector3 shakeOffset;
Quaternion shakeRotation;
if (_currentShake.data.EvaluteCurve(Time.time - _currentShake.startTime, out shakeOffset,
out shakeRotation))
{
MainCamera.transform.localPosition = shakeOffset;
MainCamera.transform.localRotation = shakeRotation;
}
}
}
public void StartCameraRock(int rockId, Obj starter, int priority)
{
// 检查Starter是否在摄像机范围内
if (PlayerPreferenceData.SystemCameraShake && starter != null)
{
var objCollider = starter.GetComponent<Collider>();
var bounds = objCollider == null ? new Bounds(starter.Position, Vector3.zero) : objCollider.bounds;
var cameraPlanes = GetFrustumPlanes();
if (GeometryUtility.TestPlanesAABB(cameraPlanes, bounds))
{
CameraShakeTableData data = null;
for (var i = 0; i < _cameraShakeData.Count; i++)
if (_cameraShakeData[i].id == rockId)
{
data = _cameraShakeData[i];
break;
}
if (data == null)
{
var tableData = TableManager.GetCameraRockByID(rockId, 0);
if (tableData == null)
LogModule.ErrorLog("无法找到震屏配置{0}", rockId);
else
{
data = new CameraShakeTableData(tableData);
_cameraShakeData.Add(data);
}
}
if (data != null)
{
var shakeData = new CameraShakeData(data, starter.ServerID, priority);
if (shakeData.data.delayTime > 0)
_delayShakeData.Add(shakeData);
else
WakeOneShakeData(shakeData);
}
}
}
}
private void WakeOneShakeData(CameraShakeData data)
{
// 按照优先程度排序,最高优先度排列最后
var add = true;
for (var i = _activeShakeData.Count - 1; i >= 0; i--)
if (_activeShakeData[i].priority <= data.priority)
{
_activeShakeData.Insert(i + 1, data);
add = false;
break;
}
if (add)
_activeShakeData.Insert(0, data);
}
public void StopCameraRock(int rockId, int serverId)
{
RemoveRockFromList(_delayShakeData, rockId, serverId);
RemoveRockFromList(_activeShakeData, rockId, serverId);
}
private void RemoveRockFromList(IList<CameraShakeData> list, int rockId, int starter)
{
for (var i = 0; i < list.Count; i++)
if (list[i].data.id == rockId && list[i].handle == starter)
list.RemoveAt(i);
}
//public void InitCameraTrack(Vector3 posStart, Vector3 posEnd, Vector3 offset)
//{
// MoveOverrider = new CameraTrackMovement(posStart, posEnd, offset);
//}
public void SetCameraOverrider(CameraMovementOverrider overrider)
{
if (MoveOverrider != overrider)
{
ResetCameraToMainPlayer();
MoveOverrider = overrider;
if(MoveOverrider != null)
MoveOverrider.Start(this);
}
}
//恢复到摄像机跟随主角状态
public void ResetCameraToMainPlayer()
{
if (MoveOverrider != null)
MoveOverrider.End(this);
MoveOverrider = null;
}
// 在副本切换达到最大亮度时切换摄像机角度
private void OnCameraSpaceBlurMax(object args)
{
EnableSceneCamera(true);
}
private void OnUiCameraCopy(object args)
{
var start = (bool)args;
_hideCamera = _hideCamera.ReplaceFlag(1.ToFlag(), start);
SetHideCamera(1, start);
}
private void OnSceneMovie(object args)
{
var start = (bool)args;
SetHideCamera(2, start);
}
private void SetHideCamera(int mask, bool isHide)
{
_hideCamera = _hideCamera.ReplaceFlag(mask.ToFlag(), isHide);
if (MainCamera != null)
MainCamera.enabled = _hideCamera <= 0;
}
// // 暂时使用协程处理这个部分
// IEnumerator LerpCameraParameters(float pitch, float yaw, float distance, float minFieldOfView, float maxFieldOfView, Tab_SceneCameraStartPos target)
// {
// const float lerpTime = 1f;
// var startTime = Time.unscaledTime;
// while (startTime + lerpTime > Time.unscaledTime)
// {
// var ratio = (Time.unscaledTime - startTime) / lerpTime;
// SetCameraParameters(
// Mathf.Lerp(pitch, target.Pitch, ratio),
// Mathf.Lerp(yaw, target.Yaw, ratio),
// Mathf.Lerp(distance, target.Distance, ratio),
// Mathf.Lerp(minFieldOfView, target.ViewMin, ratio),
// Mathf.Lerp(maxFieldOfView, target.ViewMax, ratio),
// FocusOffset);
// yield return null;
// }
// SetCameraParameters(target.Pitch, target.Yaw, target.Distance, target.ViewMin, target.ViewMax, FocusOffset);
// }
//private void OnPinch(PinchGesture gesture)
//{
// if (JoyStickLogic.Instance() != null && JoyStickLogic.Instance().FingerID != -1)
// return;
// if (gesture.Phase == ContinuousGesturePhase.Started)
// {
// var mainPlayer = Singleton<ObjManager>.Instance.MainPlayer;
// if (null != mainPlayer)
// if (Singleton<ObjManager>.GetInstance().MainPlayer.IsCanOperate_Move())
// Singleton<ObjManager>.GetInstance().MainPlayer.StopMove();
// m_bPinching = true;
// }
// else if (gesture.Phase == ContinuousGesturePhase.Updated)
// {
// var absDelta = Mathf.Abs(gesture.Delta);
// if (absDelta > m_PinchMax)
// absDelta = m_PinchMax;
// var curDelta = absDelta * gesture.Delta / Mathf.Abs(gesture.Delta);
// m_Scale -= curDelta * (0.5f + 0.5f * m_Scale) / m_pinchSpeed;
// if (m_Scale > 1.0f) m_Scale = 1.0f;
// if (m_Scale < 0) m_Scale = 0;
// }
// else
// {
// m_bPinching = false;
// }
//}
//private void PlayShakeAnimation(string animationName)
//{
// var clip = _animation.GetClip(animationName);
// if (clip == null)
// {
// var newClip = CommonUtility.LoadFromResources<AnimationClip>("CameraRockAnimation/" + animationName);
// if (newClip != null)
// {
// _animation.AddClip(newClip, animationName);
// _animation.Play(animationName);
// }
// }
// else
// {
// _animation.Play(animationName);
// }
//}
// 统一摄像机移动的接口
private void PostCameraMovement()
{
//UpdateWeatherPosition();
EventDispatcher.Instance.Dispatch(Games.Events.EventId.PostMainCameraMove);
}
/// <summary>
/// 整合CameraRock表以及AnimationCurve表的数据结构
/// </summary>
private class CameraShakeTableData
{
public readonly int id;
public readonly string animName;
public readonly float delayTime;
public readonly float animLength;
private readonly bool _playWhileDead;
private readonly AnimationCurve _localXCurve;
private readonly AnimationCurve _localYCurve;
private readonly AnimationCurve _localZCurve;
private readonly AnimationCurve _localForwardXCurve;
private readonly AnimationCurve _localForwardYCurve;
private readonly AnimationCurve _localForwardZCurve;
public CameraShakeTableData(Tab_CameraRock tableData)
{
id = tableData.RockID;
delayTime = tableData.DelayTime;
animLength = tableData.NeedRockTime;
_playWhileDead = tableData.IsContinueDie;
if (tableData.IsAnimation > 0)
animName = tableData.AnimationName;
else
{
animName = string.Empty;
_localXCurve = CommonUtility.GetAnimationCurveById(tableData.PosXAnimCurveId);
_localYCurve = CommonUtility.GetAnimationCurveById(tableData.PosYAnimCurveId);
_localZCurve = CommonUtility.GetAnimationCurveById(tableData.PosZAnimCurveId);
_localForwardXCurve = CommonUtility.GetAnimationCurveById(tableData.RXAnimCurveId);
_localForwardYCurve = CommonUtility.GetAnimationCurveById(tableData.RYAnimCurveId);
_localForwardZCurve = CommonUtility.GetAnimationCurveById(tableData.RZAnimCurveId);
}
}
/// <summary>
/// 使用动画组件执行震屏效果
/// </summary>
public bool EvaluteAnim(float time)
{
time = time - delayTime;
return time <= animLength;
}
/// <summary>
/// 计算震屏效果的位置偏移和旋转偏移
/// </summary>
/// <param name="time">时间包括delay部分</param>
/// <param name="position">位置偏移</param>
/// <param name="rotation">旋转偏移</param>
/// <returns>动画是否过期</returns>
public bool EvaluteCurve(float time, out Vector3 position, out Quaternion rotation)
{
time = time - delayTime;
var result = time <= animLength;
if (result)
{
position.x = _localXCurve == null ? 0 : _localXCurve.Evaluate(time);
position.y = _localYCurve == null ? 0 : _localYCurve.Evaluate(time);
position.z = _localZCurve == null ? 0 : _localZCurve.Evaluate(time);
var forward = new Vector3
(
_localForwardXCurve ==null ? 0 : _localForwardXCurve.Evaluate(time),
_localForwardYCurve == null ? 0 : _localForwardYCurve.Evaluate(time),
_localForwardZCurve == null ? 0 : _localForwardZCurve.Evaluate(time)
);
if (forward == Vector3.zero || Vector3.Cross(forward, Vector3.up) == Vector3.zero)
rotation = Quaternion.identity;
else
rotation = Quaternion.LookRotation(forward, Vector3.up);
}
else
{
position = Vector3.zero;
rotation = Quaternion.identity;
}
return result;
}
// 现仅仅检视主角死亡,后续有其他特殊检视都加在这里
public bool IsPlayable()
{
var result = true;
if (!_playWhileDead)
{
var mainCharacter = Singleton<ObjManager>.Instance.MainPlayer;
if (mainCharacter == null || mainCharacter.IsDie())
result = false;
}
return result;
}
}
/// <summary>
/// 实际运行中的CameraShakeData
/// </summary>
private class CameraShakeData
{
public readonly CameraShakeTableData data;
public readonly float startTime;
public readonly int handle;
public readonly int priority;
public CameraShakeData(CameraShakeTableData data,int handle, int priority)
{
this.data = data;
this.handle = handle;
this.priority = priority;
startTime = Time.time;
}
}
#region
// 接口基类
public abstract class CameraMovementOverrider
{
/// <summary>
/// 使用Override方式移动返回值表示是否继续Override
/// </summary>
public abstract bool MoveByOverride(CameraController controller);
/// <summary>
/// 开始执行移动覆盖
/// </summary>
public abstract void Start(CameraController controller);
/// <summary>
/// 结束移动覆盖
/// </summary>
public abstract void End(CameraController controller);
}
//public class CameraTrackMovement : CameraMovementOverrider
//{
// public const float defaultTrackSpeed = 10f;
// public readonly Vector3 posStart;
// public readonly Vector3 posEnd;
// public readonly Vector3 offset;
// public readonly Quaternion rotation;
// public readonly float duration;
// public readonly float startTime;
// public CameraTrackMovement(Vector3 start, Vector3 end, Vector3 offset, float trackSpeed = defaultTrackSpeed)
// {
// this.posStart = start;
// this.posEnd = end;
// this.offset = offset;
// var lookDir = -offset;
// var lookX = Vector3.Cross(Vector3.up, lookDir);
// // 仰角为90或者-90并且end = start的情况自然报错
// rotation = lookX == Vector3.zero ? Quaternion.LookRotation(lookDir, end - start) : Quaternion.LookRotation(lookDir, Vector3.up);
// this.startTime = Time.time;
// this.duration = Vector3.Distance(posStart, posEnd) / trackSpeed;
// }
// public override bool MoveByOverride(CameraController controller)
// {
// var result = false;
// if (Time.time < startTime + duration)
// {
// var focusPoint = Vector3.Lerp(posStart, posEnd, (Time.time - startTime) / duration);
// controller.transform.position = focusPoint + offset;
// controller.transform.rotation = rotation;
// result = true;
// }
// return result;
// }
//}
#endregion
// #region 天气系统
// private const string _conditionHash = "Condition";
// private static readonly MyTuple<WeatherCondition, string>[] weatherPaths =
// {
// new MyTuple<WeatherCondition, string>(WeatherCondition.Rain, "weather_rain"),
// new MyTuple<WeatherCondition, string>(WeatherCondition.Snow, "weather_snow")
// };
//
// private readonly List<MyTuple<WeatherCondition, WeatherParticle>> effectList =
// new List<MyTuple<WeatherCondition, WeatherParticle>>();
//
// public WeatherCondition currentWeather { get; private set; }
// private WeatherParticle currentWeatherSfx;
//
// public void SetWeather(WeatherCondition condition)
// {
// MyTuple<WeatherCondition, string> weather = null;
// if (condition != WeatherCondition.None)
// {
// weather = weatherPaths.Find(a => a.first == condition);
// if (weather == null)
// {
// LogModule.ErrorLog(string.Format("未定义天气效果{0}", condition.ToString()));
// condition = WeatherCondition.None;
// }
// }
// if (condition != currentWeather)
// {
// if (currentWeatherSfx != null)
// currentWeatherSfx.gameObject.SetActive(false);
// ActiveEffect(weather);
// }
// }
//
// private void ActiveEffect(MyTuple<WeatherCondition, string> weather)
// {
// currentWeather = weather.first;
// if (currentWeather != WeatherCondition.None)
// {
// var effect = effectList.Find(a => a.first == weather.first);
// if (effect == null)
// {
// var hash = new Hashtable();
// hash.Add(_conditionHash, currentWeather);
// CommonUtility.LoadAssetInstance(LoadAssetBundle.BUNDLE_PATH_EFFECT + weather.second, weather.second,
// OnWeatherBundleLoaded, hash);
// }
// else
// {
// currentWeatherSfx = effect.second;
// currentWeatherSfx.gameObject.SetActive(true);
// UpdateWeatherPosition();
// }
// }
// }
//
// private void OnWeatherBundleLoaded(string modelName, GameObject resObj, Hashtable hashParam)
// {
// var condition = (WeatherCondition)hashParam[_conditionHash];
// // 仅缓存当前天气效果,非当前天气效果不缓存
// if (condition == currentWeather)
// {
// var effect = effectList.Find(a => a.first == condition);
// // 在第一次回调前,发出第二次要求时;第二次回调时会已经处理过
// if (effect == null)
// {
// var sfxObj = Instantiate(resObj);
// currentWeatherSfx = sfxObj.GetComponent<WeatherParticle>();
// currentWeatherSfx.transform.localRotation = Quaternion.identity;
// currentWeatherSfx.transform.localScale = Vector3.one;
// effect = new MyTuple<WeatherCondition, WeatherParticle>(condition, currentWeatherSfx);
// effectList.Add(effect);
// UpdateWeatherPosition();
// }
// }
// }
//
// private void UpdateWeatherPosition()
// {
// if (currentWeatherSfx != null)
// {
// currentWeatherSfx.transform.position = MainCamera.transform.position;
// // 面向摄像机前方
// var x = Vector3.Cross(Vector3.up, MainCamera.transform.forward);
// var z = x == Vector3.zero ? Vector3.forward : Vector3.Cross(x, Vector3.up);
// currentWeatherSfx.transform.rotation = Quaternion.LookRotation(z, Vector3.up);
// currentWeatherSfx.OnCameraUpdate(this);
// }
// }
//
// public enum WeatherCondition
// {
// None, // 常规气候
// Rain, // 下雨
// Snow // 下雪
// }
// #endregion
// #region 截屏相关 全屏截图
//
// public void CaptureAllScreen(string savePath = "", CaptureOver fun = null)
// {
// StartCoroutine(CaptureScreen1(MainCamera, savePath, fun));
// }
//
// private IEnumerator CaptureScreen1(Camera came, string savePath, CaptureOver fun)
// {
// if (came == null)
// came = MainCamera;
// if (came == null)
// yield break;
// Rect r = new Rect(0, 0, Screen.width, Screen.height);
// if (came.pixelRect.x != 1 || came.pixelRect.y != 1)
// r = came.pixelRect;
// RenderTexture rt = new RenderTexture((int)r.width, (int)r.height, 0);
// CameraClearFlags Old = came.clearFlags;
// came.clearFlags = CameraClearFlags.Depth;
// came.targetTexture = rt;
// came.Render();
// RenderTexture.active = rt;
// Texture2D screenShot = new Texture2D((int)r.width, (int)r.height, TextureFormat.ARGB32, false);
//
// yield return new WaitForEndOfFrame();
//
// screenShot.ReadPixels(r, 0, 0);
// screenShot.Apply();
// came.targetTexture = null;
// RenderTexture.active = null;
// came.clearFlags = Old;
// GameObject.Destroy(rt);
//
// string path = Application.persistentDataPath + "/" + savePath;
//#if UNITY_EDITOR
// path = Application.dataPath + "/" + savePath;
//#endif
//
// savePath = savePath.Replace("\\", "/");
// int index = savePath.LastIndexOf("/");
// string Direct = savePath.Substring(0, index);
// if (System.IO.Directory.Exists(Direct))
// {
// byte[] bytes = screenShot.EncodeToPNG();
// System.IO.File.WriteAllBytes(savePath, bytes);
// }
// if(fun!=null)
// {
// fun(screenShot, savePath);
// }
// }
// #endregion
}