地图系统
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Editor.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源加载合规校验器:扫描项目脚本,禁止裸 <c>Resources.Load</c> 与散落的 <c>Addressables.*</c> 运行时加载,
|
||||
/// 强制所有资源管理统一经 <c>BaseGames.Core.Assets.AssetLoader</c> 门面(设计师拖拽的 AssetReference 实例方法不算违规)。
|
||||
/// <para>
|
||||
/// 白名单(允许直接用 Addressables):
|
||||
/// <list type="bullet">
|
||||
/// <item><c>AssetLoader.cs</c> —— 门面本体。</item>
|
||||
/// <item><c>GameSaveManager.cs</c> —— 位于底层 BaseGames.Core.Save 程序集,无法引用上层门面(循环依赖),已注明的唯一架构豁免点。</item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// 菜单:BaseGames ▸ Tools ▸ Validation ▸ Validate Resource Usage
|
||||
/// </summary>
|
||||
public static class ResourceUsageValidator
|
||||
{
|
||||
private const string ScanRoot = "Assets/_Game/Scripts";
|
||||
|
||||
// 允许直接调用 Addressables 的文件(门面本体 + 已注明的架构豁免)
|
||||
private static readonly HashSet<string> Whitelist = new()
|
||||
{
|
||||
"AssetLoader.cs",
|
||||
"GameSaveManager.cs",
|
||||
};
|
||||
|
||||
// 禁止的运行时加载调用
|
||||
private static readonly Regex ResourcesRe = new(@"\bResources\.(Load|LoadAsync|LoadAll)\b", RegexOptions.Compiled);
|
||||
private static readonly Regex AddressablesRe = new(
|
||||
@"\bAddressables\.(LoadAssetAsync|InstantiateAsync|LoadSceneAsync|UnloadSceneAsync|LoadResourceLocationsAsync|DownloadDependenciesAsync|Release|ReleaseInstance)\b",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
[MenuItem("BaseGames/Tools/Validation/Validate Resource Usage")]
|
||||
public static void Validate()
|
||||
{
|
||||
if (!Directory.Exists(ScanRoot))
|
||||
{
|
||||
Debug.LogWarning($"[ResourceUsageValidator] 未找到扫描目录 {ScanRoot}。");
|
||||
return;
|
||||
}
|
||||
|
||||
var resourcesHits = new List<string>();
|
||||
var addressablesHits = new List<string>();
|
||||
|
||||
foreach (var file in Directory.GetFiles(ScanRoot, "*.cs", SearchOption.AllDirectories))
|
||||
{
|
||||
string fileName = Path.GetFileName(file);
|
||||
// 跳过校验器自身:它的注释/消息字符串里含有这些模式字面量(属数据,非真实调用)。
|
||||
if (fileName == "ResourceUsageValidator.cs") continue;
|
||||
bool whitelisted = Whitelist.Contains(fileName);
|
||||
string assetPath = file.Replace('\\', '/');
|
||||
|
||||
var lines = File.ReadAllLines(file);
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string line = lines[i];
|
||||
string trimmed = line.TrimStart();
|
||||
// 跳过注释行(//、///、* 块注释、/* 开头),避免误报文档/说明
|
||||
if (trimmed.StartsWith("//") || trimmed.StartsWith("*") || trimmed.StartsWith("/*"))
|
||||
continue;
|
||||
|
||||
if (ResourcesRe.IsMatch(line)) // Resources.Load 一律禁止(含白名单文件)
|
||||
resourcesHits.Add($"{assetPath}:{i + 1} {trimmed}");
|
||||
|
||||
if (!whitelisted && AddressablesRe.IsMatch(line))
|
||||
addressablesHits.Add($"{assetPath}:{i + 1} {trimmed}");
|
||||
}
|
||||
}
|
||||
|
||||
int total = resourcesHits.Count + addressablesHits.Count;
|
||||
if (total == 0)
|
||||
{
|
||||
Debug.Log("[ResourceUsageValidator] ✅ 合规:项目脚本无裸 Resources.Load,无散落 Addressables 运行时加载(门面与豁免文件除外)。所有资源管理已统一经 AssetLoader。");
|
||||
return;
|
||||
}
|
||||
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine($"[ResourceUsageValidator] ⚠ 发现 {total} 处资源加载违规(应改为经 AssetLoader):");
|
||||
if (resourcesHits.Count > 0)
|
||||
{
|
||||
sb.AppendLine($"\n— Resources.Load(禁止,改用 Addressables 并经 AssetLoader)×{resourcesHits.Count}:");
|
||||
foreach (var h in resourcesHits) sb.AppendLine(" • " + h);
|
||||
}
|
||||
if (addressablesHits.Count > 0)
|
||||
{
|
||||
sb.AppendLine($"\n— 散落的 Addressables.*(改为经 AssetLoader 门面)×{addressablesHits.Count}:");
|
||||
foreach (var h in addressablesHits) sb.AppendLine(" • " + h);
|
||||
}
|
||||
Debug.LogWarning(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bbfc24e90d3cb9b4eab071c49f403ef4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user