Files
Main/Assets/Plugins/Code/Cinematic/CinematicManager.cs

352 lines
9.6 KiB
C#
Raw Permalink Normal View History

2025-01-25 04:38:09 +08:00
using UnityEngine;
using System.Collections.Generic;
using System;
namespace Thousandto.Cinematic
{
//剧情对象
public partial class CinematicManager
{
#region //私有变量
private List<CinematicObjManager> _cObjMgrList;
private float _startTime;
private int _curFrame;
//剧情播放前
private Action _afterAction;
//剧情播放后
private Action _beforeAction;
private bool _isPlaying;
private bool _isEditorPlay = false;
//自定义事件处理函数
private Dictionary<int, Func<ICinematic, bool>> _customEventHandlerDict;
#endregion
#region //公有变量
public int FrameRate = 30;
public float TimeScale = 1f;
//每一帧改变
public Action<int> 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<ICinematic, bool> handler)
{
if (_customEventHandlerDict == null)
_customEventHandlerDict = new Dictionary<int, Func<ICinematic, bool>>();
if (_customEventHandlerDict.ContainsKey((int)eventType))
_customEventHandlerDict[(int)eventType] = handler;
else
_customEventHandlerDict.Add((int)eventType, handler);
}
public Func<ICinematic, bool> GetEventHandler(KeyFrameEvent eventType)
{
Func<ICinematic, bool> handler = null;
if (_customEventHandlerDict != null)
_customEventHandlerDict.TryGetValue((int)eventType, out handler);
return handler;
}
//返回剧情数据
public List<CinematicObjManager> 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<CinematicObjManager>();
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<CinematicObjManager> 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<CinematicObj> objList)
{
if(_cObjMgrList == null)
{
_isEditorPlay = true;
_cObjMgrList = new List<CinematicObjManager>();
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);
}
}
}
}
}