using System.Collections.Generic; using BaseGames.Audio; using BaseGames.Camera; using BaseGames.Core; using BaseGames.Core.Events; using BaseGames.Core.Save; using BaseGames.Core.Pool; using BaseGames.Input; using BaseGames.UI; using BaseGames.UI.HUD; using BaseGames.UI.Menus; using BaseGames.World; using PathBerserker2d; using Unity.Cinemachine; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.Tilemaps; using UnityEngine.UI; namespace BaseGames.Editor { public static class SceneScaffoldTools { [MenuItem("BaseGames/Tools/Scaffold Persistent Scene")] public static void ScaffoldPersistentScene() { var report = new List(); EnsureEventChannelAssets(report); GameObject root = GetOrCreateRoot("[Persistent]"); Transform services = GetOrCreateChild(root.transform, "[Services]"); Transform input = GetOrCreateChild(root.transform, "[Input]"); Transform camera = GetOrCreateChild(root.transform, "[Camera]"); Transform ui = GetOrCreateChild(root.transform, "[UI]"); GameObject registrarGo = GetOrCreateChild(services, "GameServiceRegistrar").gameObject; GameObject deathRespawnGo = GetOrCreateChild(services, "DeathRespawnService").gameObject; GameObject sceneServiceGo = GetOrCreateChild(services, "SceneService").gameObject; GameObject sceneLoaderGo = GetOrCreateChild(services, "SceneLoader").gameObject; GameObject registryGo = GetOrCreateChild(services, "EventChannelRegistry").gameObject; GameObject settingsGo = GetOrCreateChild(services, "SettingsManager").gameObject; GameObject poolGo = GetOrCreateChild(services, "GlobalObjectPool").gameObject; GameObject gameManagerGo = GetOrCreateChild(services, "GameManager").gameObject; GameObject audioManagerGo = GetOrCreateChild(services, "AudioManager").gameObject; GameObject saveManagerGo = GetOrCreateChild(services, "GameSaveManager").gameObject; GameServiceRegistrar registrar = GetOrAddComponent(registrarGo); DeathRespawnService deathRespawnService = GetOrAddComponent(deathRespawnGo); SceneService sceneService = GetOrAddComponent(sceneServiceGo); SceneLoader sceneLoader = GetOrAddComponent(sceneLoaderGo); EventChannelRegistry registry = GetOrAddComponent(registryGo); SettingsManager settingsManager = GetOrAddComponent(settingsGo); GetOrAddComponent(poolGo); GameManager gameManager = GetOrAddComponent(gameManagerGo); AudioManager audioManager = GetOrAddComponent(audioManagerGo); GameSaveManager gameSaveManager = GetOrAddComponent(saveManagerGo); GameObject inputHolderGo = GetOrCreateChild(input, "InputReaderHolder").gameObject; Object inputReaderAsset = FindFirstAssetByType("InputReader", "InputReaderSO"); if (inputReaderAsset == null) inputReaderAsset = EnsureInputReaderAsset(report); InputReaderBootstrap inputBootstrap = GetOrAddComponent(inputHolderGo); AssignReference(inputBootstrap, "_inputReader", inputReaderAsset, report); if (inputReaderAsset != null) { AssignReference(inputReaderAsset, "_onPauseRequested", FindFirstAssetByType("EVT_PauseRequested"), report); AssignReference(inputReaderAsset, "_inputActions", FindFirstAssetWithExtension(".inputactions", "PlayerInputActions", "InputActions"), report); } if (inputReaderAsset == null) report.Add("未找到 InputReaderSO 资产,InputReaderBootstrap 将保持空引用。请补齐 Assets/_Game/Data/Player/Input/InputReader.asset。"); GameObject mainCameraGo = GetOrCreateChild(camera, "Main Camera").gameObject; UnityEngine.Camera mainCamera = GetOrAddComponent(mainCameraGo); mainCamera.orthographic = false; mainCamera.fieldOfView = 60f; mainCameraGo.tag = "MainCamera"; GetOrAddComponent(mainCameraGo); CinemachineBrain brain = GetOrAddComponent(mainCameraGo); GameObject cameraStateGo = GetOrCreateChild(camera, "CameraStateController").gameObject; CameraStateController cameraStateController = GetOrAddComponent(cameraStateGo); CinemachineImpulseSource impulseSource = GetOrAddComponent(cameraStateGo); // 垂直窥视系统:独立节点,CameraStateController 持引用 GameObject lookSystemGo = GetOrCreateChild(camera, "CameraLookSystem").gameObject; CameraLookSystem lookSystem = GetOrAddComponent(lookSystemGo); GameObject vcamAGo = GetOrCreateChild(camera, "VCamA").gameObject; CinemachineCamera vcamA = GetOrAddComponent(vcamAGo); GetOrAddComponent(vcamAGo); GetOrAddComponent(vcamAGo); GetOrAddComponent(vcamAGo); GetOrAddComponent(vcamAGo); // CinemachinePositionComposer:Body 阶段组件,必须存在;ConfigureSlot 依赖它写入所有相机跟随参数 var composerA = GetOrAddComponent(vcamAGo); ApplyComposerDefaults(composerA); GameObject vcamBGo = GetOrCreateChild(camera, "VCamB").gameObject; CinemachineCamera vcamB = GetOrAddComponent(vcamBGo); GetOrAddComponent(vcamBGo); GetOrAddComponent(vcamBGo); GetOrAddComponent(vcamBGo); GetOrAddComponent(vcamBGo); var composerB = GetOrAddComponent(vcamBGo); ApplyComposerDefaults(composerB); GameObject uiRootGo = GetOrCreateChild(ui, "UIRoot").gameObject; UIManager uiManager = GetOrAddComponent(uiRootGo); GameObject hudCanvasGo = GetOrCreateCanvas(uiRootGo.transform, "HUD Canvas", 0); GameObject hudRootGo = GetOrCreateChild(hudCanvasGo.transform, "HUDRoot").gameObject; HUDController hudController = GetOrAddComponent(hudRootGo); GameObject pauseRootGo = GetOrCreateChild(uiRootGo.transform, "PauseMenuRoot").gameObject; GameObject settingsRootGo = GetOrCreateChild(uiRootGo.transform, "SettingsRoot").gameObject; GameObject mapRootGo = GetOrCreateChild(uiRootGo.transform, "MapRoot").gameObject; GameObject shopRootGo = GetOrCreateChild(uiRootGo.transform, "ShopRoot").gameObject; pauseRootGo.SetActive(false); settingsRootGo.SetActive(false); mapRootGo.SetActive(false); shopRootGo.SetActive(false); GameObject deathCanvasGo = GetOrCreateCanvas(uiRootGo.transform, "DeathScreen Canvas", 10); GameObject deathRootGo = GetOrCreateChild(deathCanvasGo.transform, "DeathScreenRoot").gameObject; DeathScreenController deathScreenController = GetOrAddComponent(deathRootGo); deathRootGo.SetActive(false); GameObject respawnButtonGo = GetOrCreateChild(deathRootGo.transform, "RespawnButton").gameObject; GetOrAddComponent(respawnButtonGo); Button respawnButton = GetOrAddComponent