/******************************************************************************** * 文件名: 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 _cameraEffectList = new List(); private Animation _animation; private string _shakeAnimName; // 暂时使用掩码处理多重动态雾效关闭的条件 private static int _forceNoFog; // 隐藏摄像机的多重掩码;0为EnableCamera,1为UiCopyCamera,2为SceneMovie,3为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 _delayShakeData = new List(); private readonly List _activeShakeData = new List(); private CameraShakeData _currentShake; private readonly List _cameraShakeData = new List(); // ******** 运动覆盖参数 ******** 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(UnityAction 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(); if (createFunc != null) createFunc.Invoke(result); _cameraEffectList.Add(result); } return result; } public void RemoveCameraEffect() 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; } /// /// 替换当前主摄像机 /// 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(); FocusObjGuid = GlobeVar.INVALID_GUID; _animation = MainCamera.gameObject.EnsureComponent(); 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(); if (PlayerPreferenceData.useLowResolution) { if (lowResComponent == null) lowResComponent = MainCamera.gameObject.AddComponent(); 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; } /// /// 从基本摄像机Layer配置中,移除部分Layer /// public void RemoveLayerMask(int layerMask) { if (MainCamera != null) { var cameraMask = MainCamera.cullingMask; cameraMask &= ~layerMask; MainCamera.cullingMask = cameraMask; } } /// /// 恢复摄像机到基本Layer /// 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.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(_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(); 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 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.Instance.MainPlayer; // if (null != mainPlayer) // if (Singleton.GetInstance().MainPlayer.IsCanOperate_Move()) // Singleton.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("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); } /// /// 整合CameraRock表以及AnimationCurve表的数据结构 /// 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); } } /// /// 使用动画组件执行震屏效果 /// public bool EvaluteAnim(float time) { time = time - delayTime; return time <= animLength; } /// /// 计算震屏效果的位置偏移和旋转偏移 /// /// 时间,包括delay部分 /// 位置偏移 /// 旋转偏移 /// 动画是否过期 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.Instance.MainPlayer; if (mainCharacter == null || mainCharacter.IsDie()) result = false; } return result; } } /// /// 实际运行中的CameraShakeData /// 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 { /// /// 使用Override方式移动,返回值表示是否继续Override /// public abstract bool MoveByOverride(CameraController controller); /// /// 开始执行移动覆盖 /// public abstract void Start(CameraController controller); /// /// 结束移动覆盖 /// 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[] weatherPaths = // { // new MyTuple(WeatherCondition.Rain, "weather_rain"), // new MyTuple(WeatherCondition.Snow, "weather_snow") // }; // // private readonly List> effectList = // new List>(); // // public WeatherCondition currentWeather { get; private set; } // private WeatherParticle currentWeatherSfx; // // public void SetWeather(WeatherCondition condition) // { // MyTuple 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 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(); // currentWeatherSfx.transform.localRotation = Quaternion.identity; // currentWeatherSfx.transform.localScale = Vector3.one; // effect = new MyTuple(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 }