295 lines
8.7 KiB
C#
295 lines
8.7 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using PhxhSDK;
|
|
|
|
namespace Gameplay.Effect
|
|
{
|
|
using cfg.EffectCfg;
|
|
using Cysharp.Threading.Tasks;
|
|
using Framework;
|
|
using Gameplay.Pause;
|
|
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<LoadingResult> PreloadEffects(List<int> effectIds = null)
|
|
{
|
|
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 LoadingResult.Success;
|
|
}
|
|
|
|
private async void _PreloadEffect(DataEffect config)
|
|
{
|
|
if (string.IsNullOrEmpty(config.PrefabPath))
|
|
{
|
|
DebugUtil.LogError($"特效表中{config.RoleID} 的 PrefabPath 为空");
|
|
return;
|
|
}
|
|
_preloadingEffects.Add(config.RoleID);
|
|
var loadAsset = await AssetManager.Instance.LoadAssetAsync<GameObject>(config.PrefabPath);
|
|
_preloadingEffects.Remove(config.RoleID);
|
|
if (loadAsset == null)
|
|
{
|
|
DebugUtil.LogError("特效不存在:{0}", config.PrefabPath);
|
|
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)
|
|
{
|
|
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.SetParent(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)
|
|
{
|
|
effectPlayerData.Load(config.PrefabPath);
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
// 理论上不会进行Dispose
|
|
MonoHelper.instance.RemoveAction(EActionType.UPDATE, _LogicUpdate);
|
|
}
|
|
|
|
}
|
|
}
|