using System.IO; using System.Collections.Generic; using UnityEditor; using UnityEngine; using Newtonsoft.Json.Linq; namespace SLSUtilities.Narrative.Editor { /// /// Yarn Spinner 自动 YSLS 合并器。 /// 自动将来自不同程序集(Assembly-CSharp、SLSUtilities等)生成的多个 YSLS 声明文件 /// 合并成一个单一的 combined.ysls.json 文件,输出到项目根目录下, /// 从而完美解决 VS Code 中 Yarn Spinner 插件只能同时加载一个 definitions 文件的限制! /// [InitializeOnLoad] public static class YslsMerger { static YslsMerger() { // 每次 Unity 重新编译、资源导入或启动时自动运行 EditorApplication.delayCall += MergeYslsFiles; } [MenuItem("Tools/Yarn Spinner/Merge YSLS Files")] public static void MergeYslsFiles() { string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "ProjectSettings", "Packages", "dev.yarnspinner"); if (!Directory.Exists(packagePath)) { return; } string combinedFileName = "combined.ysls.json"; string outputRootPath = Path.Combine(packagePath, combinedFileName); try { // 搜索所有以 -generated.ysls.json 结尾的声明文件 string[] files = Directory.GetFiles(packagePath, "*-generated.ysls.json"); if (files.Length == 0) { return; } JArray allCommands = new JArray(); JArray allFunctions = new JArray(); int version = 2; foreach (string file in files) { if (Path.GetFileName(file) == combinedFileName) continue; string json = File.ReadAllText(file); if (string.IsNullOrEmpty(json)) continue; JObject root = JObject.Parse(json); if (root.TryGetValue("version", out JToken vToken)) { version = Mathf.Max(version, vToken.Value()); } if (root.TryGetValue("commands", out JToken cToken) && cToken is JArray commandsArray) { foreach (var cmd in commandsArray) { allCommands.Add(cmd); } } if (root.TryGetValue("functions", out JToken fToken) && fToken is JArray functionsArray) { foreach (var func in functionsArray) { allFunctions.Add(func); } } } // 组装合并后的 JObject JObject combined = new JObject { ["version"] = version, ["commands"] = allCommands, ["functions"] = allFunctions }; // 写入项目根目录 File.WriteAllText(outputRootPath, combined.ToString(Newtonsoft.Json.Formatting.Indented)); Debug.Log($"[YSLS Merger] 成功将 {files.Length} 个 YSLS 声明文件合并至: '{outputRootPath}'。现在您可以在 VS Code 中一键加载此合并文件!"); } catch (System.Exception ex) { // 自动合并失败通常发生在初始无缓存时,作警告处理,不中断编辑体验 Debug.LogWarning($"[YSLS Merger] 自动合并 YSLS 文件失败(这通常是由于 Yarn Spinner 尚未生成初始的 ysls 缓存文件导致的,属于正常现象):{ex.Message}"); } } } }