From 39220c761fdb024eae73a8c3a1bf058347588bb6 Mon Sep 17 00:00:00 2001
From: LiRuoChen <571244399@qq.com>
Date: Fri, 24 Jul 2026 14:51:03 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8F=8D=E5=B0=84=E7=BB=91?=
=?UTF-8?q?=E5=AE=9A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Runtime/Core/Base/XericUIBehaviour.cs | 43 +++--
.../XuiavrgFieldEntryGroupAttribute.cs | 34 ++--
...ribute.cs => XuiavrgFieldNameAttribute.cs} | 4 +-
...meta => XuiavrgFieldNameAttribute.cs.meta} | 0
.../Attribute/XuiavrgFieldTagAttribute.cs | 44 +++++
.../Scripts/AvrgMemberMetaData.cs | 17 --
.../Scripts/XuiavrgInspectorManager.cs | 163 +++++++++++-------
Runtime/OverrideUI/XuiAvrgMDGroup.cs | 11 +-
.../Rendering/Component/XericUIActionTable.cs | 1 +
9 files changed, 195 insertions(+), 122 deletions(-)
rename Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/{XuiavrgFieldPrefabOverrideAttribute.cs => XuiavrgFieldNameAttribute.cs} (87%)
rename Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/{XuiavrgFieldPrefabOverrideAttribute.cs.meta => XuiavrgFieldNameAttribute.cs.meta} (100%)
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldTagAttribute.cs
diff --git a/Runtime/Core/Base/XericUIBehaviour.cs b/Runtime/Core/Base/XericUIBehaviour.cs
index aff53d4..2fd12d0 100644
--- a/Runtime/Core/Base/XericUIBehaviour.cs
+++ b/Runtime/Core/Base/XericUIBehaviour.cs
@@ -135,13 +135,13 @@ namespace XericUI.Core.Base
_graphicRaycaster = null;
_hierarchyDirty = true;
}
-
+
///
/// 复位层级脏
///
public void ResetHierarchyDirty()
{
- _hierarchyDirty = false;
+ _hierarchyDirty = false;
rectTransform.SetLayoutDirty();
}
@@ -241,21 +241,30 @@ namespace XericUI.Core.Base
{
var rt = rectTransform;
if (rt == null || target == null) return;
- var parentRT = rt.parent as RectTransform;
- if (parentRT == null) return;
- Vector3[] corners = new Vector3[4];
- target.GetWorldCorners(corners);
- // corners[0]=左下, corners[1]=左上, corners[2]=右上, corners[3]=右下
- Vector3 worldPos = Vector3.Lerp(
- Vector3.Lerp(corners[0], corners[1], anchor.y),
- Vector3.Lerp(corners[3], corners[2], anchor.y),
- anchor.x);
-
- if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
- parentRT, worldPos, null, out Vector2 localPoint))
+ if (rt.parent == target.parent)
{
- rt.anchoredPosition = localPoint;
+ rt.anchorMin = anchor;
+ rt.anchorMax = anchor;
+ rt.pivot = anchor;
+ rt.anchoredPosition = Vector2.zero;
+ return;
+ }
+
+ var targetWorldPos = target.TransformPoint(new Vector3(anchor.x, anchor.y, 0));
+
+ // RectTransformUtility 会自动处理父级不一致的情况
+ if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
+ rt.parent as RectTransform,
+ targetWorldPos,
+ null,
+ out Vector2 anchorLocalPos))
+ {
+ Vector2 pivotOffset = new Vector2(
+ (rt.pivot.x - 0.5f) * rt.rect.width,
+ (rt.pivot.y - 0.5f) * rt.rect.height
+ );
+ rt.anchoredPosition = anchorLocalPos + pivotOffset;
}
}
@@ -265,9 +274,9 @@ namespace XericUI.Core.Base
public virtual void Show()
{
- gameObject.SetActive(true);
+ gameObject.SetActive(true);
}
-
+
public void Show(bool isShow)
{
if (isShow)
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldEntryGroupAttribute.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldEntryGroupAttribute.cs
index a2a9820..ca9e235 100644
--- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldEntryGroupAttribute.cs
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldEntryGroupAttribute.cs
@@ -4,12 +4,21 @@ namespace XericUI.ReflectionUIGenerator
{
///
/// 字段编组特性
- /// 将多个字段标记为属于同一个 Entry,共享一个 UI 组件实例
+ /// 将多个字段标记为属于同一个编组路径,共享一个 UI 组件实例
///
+ /// 编组不携带 Tag,Tag 由 [XuiavrgFieldTag] 单独标记。
/// 使用示例:
- /// [XuiavrgFieldEntryGroup("field1", XuiavrgFieldTag.Label)] public string fieldLabel = "速度";
- /// [XuiavrgFieldEntryGroup("field1", XuiavrgFieldTag.Context)] public float fieldValue = 0.1f;
- /// [XuiavrgFieldEntryGroup("field1", XuiavrgFieldTag.Unit)] public string fieldUnit = "m/s";
+ /// [XuiavrgFieldEntryGroup("field1")]
+ /// [XuiavrgFieldTag(XuiavrgFieldTag.Label)]
+ /// public string fieldLabel = "速度";
+ ///
+ /// [XuiavrgFieldEntryGroup("field1")]
+ /// [XuiavrgFieldTag(XuiavrgFieldTag.Context)]
+ /// public float fieldValue = 0.1f;
+ ///
+ /// [XuiavrgFieldEntryGroup("field1")]
+ /// [XuiavrgFieldTag(XuiavrgFieldTag.Unit)]
+ /// public string fieldUnit = "m/s";
///
/// 上述三个字段将合并为一个 Entry,分别绑定到 UI 组件上 Label、Context、Unit 三个子元素
///
@@ -18,31 +27,20 @@ namespace XericUI.ReflectionUIGenerator
{
/// 编组路径,以 "/" 分割层级。同一 groupPath 的字段合并到一个 Entry
public readonly string GroupPath;
-
- /// 该字段在编组 Entry 中的功能标记
- public readonly XuiavrgFieldTag Tag;
-
- /// 同一 Tag 存在多个时的索引区分
- public readonly int TagIndex;
///
/// 创建字段编组标记
///
- /// 编组路径 (如 "field1" 或 "field1/child")
- /// 功能标记
- /// 标记索引 (同一 Tag 存在多个时区分)
- public XuiavrgFieldEntryGroupAttribute(string groupPath, XuiavrgFieldTag tag, int tagIndex = 0)
+ /// 编组路径 (如 "field1" 或 "Stats/Speed")
+ public XuiavrgFieldEntryGroupAttribute(string groupPath)
{
GroupPath = groupPath;
- Tag = tag;
- TagIndex = tagIndex;
}
public void BindMetaData(AvrgMemberMetaData metaData)
{
metaData.GroupPath = GroupPath;
- metaData.Tag = Tag;
- metaData.TagIndex = TagIndex;
+ // 不设置 Tag/TagIndex,留给 [XuiavrgFieldTag] 单独处理
}
}
}
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldPrefabOverrideAttribute.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldNameAttribute.cs
similarity index 87%
rename from Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldPrefabOverrideAttribute.cs
rename to Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldNameAttribute.cs
index c90bda0..12dc608 100644
--- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldPrefabOverrideAttribute.cs
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldNameAttribute.cs
@@ -12,7 +12,7 @@ namespace XericUI.ReflectionUIGenerator
/// Manager 在 GenerateUI 阶段会优先使用此名称查找 PropertyGroup
///
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
- public class XuiavrgFieldPrefabOverrideAttribute : Attribute, IXuiavrgAttribute
+ public class XuiavrgFieldNameAttribute : Attribute, IXuiavrgAttribute
{
/// 覆盖的预制体组名称
public readonly string PrefabGroupName;
@@ -23,7 +23,7 @@ namespace XericUI.ReflectionUIGenerator
///
/// 目标预制体名称,在 AvrgTypePrefabMappingConfig 中查找匹配
///
- public XuiavrgFieldPrefabOverrideAttribute(string prefabGroupName)
+ public XuiavrgFieldNameAttribute(string prefabGroupName)
{
PrefabGroupName = prefabGroupName;
}
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldPrefabOverrideAttribute.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldNameAttribute.cs.meta
similarity index 100%
rename from Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldPrefabOverrideAttribute.cs.meta
rename to Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldNameAttribute.cs.meta
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldTagAttribute.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldTagAttribute.cs
new file mode 100644
index 0000000..1703083
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldTagAttribute.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace XericUI.ReflectionUIGenerator
+{
+ ///
+ /// 字段功能标记特性
+ /// 单独设置字段的功能标记,与编组分离
+ ///
+ /// 使用示例:
+ /// [XuiavrgFieldEntryGroup("field1")]
+ /// [XuiavrgFieldTag(XuiavrgFieldTag.Label)]
+ /// public string fieldLabel = "速度";
+ ///
+ /// [XuiavrgFieldEntryGroup("field1")]
+ /// [XuiavrgFieldTag(XuiavrgFieldTag.Context)]
+ /// public float fieldValue = 0.1f;
+ ///
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
+ public class XuiavrgFieldTagAttribute : Attribute, IXuiavrgAttribute
+ {
+ /// 功能标记
+ public readonly XuiavrgFieldTag Tag;
+
+ /// 同一 Tag 存在多个时的索引区分
+ public readonly int TagIndex;
+
+ ///
+ /// 创建字段功能标记
+ ///
+ /// 功能标记
+ /// 标记索引(同一 Tag 存在多个时区分)
+ public XuiavrgFieldTagAttribute(XuiavrgFieldTag tag, int tagIndex = 0)
+ {
+ Tag = tag;
+ TagIndex = tagIndex;
+ }
+
+ public void BindMetaData(AvrgMemberMetaData metaData)
+ {
+ metaData.Tag = Tag;
+ metaData.TagIndex = TagIndex;
+ }
+ }
+}
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaData.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaData.cs
index ad67545..3c0b06b 100644
--- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaData.cs
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaData.cs
@@ -85,23 +85,6 @@ namespace XericUI.ReflectionUIGenerator
/// 是否启用无效值状态检查
public bool ValidateInvalid { get; set; }
- // ============ (已弃用字段保留) 旧的验证约束 ============
-
- /// 字符串最小长度
- [Obsolete("将移至 ValueRangeConfig 管理")]
- public int StringMinLength { get; set; }
-
- /// 字符串最大长度
- public int StringMaxLength { get; set; } = int.MaxValue;
-
- /// 数值最小值
- [Obsolete("将移至 ValueRangeConfig 管理")]
- public float NumberMinValue { get; set; }
-
- /// 数值最大值
- [Obsolete("将移至 ValueRangeConfig 管理")]
- public float NumberMaxValue { get; set; }
-
// ============ 原始 Attribute 引用 ============
///
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs
index a922d06..ccb291d 100644
--- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs
@@ -7,8 +7,8 @@ using Object = UnityEngine.Object;
namespace XericUI.ReflectionUIGenerator
{
///
- /// 节点下生成反射属性管理器 — Metadata-Driven View Model (MDVM 元数据驱动的视图数据模型)
- /// 负责:构建 Entry → 创建组容器 → 生成 UI → 绑定数据
+ /// 节点下生成反射属性管理器 — MVM (Metadata-Driven View Model)
+ /// 负责:构建 Entry → 创建组容器(树状嵌套)→ 生成 UI → 绑定数据
///
public class XuiavrgInspectorManager : MonoBehaviour
{
@@ -75,9 +75,9 @@ namespace XericUI.ReflectionUIGenerator
public AvrgMemberMetaDataSet CurrentMetaDataSet { get; private set; }
///
- /// 当前活跃的组容器字典
+ /// 编组叶节点字典 — 完整 GroupPath → 对应层级的 XuiAvrgMDGroup
///
- private Dictionary _activeGroups = new Dictionary();
+ private Dictionary _leafGroupMap = new Dictionary();
[Tooltip("类型-预制体映射配置 ScriptableObject")]
public AvrgTypePrefabMappingConfig typePrefabMappingConfig;
@@ -170,13 +170,14 @@ namespace XericUI.ReflectionUIGenerator
});
}
- // ============ 三阶段 GenerateUI ============
+ // ============ 四阶段 GenerateUI ============
///
- /// 生成 UI — 三阶段流程
+ /// 生成 UI — 四阶段流程
/// Phase A: 按 GroupPath 分组
- /// Phase B: 创建 XuiAvrgMDGroup 组容器
- /// Phase C: 在组容器内生成 UI 组件并绑定
+ /// Phase B: 构建路径树,创建嵌套的 XuiAvrgMDGroup 容器
+ /// Phase C: 在叶节点容器内生成 UI 组件并绑定
+ /// Phase D: 处理非编组 Entry 直接放进根目录
///
public void GenerateUI()
{
@@ -186,21 +187,19 @@ namespace XericUI.ReflectionUIGenerator
return;
}
- // Phase A: 收集并分组
+ // Phase A: 按完整 GroupPath 分组
var groupedEntries = new Dictionary>();
var ungroupedEntries = new List();
foreach (var entry in CurrentEntries)
{
- string groupKey = !string.IsNullOrEmpty(entry.EntryName)
- ? GetGroupPathFromEntry(entry)
- : null;
+ string groupPath = GetGroupPathFromEntry(entry);
- if (!string.IsNullOrEmpty(groupKey))
+ if (!string.IsNullOrEmpty(groupPath))
{
- if (!groupedEntries.ContainsKey(groupKey))
- groupedEntries[groupKey] = new List();
- groupedEntries[groupKey].Add(entry);
+ if (!groupedEntries.ContainsKey(groupPath))
+ groupedEntries[groupPath] = new List();
+ groupedEntries[groupPath].Add(entry);
}
else
{
@@ -208,18 +207,75 @@ namespace XericUI.ReflectionUIGenerator
}
}
- // Phase B: 创建组容器
- _activeGroups.Clear();
+ // Phase B: 构建树状嵌套组容器
+ _leafGroupMap.Clear();
+ BuildGroupTree(groupedEntries.Keys);
+
+ // Phase C: 在叶节点容器内生成 UI
foreach (var kvp in groupedEntries)
{
string groupPath = kvp.Key;
var entries = kvp.Value;
- // 检查是否已创建(相同 GroupPath 只创建一个容器)
- if (_activeGroups.ContainsKey(groupPath)) continue;
+ if (!_leafGroupMap.TryGetValue(groupPath, out var leafGroup)) continue;
- var groupGo = new GameObject($"Group [{groupPath}]", typeof(RectTransform));
- groupGo.transform.SetParent(transform, false);
+ foreach (var entry in entries)
+ {
+ GenerateSingleUI(entry, leafGroup.contentRoot);
+ }
+ }
+
+ // Phase D: 非编组 Entry 直接放进根
+ foreach (var entry in ungroupedEntries)
+ {
+ GenerateSingleUI(entry, transform);
+ }
+ }
+
+ // ============ 树状编组容器构建 ============
+
+ private void BuildGroupTree(IEnumerable allGroupPaths)
+ {
+ var rootNode = new GroupTreeNode(null);
+
+ // Step 1: 将每个完整路径分裂后插入树
+ foreach (var fullPath in allGroupPaths)
+ {
+ if (string.IsNullOrEmpty(fullPath)) continue;
+
+ var segments = fullPath.Split('/');
+ var current = rootNode;
+
+ for (int i = 0; i < segments.Length; i++)
+ {
+ string seg = segments[i];
+ if (!current.Children.ContainsKey(seg))
+ current.Children[seg] = new GroupTreeNode(seg);
+ current = current.Children[seg];
+ }
+ }
+
+ // Step 2: 深度优先遍历,创建层级 GameObject
+ CreateGroupGameObjects(rootNode, null, transform, "");
+ }
+
+ private void CreateGroupGameObjects(
+ GroupTreeNode node,
+ XuiAvrgMDGroup parentGroup,
+ Transform parentTransform,
+ string accumulatedPath)
+ {
+ foreach (var kvp in node.Children)
+ {
+ string segName = kvp.Key;
+ var childNode = kvp.Value;
+
+ string childFullPath = string.IsNullOrEmpty(accumulatedPath)
+ ? segName
+ : accumulatedPath + "/" + segName;
+
+ var groupGo = new GameObject($"Group [{childFullPath}]", typeof(RectTransform));
+ groupGo.transform.SetParent(parentTransform, false);
var rect = groupGo.GetComponent();
rect.anchorMin = new Vector2(0, 1);
@@ -228,35 +284,32 @@ namespace XericUI.ReflectionUIGenerator
rect.sizeDelta = new Vector2(0, 0);
var group = groupGo.AddComponent();
- int firstOrder = entries.Count > 0 ? entries[0].FieldOrder : 0;
- group.Initialize(groupPath, firstOrder);
+ group.Initialize(childFullPath, 0, parentGroup);
- _activeGroups[groupPath] = group;
- }
-
- // Phase C: 生成 UI 组件
- foreach (var kvp in groupedEntries)
- {
- string groupPath = kvp.Key;
- var entries = kvp.Value;
-
- if (!_activeGroups.TryGetValue(groupPath, out var group)) continue;
-
- foreach (var entry in entries)
+ // 叶节点映射到完整路径
+ if (childNode.Children.Count == 0)
{
- GenerateSingleUI(entry, group.contentRoot);
+ _leafGroupMap[childFullPath] = group;
}
- }
- foreach (var entry in ungroupedEntries)
- {
- GenerateSingleUI(entry, transform);
+ CreateGroupGameObjects(childNode, group, group.contentRoot, childFullPath);
}
}
- ///
- /// 生成单个 Entry 的 UI
- ///
+ private class GroupTreeNode
+ {
+ public string SegmentName { get; }
+ public Dictionary Children { get; }
+
+ public GroupTreeNode(string name)
+ {
+ SegmentName = name;
+ Children = new Dictionary();
+ }
+ }
+
+ // ============ 生成单个 UI ============
+
private void GenerateSingleUI(IFieldEntry entry, Transform parent)
{
if (entry is not XuiFieldTempEntry tempEntry) return;
@@ -276,7 +329,6 @@ namespace XericUI.ReflectionUIGenerator
uiInstance.name = entry.EntryName;
uiInstance.transform.SetParent(parent, false);
- // 检查 XUIAvrgMDValue 是否存在
if (uiInstance.GetComponentInChildren(true) == null)
{
Debug.LogError($"[Xuiavrg] 预制体 '{prefab.name}' 不符合生成要求:缺少 XUIAvrgMDValue 组件。请确保预制体根节点或其子节点包含 XUIAvrgMDValue 脚本。");
@@ -288,12 +340,8 @@ namespace XericUI.ReflectionUIGenerator
entry.OnEntryBind();
}
- ///
- /// 从 Entry 提取 GroupPath(通过 EntryName 判断)
- ///
private string GetGroupPathFromEntry(IFieldEntry entry)
{
- // 通过 Bindings 中的元数据找到 GroupPath
if (entry.Bindings != null && entry.Bindings.Count > 0)
{
var metaData = entry.Bindings[0].MetaData;
@@ -355,14 +403,14 @@ namespace XericUI.ReflectionUIGenerator
private void ClearGroups()
{
- foreach (var kvp in _activeGroups)
+ foreach (var kvp in _leafGroupMap)
{
if (kvp.Value != null && kvp.Value.gameObject != null)
{
Destroy(kvp.Value.gameObject);
}
}
- _activeGroups.Clear();
+ _leafGroupMap.Clear();
}
private void OnDestroy()
@@ -370,18 +418,5 @@ namespace XericUI.ReflectionUIGenerator
ClearAll();
}
- // ============ 兼容旧 API ============
-
- [Obsolete("Use BuildFromMetaDataSet + GenerateUI instead", false)]
- public void SchemaHydration(object payload)
- {
- var metaDataSet = XuiavrgUtilities.ExtractAvrgMemberMetaData(payload);
- var bindingCollection = metaDataSet.BuildMDVM(payload);
- BuildFromMetaDataSet(metaDataSet, bindingCollection);
- GenerateUI();
- }
-
- #endregion
-
}
}
diff --git a/Runtime/OverrideUI/XuiAvrgMDGroup.cs b/Runtime/OverrideUI/XuiAvrgMDGroup.cs
index af8f5c3..7919946 100644
--- a/Runtime/OverrideUI/XuiAvrgMDGroup.cs
+++ b/Runtime/OverrideUI/XuiAvrgMDGroup.cs
@@ -21,30 +21,33 @@ namespace XericUI.ReflectionUIGenerator
[Tooltip("编组排序值,越小越靠前")]
private int _groupOrder;
- /// 内容挂载点 — 子 UI 组件应放入此 Transform
+ /// 内容挂载点 — 子 UI 组件或子组应放入此 Transform
public Transform contentRoot;
+ /// 父编组(为 null 表示根组,直接挂在 Manager 下)
+ public XuiAvrgMDGroup ParentGroup { get; private set; }
+
/// 编组路径对应的组名
public string GroupName => _groupName;
/// 编组排序值
public int GroupOrder => _groupOrder;
- /// 上下文层级深度(如 "group1/subgroup" → depth=2)
+ /// 上下文层级深度(如 "Stats/Speed" → depth=2)
public int ContextDepth { get; private set; }
///
/// 初始化编组容器
///
- public void Initialize(string groupPath, int order)
+ public void Initialize(string groupPath, int order, XuiAvrgMDGroup parent = null)
{
_groupName = groupPath;
_groupOrder = order;
+ ParentGroup = parent;
ContextDepth = string.IsNullOrEmpty(groupPath) ? 0 : groupPath.Split('/').Length;
gameObject.name = $"Group [{groupPath}]";
- // 如果没有指定 contentRoot,自动使用自身作为挂载点
if (contentRoot == null)
contentRoot = transform;
}
diff --git a/Runtime/XTable/Rendering/Component/XericUIActionTable.cs b/Runtime/XTable/Rendering/Component/XericUIActionTable.cs
index 6168114..009fe7f 100644
--- a/Runtime/XTable/Rendering/Component/XericUIActionTable.cs
+++ b/Runtime/XTable/Rendering/Component/XericUIActionTable.cs
@@ -622,6 +622,7 @@ namespace XericUI.XTable.Rendering.Component
}
/// 设置预制体(ContentType 自动设为 Prefab)
+ /// 注意是设置预制体而不是实例,设置后订阅单元格预制体生成事件 OnPrefabAcquire 处理获取事件
public XTableCellData SetCellPrefab(int row, int col, GameObject prefab)
{
var data = TableData.GetOrCreateCell(row, col);