Files
JJBB/Assets/Project/Script/Player/Controller/CameraController.cs
2024-08-23 15:49:34 +08:00

1087 lines
38 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************************
* 文件名: 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
}