UI 系统

This commit is contained in:
2026-06-08 16:05:00 +08:00
parent b582317692
commit 247de307c6
150 changed files with 10945 additions and 158 deletions

View File

@@ -0,0 +1,100 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
using UnityEngine;
namespace BaseGames.Editor
{
/// <summary>
/// 可复用的 Addressable 注册器:把资产登记到正确的分组并按规范打标。
///
/// 分组与标签均由 <see cref="AddressableRules"/> 推导(规范来源:
/// Docs/Standards/AddressablesLabelSpec.md §3 / AssetFolderSpec.md §8
/// 因此结果与 <c>AddressableManagerWindow</c>、<c>AddressKeyValidator</c> 完全一致。
///
/// 供各脚手架(如 <c>SceneObjectPlacerTool</c> 创建 Prefab 后)一键注册,
/// 避免每个工具重复实现 Addressables Settings API。
/// </summary>
public static class AddressableRegistrar
{
/// <summary>
/// 将指定路径的资产注册为 Addressable。
/// 地址默认取文件名(可用 <paramref name="addressOverride"/> 覆盖);
/// 分组与标签按 <see cref="AddressableRules"/> 推导,
/// <paramref name="extraLabels"/> 在规范标签之上追加(如 E003 幼蛭额外的 Poolable/Preload
/// </summary>
/// <returns>最终写入的地址Addressables 未初始化或资产不存在时返回 null。</returns>
public static string Register(string assetPath, string addressOverride = null,
IEnumerable<string> extraLabels = null, List<string> report = null)
{
var settings = AddressableAssetSettingsDefaultObject.Settings;
if (settings == null)
{
report?.Add("Addressable Asset Settings 不存在(未初始化),已跳过 Addressable 注册。");
return null;
}
string guid = AssetDatabase.AssetPathToGUID(assetPath);
if (string.IsNullOrEmpty(guid))
{
report?.Add($"资产不存在,无法注册 Addressable{assetPath}");
return null;
}
string address = string.IsNullOrEmpty(addressOverride)
? System.IO.Path.GetFileNameWithoutExtension(assetPath)
: addressOverride;
string groupName = AddressableRules.GetExpectedGroup(address);
var group = groupName != null ? EnsureGroup(settings, groupName) : settings.DefaultGroup;
var entry = settings.FindAssetEntry(guid)
?? settings.CreateOrMoveEntry(guid, group, false, false);
if (entry == null)
{
report?.Add($"创建 Addressable 条目失败:{assetPath}");
return null;
}
entry.address = address;
settings.MoveEntry(entry, group, false, false);
var labels = new HashSet<string>(AddressableRules.GetExpectedLabels(address));
if (extraLabels != null)
foreach (var l in extraLabels)
if (!string.IsNullOrWhiteSpace(l)) labels.Add(l);
foreach (var l in labels)
SetLabel(settings, entry, l);
settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryModified, entry, true);
report?.Add($"✅ Addressable 注册:{address} → 分组 {group.name}"
+ (labels.Count > 0 ? $",标签 [{string.Join(", ", labels.OrderBy(x => x))}]" : ",无标签"));
return address;
}
private static AddressableAssetGroup EnsureGroup(AddressableAssetSettings settings, string name)
{
var existing = settings.groups.FirstOrDefault(g => g != null && g.name == name);
if (existing != null) return existing;
var tmpl = settings.GroupTemplateObjects.FirstOrDefault() as AddressableAssetGroupTemplate;
var schemas = tmpl != null ? new List<AddressableAssetGroupSchema>(tmpl.SchemaObjects) : null;
var created = settings.CreateGroup(name, false, false, true, schemas);
if (created != null)
Debug.Log($"[AddressableRegistrar] 已自动创建分组:{name}");
return created ?? settings.DefaultGroup;
}
private static void SetLabel(AddressableAssetSettings settings, AddressableAssetEntry entry, string label)
{
if (!settings.GetLabels().Contains(label))
{
settings.AddLabel(label, true);
Debug.Log($"[AddressableRegistrar] 已创建标签:{label}");
}
entry.SetLabel(label, true, true);
}
}
}