feat: include the unity prefab generator

This commit is contained in:
hypercross 2025-03-30 14:19:17 +08:00
parent 71b5d545bb
commit 3874f4e801
1 changed files with 126 additions and 0 deletions

View File

@ -0,0 +1,126 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace PuertsConfigs.Editor
{
public class PrefabStructureGenerator : EditorWindow
{
[MenuItem("Tools/Generate Prefab Structure Definition")]
public static void GeneratePrefabStructureDefinition()
{
StringBuilder tsDefinition = new StringBuilder();
tsDefinition.AppendLine("// Auto-generated by PrefabStructureGenerator");
tsDefinition.AppendLine("declare type UnityPrefabs = {");
// 查找所有Resources文件夹
string[] resourcesDirs = Directory.GetDirectories(Application.dataPath, "Resources", SearchOption.AllDirectories);
Dictionary<string, Dictionary<string, List<string>>> allPrefabs = new Dictionary<string, Dictionary<string, List<string>>>();
foreach (string resourcesDir in resourcesDirs)
{
// 获取Resources文件夹下的所有Prefab
string relativePath = resourcesDir.Replace(Application.dataPath, "Assets");
string[] prefabPaths = Directory.GetFiles(relativePath, "*.prefab", SearchOption.AllDirectories);
foreach (string prefabPath in prefabPaths)
{
// 获取Prefab的相对Resources路径不带扩展名
string resourcesRelativePath = prefabPath
.Replace(relativePath + Path.DirectorySeparatorChar, "")
.Replace(".prefab", "");
// 加载Prefab
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
if (prefab == null) continue;
// 记录Prefab结构
Dictionary<string, List<string>> prefabStructure = new Dictionary<string, List<string>>();
RecordGameObjectComponents(prefab, "", prefabStructure);
allPrefabs[resourcesRelativePath] = prefabStructure;
}
}
// 生成TypeScript定义
foreach (var kvp in allPrefabs)
{
tsDefinition.AppendLine($" \"{kvp.Key}\": {{");
foreach (var componentKvp in kvp.Value)
{
string path = componentKvp.Key;
List<string> components = componentKvp.Value;
if (string.IsNullOrEmpty(path))
{
tsDefinition.Append(" \"\": ");
}
else
{
tsDefinition.Append($" \"{path}\": ");
}
tsDefinition.Append("[");
for (int i = 0; i < components.Count; i++)
{
if (i > 0) tsDefinition.Append(", ");
tsDefinition.Append(components[i]);
}
tsDefinition.AppendLine("],");
}
tsDefinition.AppendLine(" },");
}
tsDefinition.AppendLine("}");
// 确保输出目录存在
string outputDir = Path.Combine(Application.dataPath, "Gen", "Prefabs");
if (!Directory.Exists(outputDir))
{
Directory.CreateDirectory(outputDir);
}
// 写入文件
string outputPath = Path.Combine(outputDir, "index.d.ts");
File.WriteAllText(outputPath, tsDefinition.ToString());
AssetDatabase.Refresh();
Debug.Log($"Prefab structure definition generated at: {outputPath}");
}
private static void RecordGameObjectComponents(GameObject go, string currentPath, Dictionary<string, List<string>> structure)
{
// 记录当前GameObject的组件
Component[] components = go.GetComponents<Component>();
List<string> componentTypes = new List<string>();
foreach (Component component in components)
{
if (component == null) continue;
string typeName = $"CS.{component.GetType().FullName}";
componentTypes.Add(typeName);
}
if (componentTypes.Count > 0)
{
structure[currentPath] = componentTypes;
}
// 递归处理子对象
for (int i = 0; i < go.transform.childCount; i++)
{
Transform child = go.transform.GetChild(i);
string childPath = string.IsNullOrEmpty(currentPath)
? child.name
: $"{currentPath}/{child.name}";
RecordGameObjectComponents(child.gameObject, childPath, structure);
}
}
}
}