diff --git a/Runtime/XTable/Rendering/Component/TableRenderer.cs b/Runtime/XTable/Rendering/Component/TableRenderer.cs index 691d2e6..bad2e8b 100644 --- a/Runtime/XTable/Rendering/Component/TableRenderer.cs +++ b/Runtime/XTable/Rendering/Component/TableRenderer.cs @@ -234,28 +234,40 @@ namespace XericUI.XTable.Rendering.Component if (IsInSelectionRange != null && IsInSelectionRange(r, c)) { var selImg = m_Assembler.GetImage("cell_multiselect"); - selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); - selImg.Rect.sizeDelta = new Vector2(cellW, cellH); - selImg.Image.color = (r == selRow && c == selCol) ? focusColor : multiSelectColor; + if (selImg != null) + { + selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); + selImg.Rect.sizeDelta = new Vector2(cellW, cellH); + selImg.Image.color = (r == selRow && c == selCol) ? focusColor : multiSelectColor; + } } else if (r == selRow && c == selCol) { var selImg = m_Assembler.GetImage("cell_select"); - selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); - selImg.Rect.sizeDelta = new Vector2(cellW, cellH); - selImg.Image.color = selectionColor; + if (selImg != null) + { + selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); + selImg.Rect.sizeDelta = new Vector2(cellW, cellH); + selImg.Image.color = selectionColor; + } } // 网格线 var hLine = m_Assembler.GetImage("cell_hline"); - hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH); - hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth); - hLine.Image.color = borderColor; + if (hLine != null) + { + hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH); + hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth); + hLine.Image.color = borderColor; + } var vLine = m_Assembler.GetImage("cell_vline"); - vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY); - vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH); - vLine.Image.color = borderColor; + if (vLine != null) + { + vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY); + vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH); + vLine.Image.color = borderColor; + } if (data == null) continue; @@ -265,16 +277,19 @@ namespace XericUI.XTable.Rendering.Component if (!string.IsNullOrEmpty(data.Text)) { var txt = m_Assembler.GetText("cell_text", cellNS); - txt.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY); - txt.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH); - txt.Text.text = data.Text; - txt.Text.color = GetStyleColor(cellNS, XericUIActionTable.STYLE_CELL_FG_COLOR, - XericUIActionTable.FG_COLOR_FALLBACK); - txt.Text.fontSize = GetStyleInt(cellNS, XericUIActionTable.STYLE_CELL_FONT_SIZE, - XericUIActionTable.FONT_SIZE_FALLBACK); - txt.Text.alignment = TextAlignmentOptions.Midline; - txt.Text.font = GetStyleFontAsset?.Invoke(cellNS, - XericUIActionTable.STYLE_CELL_FONT_ASSET) ?? txt.Text.font; + if (txt != null) + { + txt.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY); + txt.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH); + txt.Text.SetText(data.Text); + txt.Text.color = GetStyleColor(cellNS, XericUIActionTable.STYLE_CELL_FG_COLOR, + XericUIActionTable.FG_COLOR_FALLBACK); + txt.Text.fontSize = GetStyleInt(cellNS, XericUIActionTable.STYLE_CELL_FONT_SIZE, + XericUIActionTable.FONT_SIZE_FALLBACK); + txt.Text.alignment = TextAlignmentOptions.Midline; + txt.Text.font = GetStyleFontAsset?.Invoke(cellNS, + XericUIActionTable.STYLE_CELL_FONT_ASSET) ?? txt.Text.font; + } } break; case CellContentType.Image: @@ -282,21 +297,27 @@ namespace XericUI.XTable.Rendering.Component { Sprite sprite = GetOrCreateSprite(data.Image); var img = m_Assembler.GetImage("cell_image", cellNS); - img.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY); - img.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH); - img.Image.sprite = sprite; + if (img != null) + { + img.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY); + img.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH); + img.Image.sprite = sprite; + } } break; case CellContentType.Prefab: if (data.Prefab != null && PrefabPool != null) { GameObject instance = PrefabPool.Acquire(data.Prefab, r, c); - RectTransform prt = instance.GetComponent(); - prt.anchoredPosition = new Vector2(cellX, cellY); - prt.sizeDelta = new Vector2(cellW, cellH); - if (ActivePrefabMap != null) - ActivePrefabMap[(r, c)] = instance; - data.OnPrefabAcquire?.Invoke(instance); + if (instance != null) + { + RectTransform prt = instance.GetComponent(); + prt.anchoredPosition = new Vector2(cellX, cellY); + prt.sizeDelta = new Vector2(cellW, cellH); + if (ActivePrefabMap != null) + ActivePrefabMap[(r, c)] = instance; + data.OnPrefabAcquire?.Invoke(instance); + } } break; } @@ -340,27 +361,39 @@ namespace XericUI.XTable.Rendering.Component if (IsInSelectionRange != null && IsInSelectionRange(r, c)) { var selImg = m_Assembler.GetImage("cell_multiselect"); - selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); - selImg.Rect.sizeDelta = new Vector2(cellW, cellH); - selImg.Image.color = (r == selRow && c == selCol) ? rtFocusColor : rtMultiSelectColor; + if (selImg != null) + { + selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); + selImg.Rect.sizeDelta = new Vector2(cellW, cellH); + selImg.Image.color = (r == selRow && c == selCol) ? rtFocusColor : rtMultiSelectColor; + } } else if (r == selRow && c == selCol) { var selImg = m_Assembler.GetImage("cell_select"); - selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); - selImg.Rect.sizeDelta = new Vector2(cellW, cellH); - selImg.Image.color = rtSelectionColor; + if (selImg != null) + { + selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); + selImg.Rect.sizeDelta = new Vector2(cellW, cellH); + selImg.Image.color = rtSelectionColor; + } } var hLine = m_Assembler.GetImage("cell_hline"); - hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH); - hLine.Rect.sizeDelta = new Vector2(cellW, Config.RuntimeBorderWidth); - hLine.Image.color = Config.RuntimeBorderColor; + if (hLine != null) + { + hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH); + hLine.Rect.sizeDelta = new Vector2(cellW, Config.RuntimeBorderWidth); + hLine.Image.color = Config.RuntimeBorderColor; + } var vLine = m_Assembler.GetImage("cell_vline"); - vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - Config.RuntimeBorderWidth, cellY); - vLine.Rect.sizeDelta = new Vector2(Config.RuntimeBorderWidth, cellH); - vLine.Image.color = Config.RuntimeBorderColor; + if (vLine != null) + { + vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - Config.RuntimeBorderWidth, cellY); + vLine.Rect.sizeDelta = new Vector2(Config.RuntimeBorderWidth, cellH); + vLine.Image.color = Config.RuntimeBorderColor; + } if (data == null) continue; @@ -370,9 +403,12 @@ namespace XericUI.XTable.Rendering.Component if (!string.IsNullOrEmpty(data.Text)) { var txt = m_Assembler.GetText("cell_text", cellNS); - txt.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY); - txt.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH); - txt.Text.text = data.Text; + if (txt != null) + { + txt.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY); + txt.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH); + txt.Text.SetText(data.Text); + } } break; case CellContentType.Image: @@ -380,21 +416,27 @@ namespace XericUI.XTable.Rendering.Component { Sprite sprite = GetOrCreateSprite(data.Image); var img = m_Assembler.GetImage("cell_image", cellNS); - img.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY); - img.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH); - img.Image.sprite = sprite; + if (img != null) + { + img.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY); + img.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH); + img.Image.sprite = sprite; + } } break; case CellContentType.Prefab: if (data.Prefab != null && PrefabPool != null) { GameObject instance = PrefabPool.Acquire(data.Prefab, r, c); - RectTransform prt = instance.GetComponent(); - prt.anchoredPosition = new Vector2(cellX, cellY); - prt.sizeDelta = new Vector2(cellW, cellH); - if (ActivePrefabMap != null) - ActivePrefabMap[(r, c)] = instance; - data.OnPrefabAcquire?.Invoke(instance); + if (instance != null) + { + RectTransform prt = instance.GetComponent(); + prt.anchoredPosition = new Vector2(cellX, cellY); + prt.sizeDelta = new Vector2(cellW, cellH); + if (ActivePrefabMap != null) + ActivePrefabMap[(r, c)] = instance; + data.OnPrefabAcquire?.Invoke(instance); + } } break; } diff --git a/Runtime/XTable/Rendering/Component/XericUIActionTable.RendererFilter.cs b/Runtime/XTable/Rendering/Component/XericUIActionTable.RendererFilter.cs index de20af0..93a4f23 100644 --- a/Runtime/XTable/Rendering/Component/XericUIActionTable.RendererFilter.cs +++ b/Runtime/XTable/Rendering/Component/XericUIActionTable.RendererFilter.cs @@ -195,6 +195,7 @@ namespace XericUI.XTable.Rendering.Component string key = inRange ? "cell_multiselect" : "cell_select"; var img = m_Assembler.GetImage(key, cellNS); + if (img == null) return; img.Rect.anchoredPosition = new Vector2(cellX, cellY); img.Rect.sizeDelta = new Vector2(cellW, cellH); @@ -240,17 +241,23 @@ namespace XericUI.XTable.Rendering.Component // 水平网格线(底部) var hLine = m_Assembler.GetImage("cell_hline", cellNS); - hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH); - hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth); - hLine.Image.color = borderColor; - objs.HLine = hLine; + if (hLine != null) + { + hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH); + hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth); + hLine.Image.color = borderColor; + objs.HLine = hLine; + } // 垂直网格线(右侧) var vLine = m_Assembler.GetImage("cell_vline", cellNS); - vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY); - vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH); - vLine.Image.color = borderColor; - objs.VLine = vLine; + if (vLine != null) + { + vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY); + vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH); + vLine.Image.color = borderColor; + objs.VLine = vLine; + } } private void RenderCellText(XTableCellData data, @@ -260,9 +267,10 @@ namespace XericUI.XTable.Rendering.Component if (string.IsNullOrEmpty(data.Text)) return; var txt = m_Assembler.GetText("cell_text", cellNS); + if (txt == null) return; txt.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY); txt.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH); - txt.Text.text = data.Text; + txt.Text.SetText(data.Text); if (editorMode) { @@ -283,6 +291,7 @@ namespace XericUI.XTable.Rendering.Component Sprite sprite = GetOrCreateSprite(data.Image); var img = m_Assembler.GetImage("cell_image", cellNS); + if (img == null) return; img.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY); img.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH); img.Image.sprite = sprite; @@ -296,6 +305,7 @@ namespace XericUI.XTable.Rendering.Component if (data.Prefab == null) return; GameObject instance = m_PrefabPool.Acquire(data.Prefab, row, col); + if (instance == null) return; RectTransform prt = instance.GetComponent(); prt.anchoredPosition = new Vector2(cellX, cellY); prt.sizeDelta = new Vector2(cellW, cellH); @@ -471,16 +481,14 @@ namespace XericUI.XTable.Rendering.Component private void CleanOrphanChildren() { - Transform poolRoot = m_Assembler?.PoolRoot; - Transform prefabPoolRoot = m_PrefabPool?.PoolRoot; Transform contentT = ContentTransform; Transform borderT = contentT?.Find("_TableBorders"); for (int i = contentT.childCount - 1; i >= 0; i--) { var child = contentT.GetChild(i); - if (poolRoot != null && child == poolRoot) continue; - if (prefabPoolRoot != null && child == prefabPoolRoot) continue; + // 跳过池管理的对象(标记有 POOL_FLAGS = DontSave | HideInHierarchy) + if ((child.hideFlags & HideFlags.DontSave) != 0) continue; if (m_BackgroundGo != null && child.gameObject == m_BackgroundGo) continue; if (borderT != null && child == borderT) continue; diff --git a/Runtime/XTable/Rendering/Elements/CellAssembler.cs b/Runtime/XTable/Rendering/Elements/CellAssembler.cs index 6faee5c..7e5b636 100644 --- a/Runtime/XTable/Rendering/Elements/CellAssembler.cs +++ b/Runtime/XTable/Rendering/Elements/CellAssembler.cs @@ -37,10 +37,6 @@ namespace XericUI.XTable.Rendering.Elements #region 字段 private Transform m_Parent; - private Transform m_PoolRoot; - - /// 池根节点(所有回收对象均挂在此节点下,节点本身处于 inactive) - public Transform PoolRoot => m_PoolRoot; /// 运行时的默认样式命名空间(编辑器下为 null,不绑定) private string m_DefaultStyleNamespace; @@ -48,14 +44,20 @@ namespace XericUI.XTable.Rendering.Elements /// 所有已绑定的 StyleBoundElement 回调集合(用于样式变更时通知外部) public event System.Action OnStyleChangeDetected; - private Stack m_ImagePool = new Stack(); - private Stack m_TextPool = new Stack(); + private Queue m_ImagePool = new Queue(); + private Queue m_TextPool = new Queue(); private List m_ActiveImages = new List(); private List m_ActiveTexts = new List(); /// HideFlags 应用于所有动态创建的对象(不保存、不在 Hierarchy 显示) private const HideFlags POOL_FLAGS = HideFlags.DontSave | HideFlags.HideInHierarchy; + /// 渲染项目总数上限,超出后 GetImage/GetText 返回 null 并发出警告 + private const int MAX_POOL_ITEMS = 256; + + private int m_ImageCreatedCount; + private int m_TextCreatedCount; + #endregion #region 构造函数与析构 @@ -64,12 +66,6 @@ namespace XericUI.XTable.Rendering.Elements { m_Parent = parent; m_DefaultStyleNamespace = defaultStyleNamespace; - - GameObject poolRoot = new GameObject("_CellPool"); - poolRoot.hideFlags = POOL_FLAGS; - poolRoot.transform.SetParent(parent, false); - poolRoot.SetActive(false); - m_PoolRoot = poolRoot.transform; } /// 彻底销毁所有池对象(包括活跃和休眠的) @@ -91,18 +87,11 @@ namespace XericUI.XTable.Rendering.Elements // 杀死池中对象 while (m_ImagePool.Count > 0) { - KillObject(m_ImagePool.Pop().Root); + KillObject(m_ImagePool.Dequeue().Root); } while (m_TextPool.Count > 0) { - KillObject(m_TextPool.Pop().Root); - } - - // 杀死池根 - if (m_PoolRoot != null) - { - KillObject(m_PoolRoot.gameObject); - m_PoolRoot = null; + KillObject(m_TextPool.Dequeue().Root); } } @@ -132,14 +121,18 @@ namespace XericUI.XTable.Rendering.Elements PooledImage item; if (m_ImagePool.Count > 0) { - item = m_ImagePool.Pop(); - item.Root.SetActive(true); - item.Root.transform.SetParent(m_Parent, false); + item = m_ImagePool.Dequeue(); ResetImageDefaults(item); } + else if (m_ImageCreatedCount < MAX_POOL_ITEMS) + { + item = CreateImage(name); + m_ImageCreatedCount++; + } else { - item = CreateImage(name); + Debug.LogWarning($"[XericUIActionTable] Image 池已达上限 {MAX_POOL_ITEMS},无法分配新对象"); + return null; } BindStyle(item.Style, styleNamespace); m_ActiveImages.Add(item); @@ -151,14 +144,18 @@ namespace XericUI.XTable.Rendering.Elements PooledText item; if (m_TextPool.Count > 0) { - item = m_TextPool.Pop(); - item.Root.SetActive(true); - item.Root.transform.SetParent(m_Parent, false); + item = m_TextPool.Dequeue(); ResetTextDefaults(item); } + else if (m_TextCreatedCount < MAX_POOL_ITEMS) + { + item = CreateText(name); + m_TextCreatedCount++; + } else { - item = CreateText(name); + Debug.LogWarning($"[XericUIActionTable] Text 池已达上限 {MAX_POOL_ITEMS},无法分配新对象"); + return null; } BindStyle(item.Style, styleNamespace); m_ActiveTexts.Add(item); @@ -214,18 +211,13 @@ namespace XericUI.XTable.Rendering.Elements private void ReturnImage(PooledImage item) { item.Style?.Unbind(); - item.Root.SetActive(false); - item.Root.transform.SetParent(m_PoolRoot, false); - m_ImagePool.Push(item); + m_ImagePool.Enqueue(item); } private void ReturnText(PooledText item) { item.Style?.Unbind(); - item.Text.text = ""; - item.Root.SetActive(false); - item.Root.transform.SetParent(m_PoolRoot, false); - m_TextPool.Push(item); + m_TextPool.Enqueue(item); } #endregion @@ -251,7 +243,7 @@ namespace XericUI.XTable.Rendering.Elements item.Rect.pivot = PIVOT_TOPLEFT; item.Rect.anchoredPosition = Vector2.zero; item.Rect.sizeDelta = Vector2.zero; - item.Text.text = ""; + item.Text.SetText(string.Empty); item.Text.color = Color.black; item.Text.fontSize = 14; item.Text.alignment = TextAlignmentOptions.Midline; diff --git a/Runtime/XTable/Rendering/Elements/PrefabPrototypePool.cs b/Runtime/XTable/Rendering/Elements/PrefabPrototypePool.cs index bcb61e1..ee3e0b6 100644 --- a/Runtime/XTable/Rendering/Elements/PrefabPrototypePool.cs +++ b/Runtime/XTable/Rendering/Elements/PrefabPrototypePool.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using UnityEngine; -using UnityEngine.Pool; namespace XericUI.XTable.Rendering.Elements { /// /// 预制体对象池——按原型分组管理,每个预制体对应一个独立的对象池。 - /// 使用 Stack + HashSet 模式与 保持一致。 + /// 使用 Queue + HashSet 模式,FIFO 保证对象按回收顺序均匀复用。 /// public class PrefabPrototypePool { @@ -16,8 +15,8 @@ namespace XericUI.XTable.Rendering.Elements private class PrefabPool { public GameObject Prototype; - /// 休眠实例栈(池满时先归还的优先复用) - public Stack Available = new Stack(); + /// 休眠实例队列(FIFO,先归还的优先复用) + public Queue Available = new Queue(); /// 活跃实例集合(O(1) 查找 + 防止重复归还) public HashSet Active = new HashSet(); } @@ -28,10 +27,10 @@ namespace XericUI.XTable.Rendering.Elements private Dictionary m_Pools = new Dictionary(); private Transform m_Parent; - private Transform m_PoolRoot; - /// 池根节点(所有回收对象均挂在此节点下,节点本身处于 inactive) - public Transform PoolRoot => m_PoolRoot; + /// 渲染项目总数上限 + private const int MAX_PREFAB_ITEMS = 256; + private int m_TotalCreated; private const HideFlags POOL_FLAGS = HideFlags.DontSave | HideFlags.HideInHierarchy; @@ -45,15 +44,9 @@ namespace XericUI.XTable.Rendering.Elements public PrefabPrototypePool(Transform parent) { m_Parent = parent; - - GameObject poolRoot = new GameObject("_PrefabPoolRoot"); - poolRoot.hideFlags = POOL_FLAGS; - poolRoot.transform.SetParent(parent, false); - poolRoot.SetActive(false); - m_PoolRoot = poolRoot.transform; } - /// 彻底销毁所有池对象(活跃 + 休眠 + 池根) + /// 彻底销毁所有池对象(活跃 + 休眠) public void DestroyAll() { foreach (var kv in m_Pools) @@ -65,15 +58,9 @@ namespace XericUI.XTable.Rendering.Elements pool.Active.Clear(); // 销毁休眠实例 while (pool.Available.Count > 0) - KillObject(pool.Available.Pop()); + KillObject(pool.Available.Dequeue()); } m_Pools.Clear(); - - if (m_PoolRoot != null) - { - KillObject(m_PoolRoot.gameObject); - m_PoolRoot = null; - } } private static void KillObject(GameObject go) @@ -89,7 +76,7 @@ namespace XericUI.XTable.Rendering.Elements #region 池操作 - /// 从池中获取实例(池空则 Instantiate 新的) + /// 从池中获取实例(FIFO 复用;池空且未达上限则 Instantiate;已达上限返回 null) public GameObject Acquire(GameObject prefab, int row, int col) { if (prefab == null) return null; @@ -99,14 +86,18 @@ namespace XericUI.XTable.Rendering.Elements GameObject instance; if (pool.Available.Count > 0) { - instance = pool.Available.Pop(); - instance.SetActive(true); - instance.transform.SetParent(m_Parent, false); + instance = pool.Available.Dequeue(); } - else + else if (m_TotalCreated < MAX_PREFAB_ITEMS) { instance = Object.Instantiate(prefab, m_Parent); instance.hideFlags = POOL_FLAGS; + m_TotalCreated++; + } + else + { + Debug.LogWarning($"[XericUIActionTable] Prefab 池已达上限 {MAX_PREFAB_ITEMS},无法分配新实例"); + return null; } instance.name = $"_prefab_{row}_{col}"; @@ -122,7 +113,7 @@ namespace XericUI.XTable.Rendering.Elements return instance; } - /// 将指定实例归还对象池(Deactivate + 移入 PoolRoot) + /// 将指定实例归还对象池(不入池根,原地保留避免 OnEnable/OnDisable) public void Release(GameObject instance) { if (instance == null) return; @@ -132,9 +123,7 @@ namespace XericUI.XTable.Rendering.Elements { if (kv.Value.Active.Remove(instance)) { - instance.SetActive(false); - instance.transform.SetParent(m_PoolRoot, false); - kv.Value.Available.Push(instance); + kv.Value.Available.Enqueue(instance); return; } } @@ -143,7 +132,7 @@ namespace XericUI.XTable.Rendering.Elements KillObject(instance); } - /// 将所有活跃实例回收至池 + /// 将所有活跃实例回收至池(原地保留,仅从活跃集移除并入队) public void ReturnAll() { foreach (var kv in m_Pools) @@ -151,9 +140,7 @@ namespace XericUI.XTable.Rendering.Elements var pool = kv.Value; foreach (var go in pool.Active) { - go.SetActive(false); - go.transform.SetParent(m_PoolRoot, false); - pool.Available.Push(go); + pool.Available.Enqueue(go); } pool.Active.Clear(); }