using CommonAI.Zone; using CommonLang; using Sirenix.Utilities; using System.Collections.Generic; using UnityEngine; namespace ET.Client { [FriendOf(typeof(GameObjectPool))] public static class GameObjectPoolSystem { [ObjectSystem] public class GameObjectPoolAwakeSystem : AwakeSystem { protected override void Awake(GameObjectPool self) { GameObjectPool.Instance = self; } } [ObjectSystem] public class GameObjectPoolDestroySystem : DestroySystem { protected override void Destroy(GameObjectPool self) { self.ClearCache(); GameObjectPool.Instance = null; } } } [ComponentOf(typeof(Scene))] public class GameObjectPool : Entity, IAwake, IDestroy { [StaticField] public static GameObjectPool Instance; private readonly HashMap> goPool = new(); //TODO: 选取当前场景的单位、技能(事件触发等等) //TODO: BUFF public async ETTask CacheSceneObject(/*int scnId*/) { var templates = BattleResourceMgr.Instance.GameEditorTemplates.Templates; //遍历模型 var units = templates.getUnits(); foreach(var unit in units.Values) { var name = $"Unit_{unit.FileName}"; var handle = await YooAssetProxy.LoadAssetAsync(name); var prefab = handle.GetAssetObject(); var gameobj = UnityEngine.Object.Instantiate(prefab, GlobalViewComponent.Instance.RecycleNode, true); gameobj.name = name; RecycleObject(gameobj); } List effectlist = new(); var skills = templates.getAllSkillData(); foreach (var skt in skills.Values) { foreach (var act in skt.ActionQueue) { if (!act.ActionEffectFileName.IsNullOrWhitespace()) { effectlist.Add(act.ActionEffectFileName); } foreach (var kf in act.KeyFrames) { if (kf.Effect != null && !kf.Effect.Name.IsNullOrWhitespace()) { effectlist.Add(kf.Effect.Name); } if (kf.Spell != null) { CacheSpellEffect(templates, kf.Spell.SpellID, ref effectlist); } } } } foreach (var ef in effectlist) { var name = $"Effect_{ef}"; var handle = await YooAssetProxy.LoadAssetAsync(name); var prefab = handle.GetAssetObject(); var gameobj = UnityEngine.Object.Instantiate(prefab, GlobalViewComponent.Instance.RecycleNode, true); gameobj.name = name; RecycleObject(gameobj); } } private void CacheSpellEffect(TemplateManager templates, int spellid, ref List effectlist) { var spell = templates.getSpell(spellid); if (spell == null) { Log.Error($"spell({spellid}) not exist"); return; } if (!spell.FileName.IsNullOrWhitespace()) { effectlist.Add(spell.FileName); } var frame = spell.HitIntervalKeyFrame; if (frame != null) { if (frame.Effect != null && !frame.Effect.Name.IsNullOrWhitespace()) { effectlist.Add(frame.Effect.Name); } if (frame.Spell != null && frame.Spell.SpellID != 0) { CacheSpellEffect(templates, frame.Spell.SpellID, ref effectlist); } if (frame.Attack != null) { var attack = frame.Attack; if (attack.Effect != null && !attack.Effect.Name.IsNullOrWhitespace()) { effectlist.Add(attack.Effect.Name); } if (attack.Spell != null && attack.Spell.SpellID != 0) { CacheSpellEffect(templates, attack.Spell.SpellID, ref effectlist); } } } frame = spell.HitOnExplosionKeyFrame; if (spell.HitOnExplosion && frame != null) { if (frame.Effect != null && !frame.Effect.Name.IsNullOrWhitespace()) { effectlist.Add(frame.Effect.Name); } if (frame.Spell != null && frame.Spell.SpellID != 0) { CacheSpellEffect(templates, frame.Spell.SpellID, ref effectlist); } if (frame.Attack != null) { var attack = frame.Attack; if (attack.Effect != null && !attack.Effect.Name.IsNullOrWhitespace()) { effectlist.Add(attack.Effect.Name); } if (attack.Spell != null && attack.Spell.SpellID != 0) { CacheSpellEffect(templates, attack.Spell.SpellID, ref effectlist); } } } foreach (var frm in spell.KeyFrames) { if (frm.Effect != null && !frm.Effect.Name.IsNullOrWhitespace()) { effectlist.Add(frm.Effect.Name); } if (frm.Spell != null && frame.Spell.SpellID != 0) { CacheSpellEffect(templates, frm.Spell.SpellID, ref effectlist); } if (frm.Attack != null) { var attack = frm.Attack; if (attack.Effect != null && !attack.Effect.Name.IsNullOrWhitespace()) { effectlist.Add(attack.Effect.Name); } if (attack.Spell != null && attack.Spell.SpellID != 0) { CacheSpellEffect(templates, attack.Spell.SpellID, ref effectlist); } } } } public void ClearCache() { foreach (var list in goPool.Values) { foreach (var go in list) { GameObject.Destroy(go); } } goPool.Clear(); } public void RecycleObject(GameObject go, string key = "") { if(key.IsNullOrWhitespace()) { key = go.name; } Log.Debug($"cache gameobject: {key}"); go.SetActive(false); go.transform.SetParent(GlobalViewComponent.Instance.RecycleNode, false); if (goPool.TryGetValue(key, out var golist)) { golist.Add(go); } else { goPool.Add(key, new List() { go }); } } public async ETTask Acquire(string key) { if (goPool.TryGetValue(key, out var golist)) { if (golist.Count > 0) { Log.Debug($"got gameobject ({key}) from pool"); var gobj = golist[0]; golist.RemoveRange(0, 1); return gobj; } } else { goPool.Add(key, new List()); } Log.Debug($"new gameobject: ({key})"); var handle = await YooAssetProxy.LoadAssetAsync(key); var prefab = handle.GetAssetObject(); var gameobj = UnityEngine.Object.Instantiate(prefab, GlobalViewComponent.Instance.RecycleNode, true); gameobj.name = key; return gameobj; } } }