项目仓库: Gitee | GitHub 在线试玩:ARPG WebGL Demo
My ARPG 基于 Unity 2022.3.62f3c1,覆盖场景切换、状态恢复、条件对话、任务推进、商店交互、UI 管理和存档系统。资源加载用 Addressables,输入用 Input System,模块通信用 ScriptableObject 事件。
对象
工程分场景层、状态层、导航层、交互层和存档层。
场景层:InitialLoad、SceneChanger、SceneLoadEventSO、GameSceneSO——持久场景和地图切换。状态层:DataManager、ISaveable、DataDefinition、Data——对象注册、数据分发、持久化标识。导航层:AStarPathFinder、AStarNodeManager、PathFinderDetails,底层用 Dictionary<Vector3, PathFinderDetails> + HashSet<Vector3>。交互层:NPCStateController、NPCWander、NPCPatrol、NPCChat、ShopKeeper、DialogSO、DialogLine、DialogOption、RefuseDialogSO、QuestSO、QuestObjective、Reward、QuestProgressData、ShopManager、UIManager、UIInputState。存档层:DataManager + UIManager 协同,游戏场景内支持 Save/Load,菜单场景内 Save 切换为 Delete。
职责
SceneChanger——场景卸载、加载、玩家坐标切换、输入恢复。DataManager——Save()、Load()、ISaveable 注册表。AStarPathFinder——FindPath()、WorldToCell()、CellToWorld()、GetNodeMap()。AStarNodeManager——导航节点生成。
交互层按模块拆开。NPCStateController 维护 Idle/Wander/Patrol/Chat 状态流。NPCChat 把交互请求交给 DialogManager,ShopKeeper 把商店请求交给 ShopManager。DialogManager 负责 MatchConditionsToStartDialog()、分支选择、DialogSO.HasChated;RefuseDialogSO 继承 DialogSO,处理条件不满足时的拒绝分支。QuestManager 用 Dictionary<QuestSO, QuestProgressData> + Dictionary<QuestObjective, int> 维护任务状态。UIManager 负责 ToggleCanvasEventSO、ResetCanvas()、面板互斥和存档画布组。UIInputState 通过配置 SO 和状态机逻辑管理集成菜单与面板的互斥关系。
流程
场景流程:SceneLoadEventSO → SceneChanger.OnEnable() → LoadSceneMode.Additive → OnLoadCompleted()。传送门、菜单、碰撞脚本只发切换请求,坐标写入 newPosition,缺失时回退到 GameSceneSO.initialPosition。
状态流程:VoidEventSO → DataManager.Save() / Load()。DataManager 带 [DefaultExecutionOrder(-100)],先建 List<ISaveable>,再把 Data 分发给各对象。对象侧实现 GetDataID()、SaveData()、LoadData(),用 DataDefinition.ID 定位,Data.lootsStatsDic 恢复战利品状态。
寻路流程:FindPath() → SearchCheapestCost() → AddNodeToOpen() → CanWalkDiagonally()。optPos 前移起点,NoCoverObstacleNodes() 检查直线路径,对角移动受相邻阻挡检测约束。
对话流程:NPCChat → DialogManager → MatchConditionsToStartDialog() → DialogSO / DialogOption。角色条件读 ConversationHistoryManager.CharactersHasChated,物品条件读 ItemHistoryManager.HasPickedOverAmount(),一次性条件读 DialogSO.HasChated。
任务流程:QuestManager.UpdateObjectiveProgress() 直接读历史数据。奖励由 RaiseRewardEvent() 写入 InventorySlotsStatsSO,走事件进入库存更新流程。
商店流程:ShopLoadEventSO → ShopManager.OnShopLoad() → PopulateShopItems()。买卖都经过 RaiseInventoryUpdateRequest(),出售时价格和数量取负值,共用同一条库存更新链路。
UI 流程:输入检测 → ToggleCanvasEventSO → CanvasGroup 开关,切场景时 ResetCanvas() 清空残留。集成菜单通过 UIInputState 管理面板入口,部分菜单需满足触发条件(接近 NPC 或任务板)才可打开。面板支持”X”关闭、拖动顶部移动、focus(sortOrder)。
存档流程:游戏场景内提供 Save/Load 按钮,菜单场景内 Save 切换为 Delete。存档逻辑通过 DataManager 的 Save()/Load() 接口与 UI 层连接。
边界
- 场景切换:
SceneChanger集中处理,外层对象只保留请求入口 - 状态保存:
DataManager+ISaveable,对象侧只处理序列化字段 - 寻路:
AStarPathFinder+AStarNodeManager,NPC/敌人/交互物共享导航数据,不持有网格生成逻辑 - 对话:
DialogManager依赖历史数据,不依赖移动逻辑;RefuseDialogSO继承DialogSO,条件判断与对话内容在同一数据对象内,不依赖外部枚举匹配 - 任务:
QuestManager依赖历史系统,不维护对话状态 - UI:
UIManager处理面板开关和存档画布组,不处理任务、商店、对话数据;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,可删除存档。
场景切换
木桥走到尽头切换场景。
部分信息可能已经过时
粤公网安备44011102484817号