- Created a new markdown file detailing the configuration of InputDeviceIconSetSO. - Included sections on system architecture, field explanations, image specifications, and complete workflow from setup to runtime. - Documented the automatic device recognition logic and provided troubleshooting for common issues. - Added references to relevant files and scripts for easier navigation.
221 lines
15 KiB
C#
221 lines
15 KiB
C#
using UnityEngine;
|
||
using UnityEditor;
|
||
using BaseGames.Core.Events;
|
||
using BaseGames.Combat;
|
||
using BaseGames.Combat.StatusEffects;
|
||
using BaseGames.Equipment;
|
||
using BaseGames.Parry;
|
||
using BaseGames.Player;
|
||
using BaseGames.Dialogue;
|
||
using BaseGames.Progression;
|
||
using System.IO;
|
||
|
||
namespace BaseGames.Editor
|
||
{
|
||
/// <summary>
|
||
/// Editor 工具:一键在 Assets/_Game/Data/Events/ 下生成所有全局事件频道 .asset 资产。
|
||
/// 菜单:BaseGames → Tools → Create Event Channel Assets
|
||
/// 已存在的资产会自动跳过(幂等)。
|
||
/// </summary>
|
||
public static class CreateEventChannelAssets
|
||
{
|
||
private const string RootPath = "Assets/_Game/Data/Events";
|
||
|
||
[MenuItem("BaseGames/Events/Create Event Channels")]
|
||
public static void CreateAll()
|
||
{
|
||
// ── Core 原始类型频道 ──────────────────────────────────────────────
|
||
CreateAsset<VoidEventChannelSO> ("Core", "EVT_Void");
|
||
CreateAsset<BoolEventChannelSO> ("Core", "EVT_Bool");
|
||
CreateAsset<IntEventChannelSO> ("Core", "EVT_Int");
|
||
CreateAsset<FloatEventChannelSO> ("Core", "EVT_Float");
|
||
CreateAsset<StringEventChannelSO> ("Core", "EVT_String");
|
||
CreateAsset<Vector2EventChannelSO> ("Core", "EVT_Vector2");
|
||
CreateAsset<TransformEventChannelSO> ("Core", "EVT_Transform");
|
||
CreateAsset<GameStateEventChannelSO> ("Core", "EVT_GameStateChanged");
|
||
CreateAsset<SceneLoadRequestEventChannelSO>("Core", "EVT_SceneLoadRequest");
|
||
CreateAsset<StringEventChannelSO> ("Core", "EVT_SceneLoaded");
|
||
CreateAsset<VoidEventChannelSO> ("Core", "EVT_FadeInRequest");
|
||
CreateAsset<VoidEventChannelSO> ("Core", "EVT_FadeOutRequest");
|
||
CreateAsset<VoidEventChannelSO> ("Core", "EVT_SceneWorldStateRestored"); // 场景加载完毕、世界状态恢复后触发;场景物体在此订阅并应用存档状态,淡入前保证画面正确
|
||
|
||
// ── 难度 ──────────────────────────────────────────────────────────
|
||
CreateAsset<DifficultyChangedEventChannel>("Difficulty", "EVT_DifficultyChanged");
|
||
|
||
// ── 战斗 ──────────────────────────────────────────────────────────
|
||
CreateAsset<DamageInfoEventChannelSO> ("Combat", "EVT_DamageDealt");
|
||
CreateAsset<HitConfirmedEventChannelSO> ("Combat", "EVT_HitConfirmed");
|
||
CreateAsset<VoidEventChannelSO> ("Combat", "EVT_NailClash");
|
||
CreateAsset<VoidEventChannelSO> ("Combat", "EVT_PlayerDied");
|
||
CreateAsset<VoidEventChannelSO> ("Combat", "EVT_DeathScreenConfirmed");
|
||
CreateAsset<StringEventChannelSO> ("Combat", "EVT_EnemyDied");
|
||
CreateAsset<ParryInfoEventChannelSO> ("Combat", "EVT_ParrySuccess");
|
||
CreateAsset<VoidEventChannelSO> ("Combat", "EVT_PlayerRespawned");
|
||
CreateAsset<VoidEventChannelSO> ("Combat", "EVT_RespawnStarted");
|
||
CreateAsset<VoidEventChannelSO> ("Combat", "EVT_RespawnCompleted");
|
||
CreateAsset<VoidEventChannelSO> ("Combat", "EVT_CheckpointRespawn");
|
||
CreateAsset<StatusEffectEventChannelSO> ("Combat", "EVT_StatusEffectApplied");
|
||
CreateAsset<StatusEffectEventChannelSO> ("Combat", "EVT_StatusEffectExpired");
|
||
CreateAsset<VoidEventChannelSO> ("Combat", "EVT_ShieldBroken");
|
||
CreateAsset<VoidEventChannelSO> ("Combat", "EVT_ShieldRestored");
|
||
|
||
// ── Boss ──────────────────────────────────────────────────────────
|
||
CreateAsset<BossSkillEventChannelSO> ("Boss", "EVT_BossSkill");
|
||
CreateAsset<BossPhaseEventChannelSO> ("Boss", "EVT_BossPhase");
|
||
CreateAsset<BossPhaseEventChannelSO> ("Boss", "EVT_BossPhaseChanged");
|
||
CreateAsset<StringEventChannelSO> ("Boss", "EVT_BossDefeated");
|
||
CreateAsset<StatusEffectEventChannelSO> ("Boss", "EVT_StatusEffect");
|
||
CreateAsset<StringEventChannelSO> ("Boss", "EVT_BossFightStarted");
|
||
CreateAsset<BoolEventChannelSO> ("Boss", "EVT_BossFightEnded");
|
||
|
||
// ── 任务 ──────────────────────────────────────────────────────────
|
||
CreateAsset<QuestStateChangedEventChannel>("Quest", "EVT_QuestStateChanged");
|
||
CreateAsset<QuestObjectiveEventChannelSO> ("Quest", "EVT_QuestObjective");
|
||
|
||
// ── UI ────────────────────────────────────────────────────────────
|
||
CreateAsset<VoidEventChannelSO> ("UI", "EVT_PauseRequested");
|
||
CreateAsset<VoidEventChannelSO> ("UI", "EVT_PauseResumed");
|
||
CreateAsset<VoidEventChannelSO> ("UI", "EVT_FastTravelOpen");
|
||
CreateAsset<StringEventChannelSO> ("UI", "EVT_ShopOpen");
|
||
CreateAsset<VoidEventChannelSO> ("UI", "EVT_MapOpen");
|
||
CreateAsset<ColorblindModeEventChannelSO> ("UI", "EVT_ColorblindMode");
|
||
CreateAsset<BoolEventChannelSO> ("UI", "EVT_InputDeviceChanged");
|
||
CreateAsset<BoolEventChannelSO> ("UI", "EVT_SaveIndicatorVisible");
|
||
|
||
// ── 启动流程 / Splash ─────────────────────────────────────────────
|
||
CreateAsset<VoidEventChannelSO> ("UI/Splash", "EVT_SplashStartRequest");
|
||
CreateAsset<VoidEventChannelSO> ("UI/Splash", "EVT_SplashComplete");
|
||
|
||
// ── 启动流程 / Loading 画面 ───────────────────────────────────────
|
||
CreateAsset<VoidEventChannelSO> ("UI/Loading", "EVT_LoadingStarted");
|
||
CreateAsset<VoidEventChannelSO> ("UI/Loading", "EVT_LoadingComplete");
|
||
CreateAsset<FloatEventChannelSO> ("UI/Loading", "EVT_LoadingProgressUpdated");
|
||
CreateAsset<BoolEventChannelSO> ("UI/Loading", "EVT_LoadingOverlay");
|
||
|
||
// ── 启动流程 / 主菜单 ─────────────────────────────────────────────
|
||
CreateAsset<IntEventChannelSO> ("UI/MainMenu", "EVT_SlotConfirmed");
|
||
|
||
// ── World ─────────────────────────────────────────────────────────
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_SavePointActivated");
|
||
CreateAsset<VoidEventChannelSO> ("World", "EVT_CheckpointReached");
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_DoorOpened"); // 开门/交互机关(钥匙、机关等)触发自动存档
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_ItemPickup"); // 道具/收集品获取(itemId)
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_CollectiblePickup"); // 关键物品拾取(护符、道具等)触发存档;AutoSaveService / QuestManager / EventChainManager 监听
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_CollectibleSaved"); // 持久化记录收集品(collectibleId)
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_RoomEntered"); // 玩家进入新房间(roomId)
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_RegionChanged"); // 玩家首次进入新区域(regionId)
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_RevealRegion"); // 触发地图区域揭露(regionId)
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_MapUpdated"); // 房间首次探索/标注时刷新(roomId);MapManager 发布,MapPanel 订阅
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_ChallengeCompleted"); // 挑战房间通关(challengeId)
|
||
CreateAsset<StringEventChannelSO> ("World", "EVT_ChallengeFailed"); // 挑战房间失败(challengeId)
|
||
CreateAsset<LiquidEventChannelSO> ("World", "EVT_LiquidEntered"); // 玩家进入液体区域
|
||
CreateAsset<LiquidEventChannelSO> ("World", "EVT_LiquidExited"); // 玩家离开液体区域
|
||
CreateAsset<BaseGames.World.WorldMarkerEventChannelSO>("World", "EVT_WorldMarkerActivated"); // 导航标记点激活(地图图标显示)
|
||
CreateAsset<BaseGames.World.WorldMarkerEventChannelSO>("World", "EVT_WorldMarkerDeactivated"); // 导航标记点失活(地图图标隐藏)
|
||
|
||
// ── 对话/商店 ─────────────────────────────────────────────────────
|
||
CreateAsset<ShopPurchaseEventChannelSO> ("Dialogue", "EVT_ShopPurchase");
|
||
CreateAsset<DialogueEventChannelSO> ("Dialogue", "EVT_DialogueStartRequest");
|
||
CreateAsset<VoidEventChannelSO> ("Dialogue", "EVT_DialogueEnded");
|
||
CreateAsset<VoidEventChannelSO> ("Dialogue", "EVT_ShopClosed");
|
||
|
||
// ── 玩家能力 ──────────────────────────────────────────────────────
|
||
CreateAsset<TransformEventChannelSO> ("Player", "EVT_PlayerSpawned");
|
||
CreateAsset<IntEventChannelSO> ("Player", "EVT_HPChanged");
|
||
CreateAsset<IntEventChannelSO> ("Player", "EVT_MaxHPChanged");
|
||
CreateAsset<IntEventChannelSO> ("Player", "EVT_SoulPowerChanged");
|
||
CreateAsset<IntEventChannelSO> ("Player", "EVT_SpiritPowerChanged");
|
||
CreateAsset<IntEventChannelSO> ("Player", "EVT_SpringChargesChanged");
|
||
CreateAsset<IntEventChannelSO> ("Player", "EVT_LingZhuChanged");
|
||
CreateAsset<AbilityTypeEventChannelSO> ("Player", "EVT_AbilityUnlocked");
|
||
CreateAsset<StringEventChannelSO> ("Player", "EVT_AbilityUnlockedStr");
|
||
CreateAsset<IntEventChannelSO> ("Player", "EVT_FormChanged");
|
||
CreateAsset<VoidEventChannelSO> ("Player", "EVT_SkillSetChanged");
|
||
|
||
// ── 音频 ──────────────────────────────────────────────────────────
|
||
CreateAsset<StringEventChannelSO> ("Audio", "EVT_BGMRequest");
|
||
CreateAsset<VoidEventChannelSO> ("Audio", "EVT_BGMStop");
|
||
|
||
// ── 进度/成就 ─────────────────────────────────────────────────────
|
||
CreateAsset<ToolUsedEventChannelSO> ("Progression", "EVT_ToolUsed");
|
||
CreateAsset<AchievementEventChannelSO> ("Progression", "EVT_AchievementUnlocked");
|
||
CreateAsset<StringEventChannelSO> ("Progression", "EVT_MaxHPContainerPickedUp");
|
||
CreateAsset<VoidEventChannelSO> ("Progression", "EVT_AchievementNotchGranted");
|
||
CreateAsset<CharmEventChannelSO> ("Progression", "EVT_CharmEquipped");
|
||
CreateAsset<CharmEventChannelSO> ("Progression", "EVT_CharmUnequipped");
|
||
CreateAsset<VoidEventChannelSO> ("Progression", "EVT_EquipmentChanged");
|
||
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
|
||
Debug.Log("[CreateEventChannelAssets] 所有事件频道资产生成完毕。");
|
||
}
|
||
|
||
[MenuItem("BaseGames/Events/Reimport Event Channels")]
|
||
public static void ReimportAllEventAssets()
|
||
{
|
||
if (!AssetDatabase.IsValidFolder(RootPath))
|
||
{
|
||
Debug.LogWarning($"[CreateEventChannelAssets] 未找到目录: {RootPath}");
|
||
return;
|
||
}
|
||
|
||
string absoluteRoot = Path.Combine(Directory.GetCurrentDirectory(), RootPath);
|
||
string[] files = Directory.GetFiles(absoluteRoot, "*.asset", SearchOption.AllDirectories);
|
||
|
||
int count = 0;
|
||
foreach (string file in files)
|
||
{
|
||
string relativePath = "Assets" + file.Replace('\\', '/').Substring(Directory.GetCurrentDirectory().Length);
|
||
AssetDatabase.ImportAsset(relativePath, ImportAssetOptions.ForceUpdate);
|
||
count++;
|
||
}
|
||
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
Debug.Log($"[CreateEventChannelAssets] 已重导入 {count} 个事件资产。");
|
||
}
|
||
|
||
private static void CreateAsset<T>(string subfolder, string assetName) where T : ScriptableObject
|
||
{
|
||
string folderPath = $"{RootPath}/{subfolder}";
|
||
EnsureDirectory(folderPath);
|
||
|
||
string fullPath = $"{folderPath}/{assetName}.asset";
|
||
if (AssetDatabase.LoadAssetAtPath<T>(fullPath) != null)
|
||
{
|
||
Debug.Log($"[CreateEventChannelAssets] 已跳过(已存在): {fullPath}");
|
||
return;
|
||
}
|
||
|
||
// 存在但类型不匹配(如旧版残留),先删除再重建
|
||
if (AssetDatabase.LoadMainAssetAtPath(fullPath) != null)
|
||
{
|
||
AssetDatabase.DeleteAsset(fullPath);
|
||
Debug.Log($"[CreateEventChannelAssets] 已删除旧类型资产: {fullPath}");
|
||
}
|
||
|
||
T asset = ScriptableObject.CreateInstance<T>();
|
||
AssetDatabase.CreateAsset(asset, fullPath);
|
||
Debug.Log($"[CreateEventChannelAssets] 已创建: {fullPath}");
|
||
}
|
||
|
||
/// <summary>递归创建所有缺失的中间文件夹(使用 AssetDatabase API)。</summary>
|
||
private static void EnsureDirectory(string path)
|
||
{
|
||
if (AssetDatabase.IsValidFolder(path))
|
||
return;
|
||
|
||
string[] parts = path.Split('/');
|
||
string current = parts[0];
|
||
for (int i = 1; i < parts.Length; i++)
|
||
{
|
||
string next = $"{current}/{parts[i]}";
|
||
if (!AssetDatabase.IsValidFolder(next))
|
||
AssetDatabase.CreateFolder(current, parts[i]);
|
||
current = next;
|
||
}
|
||
}
|
||
}
|
||
}
|