1233 字
6 分钟
My ARPG:场景切换、对话、任务和 UI 管理的 Unity 2D ARPG 原型

项目仓库: Gitee | GitHub 在线试玩:ARPG WebGL Demo

My ARPG 基于 Unity 2022.3.62f3c1,覆盖场景切换、状态恢复、条件对话、任务推进、商店交互、UI 管理和存档系统。资源加载用 Addressables,输入用 Input System,模块通信用 ScriptableObject 事件。

对象#

工程分场景层、状态层、导航层、交互层和存档层。

场景层:InitialLoadSceneChangerSceneLoadEventSOGameSceneSO——持久场景和地图切换。状态层:DataManagerISaveableDataDefinitionData——对象注册、数据分发、持久化标识。导航层:AStarPathFinderAStarNodeManagerPathFinderDetails,底层用 Dictionary<Vector3, PathFinderDetails> + HashSet<Vector3>。交互层:NPCStateControllerNPCWanderNPCPatrolNPCChatShopKeeperDialogSODialogLineDialogOptionRefuseDialogSOQuestSOQuestObjectiveRewardQuestProgressDataShopManagerUIManagerUIInputState。存档层:DataManager + UIManager 协同,游戏场景内支持 Save/Load,菜单场景内 Save 切换为 Delete。

职责#

SceneChanger——场景卸载、加载、玩家坐标切换、输入恢复。DataManager——Save()Load()ISaveable 注册表。AStarPathFinder——FindPath()WorldToCell()CellToWorld()GetNodeMap()AStarNodeManager——导航节点生成。

交互层按模块拆开。NPCStateController 维护 Idle/Wander/Patrol/Chat 状态流。NPCChat 把交互请求交给 DialogManagerShopKeeper 把商店请求交给 ShopManagerDialogManager 负责 MatchConditionsToStartDialog()、分支选择、DialogSO.HasChatedRefuseDialogSO 继承 DialogSO,处理条件不满足时的拒绝分支。QuestManagerDictionary<QuestSO, QuestProgressData> + Dictionary<QuestObjective, int> 维护任务状态。UIManager 负责 ToggleCanvasEventSOResetCanvas()、面板互斥和存档画布组。UIInputState 通过配置 SO 和状态机逻辑管理集成菜单与面板的互斥关系。

流程#

场景流程SceneLoadEventSOSceneChanger.OnEnable()LoadSceneMode.AdditiveOnLoadCompleted()。传送门、菜单、碰撞脚本只发切换请求,坐标写入 newPosition,缺失时回退到 GameSceneSO.initialPosition

状态流程VoidEventSODataManager.Save() / Load()DataManager[DefaultExecutionOrder(-100)],先建 List<ISaveable>,再把 Data 分发给各对象。对象侧实现 GetDataID()SaveData()LoadData(),用 DataDefinition.ID 定位,Data.lootsStatsDic 恢复战利品状态。

寻路流程FindPath()SearchCheapestCost()AddNodeToOpen()CanWalkDiagonally()optPos 前移起点,NoCoverObstacleNodes() 检查直线路径,对角移动受相邻阻挡检测约束。

对话流程NPCChatDialogManagerMatchConditionsToStartDialog()DialogSO / DialogOption。角色条件读 ConversationHistoryManager.CharactersHasChated,物品条件读 ItemHistoryManager.HasPickedOverAmount(),一次性条件读 DialogSO.HasChated

任务流程QuestManager.UpdateObjectiveProgress() 直接读历史数据。奖励由 RaiseRewardEvent() 写入 InventorySlotsStatsSO,走事件进入库存更新流程。

商店流程ShopLoadEventSOShopManager.OnShopLoad()PopulateShopItems()。买卖都经过 RaiseInventoryUpdateRequest(),出售时价格和数量取负值,共用同一条库存更新链路。

UI 流程:输入检测 → ToggleCanvasEventSOCanvasGroup 开关,切场景时 ResetCanvas() 清空残留。集成菜单通过 UIInputState 管理面板入口,部分菜单需满足触发条件(接近 NPC 或任务板)才可打开。面板支持”X”关闭、拖动顶部移动、focus(sortOrder)。

存档流程:游戏场景内提供 Save/Load 按钮,菜单场景内 Save 切换为 Delete。存档逻辑通过 DataManagerSave()/Load() 接口与 UI 层连接。

边界#

  • 场景切换SceneChanger 集中处理,外层对象只保留请求入口
  • 状态保存DataManager + ISaveable,对象侧只处理序列化字段
  • 寻路AStarPathFinder + AStarNodeManager,NPC/敌人/交互物共享导航数据,不持有网格生成逻辑
  • 对话DialogManager 依赖历史数据,不依赖移动逻辑;RefuseDialogSO 继承 DialogSO,条件判断与对话内容在同一数据对象内,不依赖外部枚举匹配
  • 任务QuestManager 依赖历史系统,不维护对话状态
  • UIUIManager 处理面板开关和存档画布组,不处理任务、商店、对话数据;UIInputState 管理输入状态,不持有业务数据
  • NPC:本体不持有对话 UI、商店 UI、任务 UI

限制#

当前版本覆盖场景切换、状态恢复、条件对话、任务统计、商店、面板互斥、集成菜单和存档系统。背包系统已实装,支持物品使用、出售和丢弃。Settings 菜单、移动端摇杆适配、敌人状态持久化和地图交互对象仍在补全。

操作指南#

移动#

WASD 控制角色移动。

战斗#

按键功能
Q切换远程(弓箭手)/ 近战(剑士)
J弓箭手射箭
K剑士挥砍

剑士模式下每次挥砍使面板伤害 +1(血怒机制)。

面板交互#

左下角集成菜单统一管理所有面板入口。能力面板和技能面板可直接打开,其余需要触发条件——比如走到 NPC 或任务板附近。

面板支持”X”关闭、拖动顶部移动,最近操作的面板显示在最上层(focus / sortOrder)。

按键 / 入口功能
能力面板集成菜单打开
技能面板集成菜单打开,左键槽位消耗技能点解锁
F与商店交互
T打开 / 关闭 NPC 对话,左键推进、选择
C任务菜单
ESC退出菜单——返回菜单、存档、退出游戏

死亡自动弹出 GameOver 菜单。

物品栏#

操作效果
左键(普通)使用物品
左键(商店打开时)出售物品
右键丢弃物品

丢弃的物品在场景重载时不保留(包括场景切换和 Retry)。

存档#

游戏场景内点击 Save / Load 存档和读档。菜单场景内 Save 变为 Delete,可删除存档。

场景切换#

木桥走到尽头切换场景。


配套开发日志:My ARPG 开发日志

My ARPG:场景切换、对话、任务和 UI 管理的 Unity 2D ARPG 原型
https://www.yonagi.world/posts/unity-arpg-project-intro/
作者
YONAGI
发布于
2026-06-02
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

封面
遠い日に想いを馳せて
Laplacian
封面
遠い日に想いを馳せて
Laplacian
0:00 / 0:00