#if UNITY_EDITOR using System; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor; using UnityEngine; namespace XGame.Editor { // publish.json 视图(JsonUtility:C# 字段名须与 json 键一致,故小写开头) [Serializable] public sealed class MiniGamePublishSpec { public string gameId; public string serverSrcDir; // 相对 Server/games-src/ public string serverProject; // 相对 serverSrcDir public string serverAssembly; public string serverEntryType; public string clientProject; // 相对仓库根 public string coreDll; public string clientDll; public string clientEntryType; public int minFrameworkVersion = 1; public int playerCount = 2; public int tickRateHz = 10; } public static class MiniGamePublishMenu { [MenuItem("XWorld/生成小游戏更新", false, 802)] public static void Open() => MiniGamePublishWindow.Open(); } public sealed class MiniGamePublishWindow : EditorWindow { private string[] _gameDirs = Array.Empty(); private string[] _gameNames = Array.Empty(); private int _selected; private int _version = 1; private bool _pc, _android, _ios, _webgl; private Vector2 _scroll; public static void Open() { var w = GetWindow("生成小游戏更新"); w.minSize = new Vector2(360, 320); w.RefreshGames(); w.Show(); } private void RefreshGames() { string root = Path.Combine(Application.dataPath, "MiniGames"); _gameDirs = Directory.Exists(root) ? Directory.GetDirectories(root).Where(d => File.Exists(Path.Combine(d, "publish.json"))).ToArray() : Array.Empty(); _gameNames = _gameDirs.Select(Path.GetFileName).ToArray(); _selected = Mathf.Clamp(_selected, 0, Mathf.Max(0, _gameDirs.Length - 1)); // 默认平台 = 当前激活 BuildTarget _pc = _android = _ios = _webgl = false; switch (EditorUserBuildSettings.activeBuildTarget) { case BuildTarget.Android: _android = true; break; case BuildTarget.iOS: _ios = true; break; case BuildTarget.WebGL: _webgl = true; break; default: _pc = true; break; } RefreshDefaultVersion(); } private void RefreshDefaultVersion() { if (_gameDirs.Length == 0) return; var spec = LoadSpec(_gameDirs[_selected]); _version = (spec == null || string.IsNullOrEmpty(spec.gameId)) ? 1 : MiniGamePublishPipeline.NextVersion(spec.gameId); } private static MiniGamePublishSpec LoadSpec(string gameDir) { try { return JsonUtility.FromJson(File.ReadAllText(Path.Combine(gameDir, "publish.json"))); } catch (Exception e) { Debug.LogError("[MiniGamePublish] publish.json 解析失败: " + e.Message); return null; } } private void OnGUI() { if (_gameDirs.Length == 0) { EditorGUILayout.HelpBox("Assets/MiniGames 下没有含 publish.json 的小游戏目录。", MessageType.Warning); if (GUILayout.Button("刷新")) RefreshGames(); return; } _scroll = EditorGUILayout.BeginScrollView(_scroll); EditorGUILayout.LabelField("小游戏", EditorStyles.boldLabel); int sel = GUILayout.SelectionGrid(_selected, _gameNames, 1, EditorStyles.radioButton); if (sel != _selected) { _selected = sel; RefreshDefaultVersion(); } EditorGUILayout.Space(); _version = Mathf.Max(1, EditorGUILayout.IntField("版本号", _version)); EditorGUILayout.Space(); EditorGUILayout.LabelField("平台(AB 按平台构建)", EditorStyles.boldLabel); _pc = EditorGUILayout.ToggleLeft("PC (StandaloneWindows64)", _pc); _android = EditorGUILayout.ToggleLeft("Android", _android); _ios = EditorGUILayout.ToggleLeft("iOS", _ios); _webgl = EditorGUILayout.ToggleLeft("WebGL", _webgl); EditorGUILayout.EndScrollView(); EditorGUILayout.Space(); using (new EditorGUI.DisabledScope(!(_pc || _android || _ios || _webgl))) { if (GUILayout.Button("生成", GUILayout.Height(32))) { var spec = LoadSpec(_gameDirs[_selected]); if (spec == null || string.IsNullOrEmpty(spec.gameId)) { EditorUtility.DisplayDialog("生成小游戏更新", "publish.json 无效(缺 gameId)", "OK"); } else { var targets = new List(); if (_pc) targets.Add(new MiniGamePublishPipeline.PlatformChoice("pc", BuildTarget.StandaloneWindows64)); if (_android) targets.Add(new MiniGamePublishPipeline.PlatformChoice("android", BuildTarget.Android)); if (_ios) targets.Add(new MiniGamePublishPipeline.PlatformChoice("ios", BuildTarget.iOS)); if (_webgl) targets.Add(new MiniGamePublishPipeline.PlatformChoice("webgl", BuildTarget.WebGL)); MiniGamePublishPipeline.Run(spec, _gameDirs[_selected], _version, targets); } } } } } } #endif