NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Effect/EffectManager.cs

306 lines
9.2 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Gameplay.Utils;
using PhxhSDK;
namespace Gameplay.Effect
{
using cfg.EffectCfg;
using Cysharp.Threading.Tasks;
using Framework;
using Gameplay.Pause;
using Gameplay.SubSystems;
using UnityEngine;
public class EffectManager
{
private static EffectManager _instance;
public static EffectManager instance
{
get
{
if (_instance == null)
{
CreateInstance();
}
return _instance;
}
}
public static EffectManager CreateInstance()
{
if (_instance != null)
{
// DebugUtil.LogError("请勿重复初始化EffectManager");
return _instance;
}
_instance = new EffectManager();
_instance.Init();
return _instance;
}
public EffectOrderCacher orderCacher = new EffectOrderCacher();
public GameObject rootObj;
private List<int> _preloadingEffects;
private List<int> _preloadedEffects;
private List<EffectPlayingData> _playingEffects;
private EffectConfig effectConfig;
public int forceSetLayer = -1;
private Transform _poolParent;
private Dictionary<int, Queue<EffectPlayingData>> _objPools;
public void Init()
{
rootObj = new GameObject("EffectManager");
_poolParent = new GameObject("EffectPool").transform;
// _poolParent.gameObject.hideFlags = HideFlags.HideInHierarchy;
_poolParent.gameObject.SetActive(false);
#if UNITY_EDITOR
if (UnityEditor.EditorApplication.isPlaying)
{
Object.DontDestroyOnLoad(rootObj);
Object.DontDestroyOnLoad(_poolParent.gameObject);
}
else
{
// 不做处理
}
#else
Object.DontDestroyOnLoad(rootObj);
Object.DontDestroyOnLoad(_poolParent.gameObject);
#endif
_playingEffects = new List<EffectPlayingData>();
_preloadingEffects = new List<int>();
_preloadedEffects = new List<int>();
_objPools = new Dictionary<int, Queue<EffectPlayingData>>();
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying)
{
effectConfig = EditorTableManager.instance.tables.EffectConfig;
}
else
{
effectConfig = TableManager.Instance.Tables.EffectConfig;
}
#else
effectConfig = TableManager.Instance.Tables.EffectConfig;
#endif
MonoHelper.instance.AddAction(EActionType.UPDATE, _LogicUpdate);
}
public async UniTask<E_LoadingResult> PreloadEffects(List<int> effectIds = null)
{
return E_LoadingResult.Success;
if (effectIds == null)
{
// 从配表读取
effectIds = new List<int>();
var dataList = effectConfig.DataList;
for (var i = 0; i < dataList.Count; ++i)
{
var data = dataList[i];
effectIds.Add(data.RoleID);
}
}
for (var i = 0; i < effectIds.Count; ++i)
{
var effectId = effectIds[i];
var config = GetEffectConfigById(effectId);
if (config == null)
{
continue;
}
if (_preloadedEffects.Contains(effectId))
{
continue;
}
_PreloadEffect(config);
}
while (_preloadingEffects.Count > 0)
{
await UniTask.DelayFrame(1);
}
return E_LoadingResult.Success;
}
private async void _PreloadEffect(DataEffect config)
{
if (string.IsNullOrEmpty(config.PrefabPath))
{
DebugUtil.LogError($"特效表中{config.RoleID} 的 PrefabPath 为空");
return;
}
_preloadingEffects.Add(config.RoleID);
var effectPath = PathEx.GetEffectPath(config.PrefabPath);
var loadAsset = await AssetManager.Instance.LoadAssetAsync<GameObject>(effectPath);
_preloadingEffects.Remove(config.RoleID);
if (loadAsset == null)
{
DebugUtil.LogError("特效不存在:{0}", effectPath);
return;
}
_preloadedEffects.Add(config.RoleID);
}
public DataEffect GetEffectConfigById(int id)
{
if (effectConfig.DataMap.TryGetValue(id, out var result))
{
return result;
}
DebugUtil.LogError("无效的特效id:{0}", id);
return null;
}
private EffectPlayingData _CreateFromPool(int effectId)
{
if (_objPools.TryGetValue(effectId, out var objects))
{
if (objects.Count > 0)
{
var obj = objects.Dequeue();
obj.Reset();
return obj;
}
}
return _CreateNew(effectId);
}
private static EffectPlayingData _CreateNew(int effectId)
{
var effectPlayerData = new EffectPlayingData(effectId);
effectPlayerData.rootObj = new GameObject();
return effectPlayerData;
}
public void ReturnEffect(EffectPlayingData effectData)
{
if (effectData.rootObj == null)
{
return;
}
var effectId = effectData.effectId;
effectData.rootObj.transform.SetParent(_poolParent);
effectData.SetActive(false);
if (_objPools.TryGetValue(effectId, out var objects))
{
objects.Enqueue(effectData);
}
else
{
objects = new Queue<EffectPlayingData>();
objects.Enqueue(effectData);
_objPools.Add(effectId, objects);
}
}
public EffectPlayingData PlayEffectById(int id,
Vector3 pos = default,
Quaternion rot = default,
Transform parent = null)
{
if (parent == null)
{
parent = rootObj.transform;
}
var effectPlayerData = _CreateFromPool(id);
_playingEffects.Add(effectPlayerData);
effectPlayerData.rootObj.transform.SetParentEx(parent);
effectPlayerData.rootObj.transform.SetPositionAndRotation(pos, rot);
effectPlayerData.rootObj.transform.localScale = Vector3.one;
effectPlayerData.rootObj.SetActive(true);
var config = GetEffectConfigById(id);
if (config == null)
{
DebugUtil.LogError("无效的特效id:{0}", id);
return effectPlayerData;
}
if (forceSetLayer != -1)
{
effectPlayerData.rootObj.SetLayerEx(forceSetLayer);
}
if (!effectPlayerData.isLoaded)
{
var prefabPath = PathEx.GetEffectPath(config.PrefabPath);
effectPlayerData.Load(prefabPath).Forget();
}
if (config.ExistTime > 0)
{
effectPlayerData.SetRemainTime(config.ExistTime);
}
else
{
effectPlayerData.autoDestroy = false;
}
return effectPlayerData;
}
private void _LogicUpdate()
{
var dt = MonoHelper.instance.deltaTime;
if (PauseManager.instance != null)
{
dt *= PauseManager.instance.globalScale;
}
for (var i = 0; i < _playingEffects.Count; ++i)
{
var playEffect = _playingEffects[i];
playEffect.LogicUpdate(dt);
if (playEffect.needReturn)
{
playEffect.Destroy();
_playingEffects.RemoveAt(i);
--i;
}
}
}
public void ClearPool()
{
// 遍历所有的对象池,销毁所有的对象
foreach (var pair in _objPools)
{
var stack = pair.Value;
while (stack.Count > 0)
{
var effectData = stack.Dequeue();
effectData.RealDestroy();
}
}
orderCacher.Clear();
_objPools.Clear();
_playingEffects.Clear();
rootObj.transform.ClearChilds();
_poolParent.ClearChilds();
}
public void Dispose()
{
// 理论上不会进行Dispose
MonoHelper.instance.RemoveAction(EActionType.UPDATE, _LogicUpdate);
}
}
}