Files
zeling_v2/Assets/_Game/Scripts/Editor/Addressables/AddressableRules.cs
Joywayer c88d2d0549 feat: Addressables rules/sync tools, UI fixes, AddressKeys update
- Add AddressableRules.cs: single source of truth for prefix->group and prefix->label rules
- Add AddressableRuleSyncWindow.cs: scan/fix/export-CSV tool (BaseGames > Addressables > Rule Sync)
- AddressableBatchTool.cs: delegate DeriveGroupName to AddressableRules, remove duplicate PrefixGroupMap
- AddressKeys.cs: add Labels constants (Preload, Poolable, Enemy, BGM, SFX, Charms, Config, Weapon)
- Docs/Standards/AddressablesLabelSpec.md: new label naming & assignment spec
- Docs/Standards/AssetFolderSpec.md: update Addressables group strategy section
- SplashScreenController.cs: fix MainMenu loading flow
- BootFlowSetupWizard.cs / SceneScaffoldTools.cs: scene scaffold fixes
- PlayerInputActions: set UI/Point to Pass-Through type
- Persistent.unity: add BootSequencer to auto-load MainMenu on play
- EditorBuildSettings.asset: register scenes for build

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 11:10:31 +08:00

123 lines
6.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using BaseGames.Core.Assets;
namespace BaseGames.Editor
{
/// <summary>
/// Addressable 分组与标签的权威规则数据。
/// 规范来源:<c>Docs/Standards/AddressablesLabelSpec.md §3</c> 与
/// <c>Docs/Standards/AssetFolderSpec.md §8</c>。
///
/// <see cref="AddressableBatchTool"/> 和 <see cref="AddressableRuleSyncWindow"/> 均引用此处,
/// 保证两个工具的分组/标签判断完全一致,修改规则时只需改这一处。
/// </summary>
public static class AddressableRules
{
// ── 前缀 → 分组名 ──────────────────────────────────────────────────────
// 规则:按 AssetFolderSpec §8.1 Group 划分策略。
// 顺序:更长/更具体的前缀必须排在更短/更泛化的前缀之前,否则短前缀会先匹配。
// 特殊Room_/Boss_ 地址的分组名在运行时动态计算,见 GetExpectedGroup()。
public static readonly (string Prefix, string Group)[] PrefixGroupMap =
{
("Scene_", "Scenes"),
("PLY_", "Player"),
("WPN_", "Player"), // 武器与玩家 Prefab 同组AssetFolderSpec §8.1
("ENM_", "Enemies"),
("PROJ_", "Projectiles"),
("VFX_", "VFX_Common"), // 通用特效组AssetFolderSpec §8.1
("UI_", "UI"),
("COL_", "Collectibles"),
("CHM_", "Config"), // 护身符 SO 归入 Config 组AddressablesLabelSpec §3.9
("Config/", "Config"),
("AUD_", "Audio_Music"),
};
// ── 精确地址 → 标签(优先级高于前缀规则)────────────────────────────────
private static readonly Dictionary<string, string[]> ExactLabelMap =
new(StringComparer.Ordinal)
{
// Scene_MainMenu 是唯一需要 Preload 的场景
{ AddressKeys.SceneMainMenu, new[] { AddressKeys.Labels.Preload } },
// Persistent 场景无需标签(随引擎启动,不通过 label 批量加载)
{ AddressKeys.ScenePersistent, Array.Empty<string>() },
// FloatingDamageText 是 Poolable + PreloadUI_ 前缀通常无 label此处例外
{ AddressKeys.PrefabUIFloatingDmgText, new[] { AddressKeys.Labels.Poolable, AddressKeys.Labels.Preload } },
// FootstepCatalog 是首帧必须可用的配置
{ AddressKeys.DataFootstepCatalog, new[] { AddressKeys.Labels.Config, AddressKeys.Labels.Preload } },
};
// ── 前缀 → 标签列表 ─────────────────────────────────────────────────────
// 顺序更具体的前缀AUD_BGM_在更泛化的前缀AUD_之前。
private static readonly (string Prefix, string[] Labels)[] PrefixLabelMap =
{
("AUD_BGM_", new[] { AddressKeys.Labels.BGM }),
("AUD_SFX_", new[] { AddressKeys.Labels.SFX }),
("AUD_", new[] { AddressKeys.Labels.BGM }), // 未细分音频默认归 BGM
("Scene_", Array.Empty<string>()), // 除 MainMenu 外场景无 label
("PLY_", new[] { AddressKeys.Labels.Preload }),
("WPN_", new[] { AddressKeys.Labels.Weapon, AddressKeys.Labels.Preload }),
("ENM_", new[] { AddressKeys.Labels.Enemy }),
("PROJ_", new[] { AddressKeys.Labels.Poolable, AddressKeys.Labels.Preload }),
("VFX_", new[] { AddressKeys.Labels.Poolable, AddressKeys.Labels.Preload }),
("UI_", Array.Empty<string>()), // 除 FloatingDamageText 外 UI 无默认 label
("COL_", new[] { AddressKeys.Labels.Poolable, AddressKeys.Labels.Preload }),
("CHM_", new[] { AddressKeys.Labels.Charms }),
("Config/", new[] { AddressKeys.Labels.Config }),
};
// ── 公开 API ───────────────────────────────────────────────────────────
/// <summary>
/// 根据 Addressable 地址字符串返回期望的分组名称。
/// <list type="bullet">
/// <item><c>Room_Forest_01</c> → <c>Room_Forest</c>(动态计算)</item>
/// <item><c>Boss_CaoZhi</c> → <c>Boss_CaoZhi</c>(动态计算)</item>
/// <item>无匹配前缀时返回 <c>null</c>(调用方可回退到 Default Group</item>
/// </list>
/// </summary>
public static string GetExpectedGroup(string address)
{
if (string.IsNullOrEmpty(address)) return null;
// Room_/Boss_ 的分组名在地址中动态编码
if (address.StartsWith("Room_", StringComparison.Ordinal))
{
var parts = address.Split('_');
return parts.Length >= 2 ? $"Room_{parts[1]}" : "Room_Unknown";
}
if (address.StartsWith("Boss_", StringComparison.Ordinal))
{
// Boss_CaoZhi → 整个地址即为分组名(与 AssetFolderSpec §8.1 一致)
return address;
}
foreach (var (prefix, group) in PrefixGroupMap)
{
if (address.StartsWith(prefix, StringComparison.Ordinal))
return group;
}
return null;
}
/// <summary>
/// 根据 Addressable 地址字符串返回期望的标签集合。
/// 精确地址匹配优先,其次前缀匹配,均无匹配时返回空数组。
/// </summary>
public static string[] GetExpectedLabels(string address)
{
if (string.IsNullOrEmpty(address)) return Array.Empty<string>();
if (ExactLabelMap.TryGetValue(address, out var exact))
return exact;
foreach (var (prefix, labels) in PrefixLabelMap)
{
if (address.StartsWith(prefix, StringComparison.Ordinal))
return labels;
}
return Array.Empty<string>();
}
}
}