using UnityEngine; using System.Collections.Generic; using System; namespace Thousandto.Cinematic { //剧情对象 public partial class CinematicManager { #region //私有变量 private List _cObjMgrList; private float _startTime; private int _curFrame; //剧情播放前 private Action _afterAction; //剧情播放后 private Action _beforeAction; private bool _isPlaying; private bool _isEditorPlay = false; //自定义事件处理函数 private Dictionary> _customEventHandlerDict; #endregion #region //公有变量 public int FrameRate = 30; public float TimeScale = 1f; //每一帧改变 public Action OnFrameUpdate; #endregion #region //静态成员、静态属性 private static string _rootName = "[CinematicRoot]"; private static GameObject _rootGo; //暂停帧数 public static float PauseFrame; public static bool IsEditorPreview; private static CinematicManager _instance; public static CinematicManager Instance { get { if(_instance == null) { _instance = new CinematicManager(); } return _instance; } } public static GameObject RootGo { get { if (_rootGo == null) { _rootGo = GameObject.Find(_rootName); if (_rootGo == null) { _rootGo = new GameObject(_rootName); } } return _rootGo; } } #endregion public void RemoveAllChild() { for(int i = RootGo.transform.childCount - 1; i >= 0; --i) { GameObject.DestroyImmediate(RootGo.transform.GetChild(i).gameObject); } } public void Destroy() { RemoveAllChild(); GameObject.DestroyImmediate(RootGo); } private void Reset() { if(_cObjMgrList != null) { for(int i = 0; i < _cObjMgrList.Count; ++i) { _cObjMgrList[i].Destory(); } } _cObjMgrList = null; _timer = 0; } public void RegisterHandler(KeyFrameEvent eventType, Func handler) { if (_customEventHandlerDict == null) _customEventHandlerDict = new Dictionary>(); if (_customEventHandlerDict.ContainsKey((int)eventType)) _customEventHandlerDict[(int)eventType] = handler; else _customEventHandlerDict.Add((int)eventType, handler); } public Func GetEventHandler(KeyFrameEvent eventType) { Func handler = null; if (_customEventHandlerDict != null) _customEventHandlerDict.TryGetValue((int)eventType, out handler); return handler; } //返回剧情数据 public List GetCinematicDatas() { return _cObjMgrList; } public void Play(string clipName, Action before, Action after) { //先清空之前的残余数据 Reset(); _beforeAction = before; _afterAction = after; _isEditorPlay = false; PauseFrame = 0; BeforePlay(); var cs = CinematicSerialize.BinaryDeserialize(clipName); FrameRate = cs.FrameRate; if (cs.ObjList.Count > 0) { _cObjMgrList = new List(); for (int i = 0; i < cs.ObjList.Count; ++i) { CinematicObjManager cObjM = new CinematicObjManager(); cObjM.Prepare(cs.ObjList[i]); _cObjMgrList.Add(cObjM); } _startTime = Time.realtimeSinceStartup; _curFrame = -1; _isPlaying = true; //触发第一帧 TriggerEvent(1); } else if (after != null) { after(); } } public void BeforePlay() { if (_beforeAction != null) _beforeAction(); } public void AfterPlay() { if (_afterAction != null) _afterAction(); } public void StopPlay() { Reset(); _isPlaying = false; _isEditorPlay = false; TimeScale = 1; AfterPlay(); } //当前帧 public int GetCurFrame() { return _curFrame; } public bool IsPlaying() { return _isPlaying; } public List GetObjMgrList() { return _cObjMgrList; } #if UNITY_EDITOR #region //Editor use public void ResetEditorPlay() { if(_cObjMgrList != null && _cObjMgrList.Count > 0) { for(int i = 0; i < _cObjMgrList.Count; ++i) { _cObjMgrList[i].Destory(); } } _cObjMgrList = null; } public void EditorPlay(List objList) { if(_cObjMgrList == null) { _isEditorPlay = true; _cObjMgrList = new List(); for (int i = 0; i < objList.Count; ++i) { CinematicObjManager cObjM = new CinematicObjManager(); cObjM.Prepare(objList[i]); _cObjMgrList.Add(cObjM); } _startTime = Time.realtimeSinceStartup; _curFrame = -1; } } //单帧播放 public void EditorUpdate(int frame) { _isPlaying = true; if (_cObjMgrList == null || _cObjMgrList.Count == 0) return; for (int i = 0; i < _cObjMgrList.Count; ++i) { //防止跳帧 int runningFrame = _cObjMgrList[i].GetCurFrame(); int frameDelta = Mathf.Abs(frame - runningFrame); for (int m = 0; m < frameDelta; ++m) { if(frame >= runningFrame) runningFrame++; else runningFrame--; _cObjMgrList[i].Update(runningFrame); } } } #endregion #endif float _timer; float _tempFrameRate; public void Update() { #if UNITY_EDITOR if (_isEditorPlay) return; #endif if (!_isPlaying) return; if(_timer == 0) { _tempFrameRate = FrameRate; } if (_cObjMgrList == null || _cObjMgrList.Count == 0) return; float nowTime = Time.realtimeSinceStartup; float deltaTime = nowTime - _startTime; //float deltaTime = Time.deltaTime; deltaTime *= TimeScale; _timer += deltaTime; _startTime = nowTime; //暂停时间 if (PauseFrame > 0) { _timer -= deltaTime; PauseFrame -= deltaTime/TimeScale; if (PauseFrame <= 0) PauseFrame = 0; } else { if(_tempFrameRate != FrameRate) { //消除帧率改变的影响 _timer -= deltaTime; _timer = _tempFrameRate * _timer / FrameRate; _timer += deltaTime; _tempFrameRate = FrameRate; } //总共多少帧 float frames = _timer * FrameRate; float deltaFrames = frames - _curFrame; int frameCount = (int)(deltaFrames); //间隔没有1帧,则返回 if (frameCount >= 1) { TriggerEvent(frameCount); } if(_isPlaying) DoSmoothMove(deltaFrames - frameCount); } } private void TriggerEvent(int frames) { bool isAllEnd = true; //防止跳帧 for (int frame = 0; frame < frames; ++frame) { isAllEnd = true; _curFrame++; if (OnFrameUpdate != null) OnFrameUpdate(_curFrame); for (int i = 0; i < _cObjMgrList.Count; ++i) { _cObjMgrList[i].Update(_curFrame); isAllEnd &= _cObjMgrList[i].IsEnd(_curFrame); } if (PauseFrame > 0) return; } if (isAllEnd) { StopPlay(); } } private void DoSmoothMove(float deltaFrame) { if (PauseFrame == 0 && _cObjMgrList != null) { for (int i = 0; i < _cObjMgrList.Count; ++i) { _cObjMgrList[i].UpdateSmooth(deltaFrame); } } } } }