新增独立的场景加载功能: 全局脚本和"加载场景"
This commit is contained in:
parent
5f61a2fb9c
commit
dbf6357bf1
26
Autoload/LoadingContext.gd
Normal file
26
Autoload/LoadingContext.gd
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# LoadingContext.gd
|
||||||
|
# Autoload Singleton
|
||||||
|
# 负责在 start 场景和 LoadingScene 之间传递加载指令和必要的存档数据。
|
||||||
|
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
# 加载操作的类型
|
||||||
|
# 可能的值: "new_game", "load_game", 或空字符串 (表示无操作或已处理)
|
||||||
|
var action_to_perform: String = ""
|
||||||
|
|
||||||
|
# 当 action_to_perform 为 "load_game" 时,这里会存储从 SaveLoadManager 加载到的存档数据字典。
|
||||||
|
# 其他情况下应为空字典。
|
||||||
|
var save_data_for_loading: Dictionary = {}
|
||||||
|
|
||||||
|
|
||||||
|
# 清理上下文,在 LoadingScene 读取完数据后调用,避免旧数据影响下一次加载。
|
||||||
|
func clear_context() -> void:
|
||||||
|
action_to_perform = ""
|
||||||
|
save_data_for_loading = {}
|
||||||
|
print("LoadingContext: Context cleared.")
|
||||||
|
|
||||||
|
# (可选) 一个辅助函数,用于在设置上下文时打印信息,方便调试
|
||||||
|
func set_context(action: String, data: Dictionary = {}) -> void:
|
||||||
|
action_to_perform = action
|
||||||
|
save_data_for_loading = data.duplicate(true) # 使用深拷贝以防外部修改
|
||||||
|
print("LoadingContext: Context set - Action: ", action_to_perform, ", Data keys: ", save_data_for_loading.keys())
|
||||||
1
Autoload/LoadingContext.gd.uid
Normal file
1
Autoload/LoadingContext.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://cmx5osjpib4n5
|
||||||
@ -1,6 +1,6 @@
|
|||||||
# 核心 Autoload 管理器说明文档 (v1.4 - 基于代码审查)
|
# 核心 Autoload 管理器说明文档 (v1.5 - 基于代码审查与新增 LoadingContext)
|
||||||
|
|
||||||
**文档目的:** 本文档旨在详细说明游戏核心的四个 Autoload 管理器 (`InitializationManager`, `InitialDataManager`, `GameState`, `SaveLoadManager`) 的设计、职责、交互方式以及对外提供的接口(API)。**特别注意:本文档描述的是基于“数据枢纽”模型的架构,并已根据最新代码实现进行更新。** 它是后续开发其他游戏玩法模块(如员工管理、项目管理、UI 等)时的**主要参考依据**,确保各模块能正确、高效地与核心系统协作。
|
**文档目的:** 本文档旨在详细说明游戏核心的五个 Autoload 管理器 (`InitializationManager`, `InitialDataManager`, `GameState`, `SaveLoadManager`, `LoadingContext`) 的设计、职责、交互方式以及对外提供的接口(API)。**特别注意:本文档描述的是基于“数据枢纽”模型的架构,并已根据最新代码实现进行更新。** 它是后续开发其他游戏玩法模块(如员工管理、项目管理、UI 等)时的**主要参考依据**,确保各模块能正确、高效地与核心系统协作。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -11,8 +11,8 @@
|
|||||||
1. **Key 管理:** 定义并维护模块自身所需状态数据在 `GameState` 中的唯一 `key`。建议采用命名空间或前缀避免冲突 (e.g., `"employee.list"`, `"project.active_ids"`)。
|
1. **Key 管理:** 定义并维护模块自身所需状态数据在 `GameState` 中的唯一 `key`。建议采用命名空间或前缀避免冲突 (e.g., `"employee.list"`, `"project.active_ids"`)。
|
||||||
2. **数据结构定义:** 定义与模块相关的 `key` 所对应的 `value` 的具体数据结构(字典、数组、基础类型等)。
|
2. **数据结构定义:** 定义与模块相关的 `key` 所对应的 `value` 的具体数据结构(字典、数组、基础类型等)。
|
||||||
3. **初始化/状态恢复:**
|
3. **初始化/状态恢复:**
|
||||||
* **必须**监听 `GameState` 的 `state_restored` 信号。
|
* **必须**监听 `GameState` 的 `state_restored` 信号 (用于读档后恢复) 以及 `state_initialized` 信号 (用于新游戏初始化后,如果模块需要在此时进行特定设置)。
|
||||||
* 在该信号的回调函数中,调用 `GameState.get_value(key)` 来获取本模块所需的所有数据。
|
* 在这些信号的回调函数中,调用 `GameState.get_value(key)` 来获取本模块所需的所有数据。
|
||||||
* 使用获取到的数据完成模块自身的初始化或状态恢复(更新内部变量、刷新 UI 等)。
|
* 使用获取到的数据完成模块自身的初始化或状态恢复(更新内部变量、刷新 UI 等)。
|
||||||
4. **数据读取与更新:** 通过 `GameState.get_value(key)` 读取状态,通过 `GameState.set_value(key, new_value)` 更新状态。
|
4. **数据读取与更新:** 通过 `GameState.get_value(key)` 读取状态,通过 `GameState.set_value(key, new_value)` 更新状态。
|
||||||
5. **业务逻辑验证:** **所有**业务逻辑相关的验证(如花钱前检查余额、操作是否允许等)**必须**在调用 `GameState.set_value` **之前**由模块自身完成。`GameState` 不进行任何业务逻辑校验。
|
5. **业务逻辑验证:** **所有**业务逻辑相关的验证(如花钱前检查余额、操作是否允许等)**必须**在调用 `GameState.set_value` **之前**由模块自身完成。`GameState` 不进行任何业务逻辑校验。
|
||||||
@ -25,40 +25,40 @@
|
|||||||
### 目标 (Purpose/Goal)
|
### 目标 (Purpose/Goal)
|
||||||
* 作为游戏启动流程的总控制器,统一协调新游戏开始或存档加载的准备工作。
|
* 作为游戏启动流程的总控制器,统一协调新游戏开始或存档加载的准备工作。
|
||||||
* 确保在通知模块进行状态恢复前,`GameState` 已被正确的数据填充。
|
* 确保在通知模块进行状态恢复前,`GameState` 已被正确的数据填充。
|
||||||
* 提供一个清晰的入口点来响应用户的启动选择(新游戏/加载)。
|
* 提供一个清晰的入口点来响应用户的启动选择(新游戏/加载),通常由加载场景(Loading Scene)在获取必要数据后调用。
|
||||||
|
|
||||||
### 核心职责 (Responsibilities)
|
### 核心职责 (Responsibilities)
|
||||||
* **流程决策:** 根据用户输入(来自主菜单 UI),决定启动“新游戏”流程还是“载入存档”流程。
|
* **流程决策:** 根据传递的指令(通常来自加载场景,该场景会根据 `LoadingContext` 的信息决定)启动“新游戏”流程还是“载入存档”流程。
|
||||||
* **数据准备:**
|
* **数据准备:**
|
||||||
* **新游戏:** 确保 `InitialDataManager` 数据加载完成 -> 调用 `InitialDataManager` 获取初始数据 (`settings_data`, `task_dev_data`, `npc_initial_data`) -> **调用 `_build_initial_state` 方法,根据获取的数据构建注入 `GameState` 的初始状态字典。此方法会:**
|
* **新游戏:** 确保 `InitialDataManager` 数据加载完成 -> 调用 `InitialDataManager` 获取初始数据 (`settings_data`, `task_dev_data`, `npc_initial_data`) -> **调用 `_build_initial_state` 方法,根据获取的数据构建注入 `GameState` 的初始状态字典。此方法会:**
|
||||||
* **合并基础设置 (`Init_Base.json`) 到状态字典的顶层。**
|
* **合并基础设置 (`Init_Base.json` 的内容,通过 `settings_data` 传入) 到状态字典的顶层 (进行深拷贝)。**
|
||||||
* **处理任务开发相关数据 (`task_development.json`),提取其中需要动态追踪的状态(如平台的 `enabled`, `Market_share`;玩法/主题的 `enabled`, `Experience`;策略的 `enabled`;产品侧重点的完整结构),并将这些动态状态组织在一个名为 `"task_development"` 的子字典内,再将该子字典存入主状态字典。**
|
* **处理任务开发相关数据 (`task_development.json` 的内容,通过 `task_dev_data` 传入),将其内部定义的 "platforms", "gameplays", "themes", "strategies", "product_focus_points" 等数据(经过深拷贝)组织在一个名为 `"task_development"` 的子字典内,再将该子字典存入主状态字典。**
|
||||||
* **处理 NPC 数据 (`npc.json`),将从 `npc_initial_data` 中获取的 NPC 定义(通常是 `npc_defs["npc"]` 部分,即 `npc.json` 文件中 "npc" 键对应的值)存入主状态字典的 `"npcs"` 键下。**
|
* **处理 NPC 数据 (`npc.json` 的内容,通过 `npc_initial_data` 传入),将从 `npc_initial_data` 中获取的 NPC 定义 (通常是 `npc_initial_data["npc"]` 部分,即 `npc.json` 文件中 "npc" 键对应的值,进行深拷贝) 存入主状态字典的 `"npcs"` 键下。**
|
||||||
* **载入存档:** **接收**由外部(例如存档选择 UI,它会调用 `SaveLoadManager.load_game`)加载并传入的存档数据字典。
|
* **载入存档:** **接收**由外部(例如加载场景,它会从 `LoadingContext` 获取由 `SaveLoadManager.load_game` 加载的存档数据)传入的存档数据字典 (`save_data`)。
|
||||||
* **数据注入:**
|
* **数据注入:**
|
||||||
* **新游戏:** 将构建好的初始状态字典传递给 `GameState.initialize_for_new_game()`。
|
* **新游戏:** 将构建好的初始状态字典传递给 `GameState.initialize_for_new_game()`。
|
||||||
* **载入存档:** 将接收到的存档数据字典传递给 `GameState.restore_state()`。
|
* **载入存档:** 将接收到的存档数据字典传递给 `GameState.restore_state()`。
|
||||||
* **流程控制:** 管理初始化过程中的用户反馈(如显示/隐藏加载界面),并在 `GameState` 准备就绪后(通过信号通知),触发到主游戏场景的切换(此部分逻辑通常在此管理器或调用它的 UI 中实现)。
|
* **流程控制:** 管理初始化过程中的用户反馈(如显示/隐藏加载界面,通常由调用此管理器的加载场景处理),并在 `GameState` 准备就绪后(通过信号通知),触发到主游戏场景的切换(此部分逻辑通常在此管理器触发信号后,由加载场景或主UI控制器实现)。
|
||||||
* **错误处理:** 捕获并处理在初始化过程中(如 `InitialDataManager` 加载失败、构建初始状态失败)发生的错误,向用户提供反馈并阻止进入游戏。
|
* **错误处理:** 捕获并处理在初始化过程中(如 `InitialDataManager` 加载失败、构建初始状态失败、获取的初始数据为空)发生的错误,向用户提供反馈并阻止进入游戏。
|
||||||
|
|
||||||
### **对外接口 (Public API)**
|
### **对外接口 (Public API)**
|
||||||
* `start_new_game_process() -> bool`: 由主菜单调用,启动新游戏流程。成功返回 `true`,失败返回 `false`。
|
* `start_new_game_process() -> bool`: 由加载场景或等效的流程控制器调用,启动新游戏流程。成功返回 `true`,失败返回 `false`。
|
||||||
* `load_game_process(save_data: Dictionary) -> bool`: **接收**已加载的存档数据字典 `save_data`,启动加载流程。成功返回 `true`,失败返回 `false`。(**注意:** 此函数**不负责**从文件加载数据,它期望 `save_data` 已经被加载好并传入)。
|
* `load_game_process(save_data: Dictionary) -> bool`: 由加载场景或等效的流程控制器调用,**接收**已加载的存档数据字典 `save_data`,启动加载流程。成功返回 `true`,失败返回 `false`。(**注意:** 此函数**不负责**从文件加载数据,它期望 `save_data` 已经被加载好并传入)。
|
||||||
* **注意:** 其他游戏玩法模块通常**不需要**在游戏运行过程中直接调用此管理器。其主要交互对象是启动阶段的 UI。
|
* **注意:** 其他游戏玩法模块通常**不需要**在游戏运行过程中直接调用此管理器。其主要交互对象是启动阶段的加载场景或主菜单后的流程控制逻辑。
|
||||||
|
|
||||||
### **对外信号 (Public Signals)**
|
### **对外信号 (Public Signals)**
|
||||||
* `new_game_initialized`: 在 `start_new_game_process` 成功执行,`GameState` 被初始化后发出。
|
* `new_game_initialized`: 在 `start_new_game_process` 成功执行,`GameState` 被初始化后发出。
|
||||||
* `game_loaded`: 在 `load_game_process` 成功执行,`GameState` 被恢复后发出。
|
* `game_loaded`: 在 `load_game_process` 成功执行,`GameState` 被恢复后发出。
|
||||||
|
|
||||||
### 交互关键点 (Key Interactions)
|
### 交互关键点 (Key Interactions)
|
||||||
* **接收:** 来自 UI 的调用 (`start_new_game_process`, `load_game_process`)。
|
* **接收:** 来自加载场景 (Loading Scene) 或类似流程控制器的调用 (`start_new_game_process`, `load_game_process(save_data)`). `save_data` 通常通过 `LoadingContext` 传递给加载场景。
|
||||||
* **调用:** `InitialDataManager` (在新游戏流程中调用 `ensure_data_loaded`, `get_starting_settings`, `get_task_development_data`, `get_npc_initial_data`), `GameState` (调用 `initialize_for_new_game` 或 `restore_state`)。
|
* **调用:** `InitialDataManager` (在新游戏流程中调用 `ensure_data_loaded`, `get_starting_settings`, `get_task_development_data`, `get_npc_initial_data`), `GameState` (调用 `initialize_for_new_game` 或 `restore_state`)。
|
||||||
* **发出:** `new_game_initialized`, `game_loaded` 信号。
|
* **发出:** `new_game_initialized`, `game_loaded` 信号。
|
||||||
* **(可能)** `SceneTree` (用于切换场景,虽然未在提供的代码片段中直接显示,但通常是其职责一部分)。
|
* **(可能)** 间接影响 `SceneTree` (通过信号触发场景切换,由其他脚本执行)。
|
||||||
|
|
||||||
### 核心逻辑流程 (Core Logic/Flow)
|
### 核心逻辑流程 (Core Logic/Flow)
|
||||||
* **新游戏:** (UI 调用 `start_new_game_process`) -> 显示加载 -> 确保 `InitialDataManager` 就绪 -> 获取初始数据 (`settings`, `task_dev`, `npc_initial_data`) -> **调用 `_build_initial_state` 构建包含 `"task_development"` 和 `"npcs"` 结构的初始状态字典** -> 调用 `GameState.initialize_for_new_game()` -> 发出 `new_game_initialized` 信号 -> (后续逻辑) 切换场景 -> 隐藏加载。
|
* **新游戏:** (UI 设置 `LoadingContext.action_to_perform = "new_game"`) -> (切换到加载场景) -> (加载场景调用 `start_new_game_process`) -> 显示加载 -> 确保 `InitialDataManager` 就绪 -> 获取初始数据 (`settings`, `task_dev`, `npc_initial_data`) -> **调用 `_build_initial_state` 构建包含 `"task_development"` 和 `"npcs"` 结构的初始状态字典** -> 调用 `GameState.initialize_for_new_game()` -> 发出 `new_game_initialized` 信号 -> (后续逻辑,如加载场景处理) 切换到主游戏场景 -> 隐藏加载。
|
||||||
* **载入存档:** (UI 调用 `SaveLoadManager.load_game(slot_id)` 得到 `save_data` 字典) -> (UI 调用 `load_game_process(save_data)`) -> 显示加载 -> (可选:确保 `InitialDataManager` 就绪) -> 调用 `GameState.restore_state(save_data)` -> 发出 `game_loaded` 信号 -> (后续逻辑) 切换场景 -> 隐藏加载。
|
* **载入存档:** (UI 调用 `SaveLoadManager.load_game(slot_id)` 得到 `save_data` 字典) -> (UI 设置 `LoadingContext.set_context("load_game", save_data)`) -> (切换到加载场景) -> (加载场景读取 `LoadingContext` 并调用 `InitializationManager.load_game_process(LoadingContext.save_data_for_loading)`) -> 显示加载 -> (可选:确保 `InitialDataManager` 就绪,以防需要参考静态数据) -> 调用 `GameState.restore_state(save_data)` -> 发出 `game_loaded` 信号 -> (后续逻辑,如加载场景处理) 切换到主游戏场景 -> 隐藏加载。
|
||||||
* 在每个关键步骤后检查成功/失败状态,失败则中止流程并反馈用户。
|
* 在每个关键步骤后检查成功/失败状态,失败则中止流程并反馈用户。
|
||||||
|
|
||||||
### 配置 (Configuration)
|
### 配置 (Configuration)
|
||||||
@ -80,11 +80,11 @@
|
|||||||
* **数据提供:** 通过函数接口提供数据的**深拷贝**副本。
|
* **数据提供:** 通过函数接口提供数据的**深拷贝**副本。
|
||||||
|
|
||||||
### **对外接口 (Public API / Data Access Functions)**
|
### **对外接口 (Public API / Data Access Functions)**
|
||||||
* `ensure_data_loaded() -> bool`: 确保所有必需的初始数据 (`Init_Base.json`, `task_development.json`, `npc.json`) 已加载。通常由 `InitializationManager` 在新游戏流程开始时调用。返回加载是否成功。
|
* `ensure_data_loaded() -> bool`: 确保所有必需的初始数据 (`Init_Base.json`, `task_development.json`, `npc.json`) 已加载。通常由 `InitializationManager` 在新游戏流程开始时或加载游戏流程中调用。返回加载是否成功。
|
||||||
* `get_starting_settings() -> Dictionary`: 获取 `Init_Base.json` 中的初始游戏设定。返回数据的深拷贝。
|
* `get_starting_settings() -> Dictionary`: 获取 `Init_Base.json` 中的初始游戏设定。返回数据的深拷贝。
|
||||||
* `get_task_development_data() -> Dictionary`: 获取 `task_development.json` 中的所有数据。返回数据的深拷贝。
|
* `get_task_development_data() -> Dictionary`: 获取 `task_development.json` 中的所有数据。返回数据的深拷贝。
|
||||||
* `get_npc_initial_data() -> Dictionary`: 获取 `npc.json` 中的所有数据。返回数据的深拷贝。
|
* `get_npc_initial_data() -> Dictionary`: 获取 `npc.json` 中的所有数据。返回数据的深拷贝。
|
||||||
* **数据规范:** 返回的数据结构遵循 JSON 文件结构。所有通过此管理器获取的数据都应视为**只读**。
|
* **数据规范:** 返回的数据结构遵循 JSON 文件结构。所有通过此管理器获取的数据都应视为**只读**。`npc.json` 文件应为字典结构,`task_development.json` 和 `Init_Base.json` 也应为字典结构。
|
||||||
|
|
||||||
### **对外信号 (Public Signals)**
|
### **对外信号 (Public Signals)**
|
||||||
* 通常不发出信号,因为它主要提供静态数据查询。
|
* 通常不发出信号,因为它主要提供静态数据查询。
|
||||||
@ -113,21 +113,21 @@
|
|||||||
### 核心职责 (Responsibilities)
|
### 核心职责 (Responsibilities)
|
||||||
* **状态存储:** 内部维护一个核心字典 (`_state_data`),用于存储所有动态游戏状态的 Key-Value 对。
|
* **状态存储:** 内部维护一个核心字典 (`_state_data`),用于存储所有动态游戏状态的 Key-Value 对。
|
||||||
* **通用状态访问:** 提供通用的 `set_value`, `get_value` 接口。
|
* **通用状态访问:** 提供通用的 `set_value`, `get_value` 接口。
|
||||||
* **状态初始化:** 提供 `initialize_for_new_game` 方法,使用初始设置数据填充状态字典,**并在此过程中调用内部方法(如 `add_init_data`)根据已填充的 `_state_data` 的一部分(例如 `"task_development"`)来进一步初始化其他状态数据(例如 `"task_info"`),** 完成后发出 `state_initialized` 信号。
|
* **状态初始化:** 提供 `initialize_for_new_game` 方法,使用初始设置数据填充状态字典,**并在此过程中调用内部方法 (`add_init_data`),该方法会读取 `_state_data["task_development"]` 中的数据(如平台、玩法、主题、策略的启用状态和产品侧重点配置),用于构建并填充 `_state_data["task_development_info"]` 字典,该字典包含了当前选定的开发相关初始信息。** 完成后发出 `state_initialized` 信号。
|
||||||
* **状态恢复与通知:** 提供 `restore_state` 方法用于接收并覆盖整个状态字典,完成后发出 `state_restored` 信号。
|
* **状态恢复与通知:** 提供 `restore_state` 方法用于接收并覆盖整个状态字典(进行深拷贝),完成后发出 `state_restored` 信号。
|
||||||
* **存档数据提供:** 提供 `get_savable_state` 方法,返回内部状态字典的**深拷贝**副本,供 `SaveLoadManager` 使用。
|
* **存档数据提供:** 提供 `get_savable_state` 方法,返回内部状态字典的**深拷贝**副本,供 `SaveLoadManager` 使用。
|
||||||
* **系统状态管理:** 通过内部的 `"system_status"` 字典(存储在 `_state_data["system_status"]`)管理如游戏暂停 (`game_pause`)、是否在任务中 (`is_on_task`) 等状态。提供方法来修改和查询这些特定状态。
|
* **系统状态管理:** 通过内部的 `"system_status"` 字典(存储在 `_state_data["system_status"]`)管理如游戏暂停 (`game_pause`)、是否在任务中 (`is_on_task`) 等状态。提供方法来修改和查询这些特定状态。
|
||||||
|
|
||||||
### **对外接口 (Public API / Generic State Access)**
|
### **对外接口 (Public API / Generic State Access)**
|
||||||
|
|
||||||
* `initialize_for_new_game(initial_settings: Dictionary) -> void`: **(供 InitializationManager 调用)** 使用 `initial_settings` 字典(进行深拷贝)来初始化内部的 `_state_data`。**随后,会调用一个内部函数 (`add_init_data`),该函数读取 `_state_data` 中已存在的 `"task_development"` 数据,并用其来填充 `_state_data` 中的 `"task_info"` 键。** 完成后发出 `state_initialized` 信号。
|
* `initialize_for_new_game(initial_settings: Dictionary) -> void`: **(供 InitializationManager 调用)** 使用 `initial_settings` 字典(进行深拷贝)来初始化内部的 `_state_data`。**随后,会调用一个内部函数 (`add_init_data`),该函数基于 `_state_data["task_development"]` 的内容(例如,查找各分类如平台、玩法、主题、开发策略中首个标记为 `enabled:true` 的条目,并获取产品侧重点数据)来构建和填充 `_state_data` 中的 `"task_development_info"` 字典(其键包括:"平台"、"玩法"、"题材"、"开发策略"、"预算"、"产品侧重点"等)。** 完成后发出 `state_initialized` 信号。如果 `_state_data` 中存在 `"time"` 键且其值为字典,还会发出 `date_changed` 兼容性信号。
|
||||||
* `restore_state(loaded_data: Dictionary) -> void`: **(供 InitializationManager 调用)** 用 `loaded_data` 字典(进行深拷贝)**完全替换**内部的 `_state_data` 字典,然后发出 `state_restored` 信号。
|
* `restore_state(loaded_data: Dictionary) -> void`: **(供 InitializationManager 调用)** 用 `loaded_data` 字典(进行深拷贝)**完全替换**内部的 `_state_data` 字典,然后发出 `state_restored` 信号。如果 `_state_data` 中存在 `"time"` 键且其值为字典,还会发出 `date_changed` 兼容性信号。
|
||||||
* `get_savable_state() -> Dictionary`: **(供 SaveLoadManager 调用)** 返回内部 `_state_data` 字典的**深拷贝** (`duplicate(true)`),用于存档,确保返回的是当前状态的一个独立快照。
|
* `get_savable_state() -> Dictionary`: **(供 SaveLoadManager 调用)** 返回内部 `_state_data` 字典的**深拷贝** (`duplicate(true)`),用于存档,确保返回的是当前状态的一个独立快照。
|
||||||
* `get_value(key: String, default = null) -> Variant`: 根据 `key` 从内部字典检索 `value`。如果 `key` 不存在,返回 `default` 值。
|
* `get_value(key: String, default = null) -> Variant`: 根据 `key` 从内部字典检索 `value`。如果 `key` 不存在,返回 `default` 值。
|
||||||
* `set_value(key: String, value: Variant) -> void`: 向内部字典设置或更新一个 Key-Value 对。**注意:调用者负责确保 `value` 是可序列化的,并进行必要的业务逻辑验证。** 只有当新值与旧值**通过 `!=` (浅比较) 判断为不同**时,才会实际更新并发出 `state_value_changed` 信号。如果 `key` 是 `"time"` 且 `value` 是字典,还会额外发出 `date_changed` 兼容性信号。
|
* `set_value(key: String, value: Variant) -> void`: 向内部字典设置或更新一个 Key-Value 对。**注意:调用者负责确保 `value` 是可序列化的,并进行必要的业务逻辑验证。** 只有当新值与旧值**通过 `!=` (浅比较) 判断为不同**时,才会实际更新并发出 `state_value_changed` 信号。如果 `key` 是 `"time"` 且 `value` 是字典,还会额外发出 `date_changed` 兼容性信号。
|
||||||
* `pause_game() -> void`: **通过 `set_system_status_value("game_pause", true)` 修改状态,将 `"system_status"` 中的 `game_pause` 设置为 `true`。**
|
* `pause_game() -> void`: **通过 `set_system_status_value("game_pause", true)` 修改状态,将 `"system_status"` 中的 `game_pause` 设置为 `true`。**
|
||||||
* `resume_game() -> void`: **通过 `set_system_status_value("game_pause", false)` 修改状态,将 `"system_status"` 中的 `game_pause` 设置为 `false`。**
|
* `resume_game() -> void`: **通过 `set_system_status_value("game_pause", false)` 修改状态,将 `"system_status"` 中的 `game_pause` 设置为 `false`。**
|
||||||
* `set_system_status_value(key: String, value: bool) -> void`: 设置 `"system_status"` 字典中指定 `key` (`"game_pause"` 或 `"is_on_task"`) 的布尔值。会触发 `state_value_changed` 信号(针对 `"system_status"` 键,传递更新后的整个 `"system_status"` 字典)。
|
* `set_system_status_value(key: String, value: bool) -> void`: 设置 `"system_status"` 字典中指定 `key` (`"game_pause"` 或 `"is_on_task"`) 的布尔值。会触发 `state_value_changed` 信号(针对 `"system_status"` 键,传递更新后的整个 `"system_status"` 字典的副本)。
|
||||||
* `is_game_paused() -> bool`: 返回游戏是否暂停 (从 `"system_status"` 读取 `game_pause`,若 `"system_status"` 或键不存在则返回 `false`)。
|
* `is_game_paused() -> bool`: 返回游戏是否暂停 (从 `"system_status"` 读取 `game_pause`,若 `"system_status"` 或键不存在则返回 `false`)。
|
||||||
* `is_on_task_status() -> bool`: 返回是否处于任务中状态 (从 `"system_status"` 读取 `is_on_task`,若 `"system_status"` 或键不存在则返回 `false`)。
|
* `is_on_task_status() -> bool`: 返回是否处于任务中状态 (从 `"system_status"` 读取 `is_on_task`,若 `"system_status"` 或键不存在则返回 `false`)。
|
||||||
|
|
||||||
@ -135,10 +135,10 @@
|
|||||||
* `state_initialized(initial_state: Dictionary)`: 在 `initialize_for_new_game` 方法成功执行,内部数据被初始化后发出。传递初始化后的状态字典的副本。
|
* `state_initialized(initial_state: Dictionary)`: 在 `initialize_for_new_game` 方法成功执行,内部数据被初始化后发出。传递初始化后的状态字典的副本。
|
||||||
* `state_restored(restored_state: Dictionary)`: 在 `restore_state` 方法成功执行,内部数据被完全替换后发出。**所有需要状态的功能模块都应监听此信号**,以触发它们的初始化/状态恢复逻辑。传递恢复后的状态字典的副本。
|
* `state_restored(restored_state: Dictionary)`: 在 `restore_state` 方法成功执行,内部数据被完全替换后发出。**所有需要状态的功能模块都应监听此信号**,以触发它们的初始化/状态恢复逻辑。传递恢复后的状态字典的副本。
|
||||||
* `state_value_changed(key: String, new_value: Variant)`: 在 `set_value` 被调用且值发生改变时发出。可用于需要对特定状态变化做出实时反应的模块。
|
* `state_value_changed(key: String, new_value: Variant)`: 在 `set_value` 被调用且值发生改变时发出。可用于需要对特定状态变化做出实时反应的模块。
|
||||||
* `date_changed(new_date: Dictionary)`: **[兼容性信号]** 当 `set_value` 更新了键为 `"time"` 的状态,并且其新值为字典类型时发出。主要用于保持与旧代码或特定UI(如日期显示)的兼容性。传递新日期字典的副本。
|
* `date_changed(new_date: Dictionary)`: **[兼容性信号]** 当 `set_value` 更新了键为 `"time"` 的状态,并且其新值为字典类型时发出,或者在 `initialize_for_new_game` / `restore_state` 后如果存在 `"time"` 键时发出。主要用于保持与旧代码或特定UI(如日期显示)的兼容性。传递新日期字典的副本。
|
||||||
|
|
||||||
### 数据处理 (Data Handled)
|
### 数据处理 (Data Handled)
|
||||||
* **核心:** 管理一个包含所有动态游戏状态的 Key-Value 字典 (`_state_data`)。**系统级状态如暂停 (`game_pause`) 和是否在任务中 (`is_on_task`) 被存储在 `_state_data` 下的 `"system_status"` 子字典中。**
|
* **核心:** 管理一个包含所有动态游戏状态的 Key-Value 字典 (`_state_data`)。**系统级状态如暂停 (`game_pause`) 和是否在任务中 (`is_on_task`) 被存储在 `_state_data` 下的 `"system_status"` 子字典中 (如果该子字典不存在,访问时会提供默认值)。** `_state_data` 中的 `"task_development_info"` 键则存储了当前选定的开发相关初始信息,由 `add_init_data` 方法在初始化时基于 `_state_data["task_development"]` 构建。
|
||||||
* **数据规范:** 不强制规定具体 Key 或 Value 的结构,由各个功能模块自行定义和管理。仅要求 Value 是可序列化的 `Variant`。
|
* **数据规范:** 不强制规定具体 Key 或 Value 的结构,由各个功能模块自行定义和管理。仅要求 Value 是可序列化的 `Variant`。
|
||||||
|
|
||||||
### 配置 (Configuration)
|
### 配置 (Configuration)
|
||||||
@ -153,14 +153,14 @@
|
|||||||
* 封装文件操作和 JSON 序列化/反序列化。
|
* 封装文件操作和 JSON 序列化/反序列化。
|
||||||
|
|
||||||
### 核心职责 (Responsibilities)
|
### 核心职责 (Responsibilities)
|
||||||
* **存档 (Save):** 调用 `GameState.get_savable_state()` 获取状态字典 -> 添加元数据 (存档时间, 游戏版本) -> 序列化为 JSON -> 写入 `user://` 目录下的存档文件。
|
* **存档 (Save):** 调用 `GameState.get_savable_state()` 获取状态字典 -> 添加元数据 (存档时间 ISO 8601 格式, 项目版本号) -> 序列化为 JSON (使用制表符缩进以提高可读性) -> 写入 `user://` 目录下的存档文件 (文件名如 `save_1.json`)。
|
||||||
* **读档 (Load):** 从 `user://` 目录读取存档文件 -> 解析 JSON 为字典 -> 验证基本结构 -> **返回**提取出的 `game_state` 部分字典给调用者 (例如 `InitializationManager` 或调用它的 UI)。
|
* **读档 (Load):** 从 `user://` 目录读取存档文件 -> 解析 JSON 为字典 -> 验证基本结构 (如存在 `game_state` 键且其值为字典) -> **返回**提取出的 `game_state` 部分字典给调用者 (例如主菜单UI,它随后会将此数据通过 `LoadingContext` 传递给加载流程)。如果失败(文件不存在、无法解析、格式错误等),则返回 `null`。
|
||||||
* **文件管理:** 管理 `user://` 目录下的存档文件命名和存在性检查。
|
* **文件管理:** 管理 `user://` 目录下的存档文件命名 (基于槽位 ID,如 `save_1.json`) 和存在性检查。
|
||||||
* **错误处理:** 处理文件读写和 JSON 解析过程中的错误。
|
* **错误处理:** 处理文件读写和 JSON 解析过程中的错误,并通过返回值或打印错误信息 (`printerr`) 进行反馈。
|
||||||
|
|
||||||
### **对外接口 (Public API)**
|
### **对外接口 (Public API)**
|
||||||
* `save_game(slot_id: int) -> bool`: 执行存档操作。调用 `GameState.get_savable_state()` 获取数据,然后写入到指定槽位的文件。返回是否成功。 (通常由存档 UI 调用)
|
* `save_game(slot_id: int) -> bool`: 执行存档操作。调用 `GameState.get_savable_state()` 获取数据,然后写入到指定槽位的文件。返回是否成功。 (通常由存档 UI 调用)
|
||||||
* `load_game(slot_id: int) -> Variant`: 执行读档操作。读取指定槽位的文件,解析 JSON。**成功时返回包含 `game_state` 数据的字典 (Dictionary),失败时返回 `null`。** (通常由需要加载存档的 UI 或流程控制器调用,其结果再传递给 `InitializationManager.load_game_process`)
|
* `load_game(slot_id: int) -> Variant`: 执行读档操作。读取指定槽位的文件,解析 JSON。**成功时返回包含 `game_state` 数据的字典 (Dictionary),失败时返回 `null`。** (通常由需要加载存档的 UI 或流程控制器调用,其结果随后通过 `LoadingContext` 传递给 `InitializationManager.load_game_process`)
|
||||||
* `does_save_exist(slot_id: int) -> bool`: 检查指定槽位是否存在存档文件。
|
* `does_save_exist(slot_id: int) -> bool`: 检查指定槽位是否存在存档文件。
|
||||||
|
|
||||||
### **对外信号 (Public Signals)**
|
### **对外信号 (Public Signals)**
|
||||||
@ -168,13 +168,51 @@
|
|||||||
|
|
||||||
### 交互关键点 (Key Interactions)
|
### 交互关键点 (Key Interactions)
|
||||||
* **被调用:** UI (存档菜单调用 `save_game`, `does_save_exist`; 读档菜单调用 `load_game`)。
|
* **被调用:** UI (存档菜单调用 `save_game`, `does_save_exist`; 读档菜单调用 `load_game`)。
|
||||||
* **调用:** `GameState` (仅在 `save_game` 时调用 `get_savable_state()`), `FileAccess` API, `JSON` API, `Time` API, `ProjectSettings` API, `OS` API。
|
* **调用:** `GameState` (仅在 `save_game` 时调用 `get_savable_state()`), `FileAccess` API, `JSON` API, `Time` API, `ProjectSettings` API, `OS` API (用于 `is_debug_build` 检查)。
|
||||||
* **重要:** 开发者在编写其他模块时,**无需直接与 `SaveLoadManager` 交互**。模块的状态通过 `GameState` 间接被保存和加载。
|
* **重要:** 开发者在编写其他模块时,**无需直接与 `SaveLoadManager` 交互**。模块的状态通过 `GameState` 间接被保存和加载。
|
||||||
|
|
||||||
### 数据处理 (Data Handled)
|
### 数据处理 (Data Handled)
|
||||||
* **输入 (Save):** 从 `GameState` 获取的状态字典。
|
* **输入 (Save):** 从 `GameState` 获取的状态字典。
|
||||||
* **输出 (Save):** `user://` 目录下的 JSON 文件 (包含 metadata 和 game_state)。
|
* **输出 (Save):** `user://` 目录下的 JSON 文件 (包含 `metadata` 和 `game_state`)。
|
||||||
* **输入 (Load):** `user://` 目录下的 JSON 文件。
|
* **输入 (Load):** `user://` 目录下的 JSON 文件。
|
||||||
* **输出 (Load):** 解析后的 `game_state` 字典 (返回给调用者) 或 `null`。
|
* **输出 (Load):** 解析后的 `game_state` 字典 (返回给调用者) 或 `null`。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 5. 加载上下文管理器 (LoadingContext)
|
||||||
|
|
||||||
|
### 目标 (Purpose/Goal)
|
||||||
|
* 作为在不同场景之间(尤其是从启动界面/主菜单到加载场景)传递加载指令和必要数据的临时容器。
|
||||||
|
* 确保加载场景能够获取执行新游戏或加载存档所需的信息。
|
||||||
|
|
||||||
|
### 核心职责 (Responsibilities)
|
||||||
|
* **数据传递:** 临时存储加载操作的类型 (`"new_game"` 或 `"load_game"`)。
|
||||||
|
* **存档数据暂存:** 当操作类型为 `"load_game"` 时,暂存从 `SaveLoadManager` 加载到的存档数据字典。
|
||||||
|
* **上下文清理:** 提供方法以在数据使用完毕后(通常在加载场景完成其任务后)清除上下文,避免旧数据影响后续操作。
|
||||||
|
|
||||||
|
### **对外属性 (Public Properties)**
|
||||||
|
* `action_to_perform: String`: 存储当前的加载操作指令。
|
||||||
|
* 可能的值: `"new_game"`, `"load_game"`, 或空字符串 (表示无操作或已处理)。
|
||||||
|
* `save_data_for_loading: Dictionary`: 当 `action_to_perform` 为 `"load_game"` 时,这里存储从 `SaveLoadManager.load_game()` 获取到的存档数据字典。其他情况下为空字典。
|
||||||
|
|
||||||
|
### **对外接口 (Public API)**
|
||||||
|
* `clear_context() -> void`: 清理 `action_to_perform` 和 `save_data_for_loading`,将它们重置为空字符串和空字典。通常在加载场景使用完上下文信息后调用。
|
||||||
|
* `set_context(action: String, data: Dictionary = {}) -> void`: 设置加载操作类型和可选的存档数据。传入的 `data` 会被深拷贝 (`duplicate(true)`) 以防止外部修改影响存储的上下文。
|
||||||
|
|
||||||
|
### **对外信号 (Public Signals)**
|
||||||
|
* *此管理器不发出信号。*
|
||||||
|
|
||||||
|
### 交互关键点 (Key Interactions)
|
||||||
|
* **被设置:** 通常由主菜单或启动场景中的 UI 逻辑设置。
|
||||||
|
* 例如,点击“新游戏”按钮时,调用 `set_context("new_game")`。
|
||||||
|
* 例如,选择存档并成功调用 `SaveLoadManager.load_game(slot_id)` 后,调用 `set_context("load_game", loaded_save_data)`。
|
||||||
|
* **被读取:** 主要由加载场景 (Loading Scene) 读取。加载场景根据 `action_to_perform` 的值来决定是调用 `InitializationManager.start_new_game_process()` 还是 `InitializationManager.load_game_process(save_data_for_loading)`。
|
||||||
|
* **调用:** 无直接调用其他核心管理器,它是一个被动的数据容器。
|
||||||
|
* **清理:** 加载场景在完成对 `InitializationManager` 的调用并准备切换到主游戏场景之前,应调用 `clear_context()`。
|
||||||
|
|
||||||
|
### 数据处理 (Data Handled)
|
||||||
|
* **输入:** 加载操作类型 (字符串) 和可选的存档数据 (字典)。
|
||||||
|
* **存储:** 内部临时存储这些输入。
|
||||||
|
* **输出:** 加载场景通过直接访问其公共属性来读取这些数据。
|
||||||
|
|
||||||
|
---
|
||||||
|
|||||||
189
Entity/Level/LoadingScene.gd
Normal file
189
Entity/Level/LoadingScene.gd
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
# LoadingScene.gd
|
||||||
|
# 负责驱动加载流程,更新UI,并在完成后切换到游戏主场景。
|
||||||
|
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
# --- 节点引用 ---
|
||||||
|
@onready var progress_bar: ProgressBar = $MainContainer/LoadingProgressBar
|
||||||
|
@onready var loading_label: Label = $MainContainer/LoadingLabel
|
||||||
|
|
||||||
|
# --- 常量 ---
|
||||||
|
const GAME_SCENE_PATH = "res://Entity/Level/GameScene.tscn" # 请确保这个路径是正确的!
|
||||||
|
|
||||||
|
# --- 内部状态变量 ---
|
||||||
|
var _current_action: String = ""
|
||||||
|
var _save_data_to_process: Dictionary = {}
|
||||||
|
|
||||||
|
var _target_animation_progress: float = 0.0 # 进度条动画的目标值 (用于20%-80%的平滑过渡)
|
||||||
|
var _current_animation_progress: float = 0.0 # 进度条动画的当前值
|
||||||
|
var _animation_speed: float = 30.0 # 进度条动画速度 (百分比/秒),可以根据需要调整
|
||||||
|
|
||||||
|
var _initialization_started: bool = false # 标记核心初始化流程是否已开始
|
||||||
|
var _initialization_complete: bool = false # 标记核心初始化流程是否已完成
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
print("LoadingScene: Scene Ready.")
|
||||||
|
# 1. 初始化UI
|
||||||
|
_update_progress(0.0, "准备加载...")
|
||||||
|
|
||||||
|
# 2. 从 LoadingContext 获取参数
|
||||||
|
if not ProjectSettings.has_setting("autoload/LoadingContext"):
|
||||||
|
_handle_critical_error("LoadingContext Autoload 未配置!")
|
||||||
|
return
|
||||||
|
|
||||||
|
_current_action = LoadingContext.action_to_perform
|
||||||
|
# 对存档数据进行深拷贝,以防万一LoadingContext中的原始数据被意外修改
|
||||||
|
_save_data_to_process = LoadingContext.save_data_for_loading.duplicate(true)
|
||||||
|
|
||||||
|
# 3. 清空 LoadingContext (这是一个好习惯)
|
||||||
|
LoadingContext.clear_context()
|
||||||
|
|
||||||
|
# 验证获取到的action是否有效
|
||||||
|
if _current_action != "new_game" and _current_action != "load_game":
|
||||||
|
_handle_critical_error("无效的加载指令: " + _current_action)
|
||||||
|
return
|
||||||
|
|
||||||
|
print("LoadingScene: Action to perform - ", _current_action)
|
||||||
|
if _current_action == "load_game":
|
||||||
|
print("LoadingScene: Save data keys to process - ", _save_data_to_process.keys())
|
||||||
|
|
||||||
|
# 4. 更新进度到阶段1 (10%)
|
||||||
|
_update_progress(10.0, "加载参数读取完毕...")
|
||||||
|
|
||||||
|
# 5. 连接 InitializationManager 的信号
|
||||||
|
# 使用 CONNECT_ONE_SHOT 确保信号只触发一次,处理后自动断开,避免重复处理或内存泄漏
|
||||||
|
if not ProjectSettings.has_setting("autoload/InitializationManager"):
|
||||||
|
_handle_critical_error("InitializationManager Autoload 未配置!")
|
||||||
|
return
|
||||||
|
|
||||||
|
if _current_action == "new_game":
|
||||||
|
if InitializationManager.is_connected("new_game_initialized", Callable(self, "_on_initialization_manager_finished")):
|
||||||
|
printerr("LoadingScene: Warning - new_game_initialized signal already connected by this instance. This might indicate a logic error if _ready is called multiple times unexpectedly.")
|
||||||
|
else:
|
||||||
|
InitializationManager.new_game_initialized.connect(self._on_initialization_manager_finished, CONNECT_ONE_SHOT)
|
||||||
|
print("LoadingScene: Connected to InitializationManager.new_game_initialized.")
|
||||||
|
elif _current_action == "load_game":
|
||||||
|
if InitializationManager.is_connected("game_loaded", Callable(self, "_on_initialization_manager_finished")):
|
||||||
|
printerr("LoadingScene: Warning - game_loaded signal already connected by this instance.")
|
||||||
|
else:
|
||||||
|
InitializationManager.game_loaded.connect(self._on_initialization_manager_finished, CONNECT_ONE_SHOT)
|
||||||
|
print("LoadingScene: Connected to InitializationManager.game_loaded.")
|
||||||
|
|
||||||
|
# 6. 使用 call_deferred 延迟调用实际的初始化启动函数
|
||||||
|
# 这可以确保当前 _ready() 函数中的UI更新等操作完成后再开始耗时操作。
|
||||||
|
call_deferred("_start_actual_initialization")
|
||||||
|
|
||||||
|
|
||||||
|
func _start_actual_initialization() -> void:
|
||||||
|
print("LoadingScene: Starting actual initialization...")
|
||||||
|
# 更新进度到阶段2 (20%)
|
||||||
|
_update_progress(20.0, "开始初始化核心数据...")
|
||||||
|
|
||||||
|
_initialization_started = true
|
||||||
|
_current_animation_progress = 20.0 # 动画从20%开始
|
||||||
|
_target_animation_progress = 80.0 # 动画目标到80%
|
||||||
|
|
||||||
|
var success: bool = false
|
||||||
|
if _current_action == "new_game":
|
||||||
|
success = InitializationManager.start_new_game_process()
|
||||||
|
if not success:
|
||||||
|
_handle_initialization_failure("新游戏流程启动失败 (InitializationManager.start_new_game_process 返回 false)。")
|
||||||
|
elif _current_action == "load_game":
|
||||||
|
if _save_data_to_process.is_empty() and _current_action == "load_game":
|
||||||
|
# 这是一个潜在问题,如果我们要加载游戏,但没有存档数据
|
||||||
|
_handle_initialization_failure("加载游戏失败:没有提供有效的存档数据。")
|
||||||
|
return
|
||||||
|
success = InitializationManager.load_game_process(_save_data_to_process)
|
||||||
|
if not success:
|
||||||
|
_handle_initialization_failure("加载游戏流程启动失败 (InitializationManager.load_game_process 返回 false)。")
|
||||||
|
|
||||||
|
if success:
|
||||||
|
print("LoadingScene: Initialization process started via InitializationManager.")
|
||||||
|
# 如果 success 为 false,_handle_initialization_failure 已经被调用
|
||||||
|
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
# 如果核心初始化已开始且未完成,则驱动进度条动画
|
||||||
|
if _initialization_started and not _initialization_complete:
|
||||||
|
if _current_animation_progress < _target_animation_progress:
|
||||||
|
_current_animation_progress = move_toward(_current_animation_progress, _target_animation_progress, _animation_speed * delta)
|
||||||
|
# 只更新进度条的值,不频繁更新文本,避免性能开销和视觉跳动
|
||||||
|
progress_bar.value = _current_animation_progress
|
||||||
|
# (可选) 如果动画已达到80%但仍在等待信号,可以添加一个小的等待动画或文本提示
|
||||||
|
# else:
|
||||||
|
# loading_label.text = "正在等待核心数据处理完成..." (确保只设置一次)
|
||||||
|
|
||||||
|
|
||||||
|
# 当 InitializationManager 完成新游戏或加载游戏流程后,此函数被调用
|
||||||
|
func _on_initialization_manager_finished() -> void: # success 参数已移除,因为信号发出即代表成功
|
||||||
|
print("LoadingScene: Received signal from InitializationManager (initialization finished).")
|
||||||
|
_initialization_complete = true
|
||||||
|
|
||||||
|
# 确保动画进度至少达到目标,或者直接跳到90%
|
||||||
|
_current_animation_progress = max(_current_animation_progress, _target_animation_progress)
|
||||||
|
|
||||||
|
# 更新进度到阶段3 (90%)
|
||||||
|
_update_progress(90.0, "核心数据准备完毕!")
|
||||||
|
|
||||||
|
# 【增加延时】在切换到游戏场景之前
|
||||||
|
#print("LoadingScene: Adding a DEBUG delay before transitioning to GameScene...")
|
||||||
|
#await get_tree().create_timer(3.0).timeout # <--- 增加3秒延时 (用于调试)
|
||||||
|
#print("LoadingScene: DEBUG delay finished.")
|
||||||
|
|
||||||
|
# 延迟切换到游戏场景
|
||||||
|
call_deferred("_transition_to_game_scene")
|
||||||
|
|
||||||
|
|
||||||
|
func _transition_to_game_scene() -> void:
|
||||||
|
print("LoadingScene: Preparing to transition to GameScene...")
|
||||||
|
# 更新进度到阶段4 (100%)
|
||||||
|
_update_progress(100.0, "正在进入游戏...")
|
||||||
|
|
||||||
|
# (可选) 给用户一个非常短暂的时间看到100%
|
||||||
|
# await get_tree().create_timer(0.1).timeout
|
||||||
|
# 注意: 上面的 await 会使函数变成异步,如果后续有更多同步代码,需要注意。
|
||||||
|
# 对于简单的场景切换,直接调用通常没问题。
|
||||||
|
|
||||||
|
var err = get_tree().change_scene_to_file(GAME_SCENE_PATH)
|
||||||
|
if err != OK:
|
||||||
|
_handle_critical_error("切换到 GameScene 失败! 错误码: " + str(err) + "路径: " + GAME_SCENE_PATH)
|
||||||
|
# 此时游戏可能处于一个无法恢复的状态,可以考虑显示一个永久的错误信息
|
||||||
|
|
||||||
|
|
||||||
|
# --- 辅助函数 ---
|
||||||
|
|
||||||
|
func _update_progress(value: float, message: String = "") -> void:
|
||||||
|
progress_bar.value = value
|
||||||
|
if not message.is_empty():
|
||||||
|
# 为了避免过于频繁地更新Label内容导致潜在的性能问题或闪烁,
|
||||||
|
# 我们可以只在关键阶段更新文本,或者确保文本内容确实改变了再更新。
|
||||||
|
# 这里我们假设在关键阶段更新文本是可以接受的。
|
||||||
|
loading_label.text = message # +" " + str(int(value)) + "%"
|
||||||
|
# ProgressBar的show_percentage=true会自动显示百分比
|
||||||
|
print("LoadingScene: Progress updated - ", int(value), "% - ", message)
|
||||||
|
|
||||||
|
|
||||||
|
func _handle_initialization_failure(error_message: String) -> void:
|
||||||
|
printerr("LoadingScene: Initialization Failed - ", error_message)
|
||||||
|
_initialization_started = false # 停止任何进行中的动画逻辑
|
||||||
|
_initialization_complete = true # 标记流程结束(虽然是失败的结束)
|
||||||
|
|
||||||
|
# 更新UI以反映错误状态
|
||||||
|
progress_bar.value = progress_bar.min_value # 或者一个特定的错误值/样式
|
||||||
|
# 可以考虑给ProgressBar添加一个自定义主题,当发生错误时改变其颜色
|
||||||
|
# progress_bar.add_theme_stylebox_override("fill", preload("res://error_progress_bar_fill_style.tres"))
|
||||||
|
loading_label.text = "错误: " + error_message + "\n请尝试返回主菜单或重启游戏。"
|
||||||
|
# 在这里,可以考虑启用一个“返回主菜单”的按钮,或者其他用户可进行的操作。
|
||||||
|
# 例如: get_node("Path/To/RetryButton").disabled = false
|
||||||
|
|
||||||
|
|
||||||
|
func _handle_critical_error(error_message: String) -> void:
|
||||||
|
printerr("LoadingScene: CRITICAL ERROR - ", error_message)
|
||||||
|
_initialization_started = false
|
||||||
|
_initialization_complete = true # 阻止进一步操作
|
||||||
|
if progress_bar: progress_bar.value = 0
|
||||||
|
if loading_label: loading_label.text = "严重错误: " + error_message + "\n游戏可能无法继续。"
|
||||||
|
# 对于严重错误,可能除了显示信息外做不了太多
|
||||||
|
# 可以禁用所有交互,或者尝试安全退出游戏
|
||||||
|
# get_tree().quit() # 如果错误非常严重
|
||||||
1
Entity/Level/LoadingScene.gd.uid
Normal file
1
Entity/Level/LoadingScene.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://dlvo4fwjsy7r5
|
||||||
47
Entity/Level/LoadingScene.tscn
Normal file
47
Entity/Level/LoadingScene.tscn
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://4wbnffj2cbmc"]
|
||||||
|
|
||||||
|
[ext_resource type="FontFile" uid="uid://egugs822n8gr" path="res://UI/font/AlimamaFangYuanTiVF-Thin.ttf" id="1_7week"]
|
||||||
|
[ext_resource type="Script" uid="uid://dlvo4fwjsy7r5" path="res://Entity/Level/LoadingScene.gd" id="1_sd15f"]
|
||||||
|
|
||||||
|
[node name="LoadingScene" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_sd15f")
|
||||||
|
|
||||||
|
[node name="BackgroundColor" type="ColorRect" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
color = Color(0, 0, 0, 1)
|
||||||
|
|
||||||
|
[node name="MainContainer" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 8
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = -150.0
|
||||||
|
offset_top = -23.5
|
||||||
|
offset_right = 150.0
|
||||||
|
offset_bottom = 23.5
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="LoadingLabel" type="Label" parent="MainContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
theme_override_fonts/font = ExtResource("1_7week")
|
||||||
|
text = "加载中..."
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="LoadingProgressBar" type="ProgressBar" parent="MainContainer"]
|
||||||
|
custom_minimum_size = Vector2(300, 0)
|
||||||
|
layout_mode = 2
|
||||||
@ -3,13 +3,13 @@
|
|||||||
extends Node2D
|
extends Node2D
|
||||||
|
|
||||||
# --- 节点引用 ---
|
# --- 节点引用 ---
|
||||||
# !! 重要:请根据你的实际场景结构调整以下节点路径 !!
|
@onready var new_game_button: Button = $UI/Select_List/New
|
||||||
@onready var new_game_button = $UI/Select_List/New
|
@onready var load_game_button: Button = $UI/Select_List/Load
|
||||||
@onready var load_game_button = $UI/Select_List/Load
|
|
||||||
# @onready var error_message_label = $UI/ErrorMessageLabel # 如果有错误提示标签
|
# @onready var error_message_label = $UI/ErrorMessageLabel # 如果有错误提示标签
|
||||||
|
|
||||||
# --- 场景路径 ---
|
# --- 场景路径 ---
|
||||||
var GameScene_path = "res://Entity/Level/GameScene.tscn"
|
# const GameScene_path = "res://Entity/Level/GameScene.tscn" # 不再由此脚本直接切换
|
||||||
|
const LOADING_SCENE_PATH = "res://Entity/Level/LoadingScene.tscn" # <--- 新增:LoadingScene的路径,请确保正确!
|
||||||
|
|
||||||
# --- Godot 生命周期方法 ---
|
# --- Godot 生命周期方法 ---
|
||||||
|
|
||||||
@ -17,13 +17,15 @@ func _ready():
|
|||||||
print("Start Scene: Initializing...")
|
print("Start Scene: Initializing...")
|
||||||
# --- 连接 UI 信号 ---
|
# --- 连接 UI 信号 ---
|
||||||
if new_game_button:
|
if new_game_button:
|
||||||
new_game_button.pressed.connect(_on_new_game_pressed)
|
if not new_game_button.is_connected("pressed", Callable(self, "_on_new_game_pressed")):
|
||||||
|
new_game_button.pressed.connect(self._on_new_game_pressed)
|
||||||
print("Start Scene: Connected 'pressed' signal for New Game button.")
|
print("Start Scene: Connected 'pressed' signal for New Game button.")
|
||||||
else:
|
else:
|
||||||
printerr("Start Scene Error: New Game button node not found at path specified in @onready var.")
|
printerr("Start Scene Error: New Game button node not found at path specified in @onready var.")
|
||||||
|
|
||||||
if load_game_button:
|
if load_game_button:
|
||||||
load_game_button.pressed.connect(_on_load_game_pressed)
|
if not load_game_button.is_connected("pressed", Callable(self, "_on_load_game_pressed")):
|
||||||
|
load_game_button.pressed.connect(self._on_load_game_pressed)
|
||||||
print("Start Scene: Connected 'pressed' signal for Load Game button.")
|
print("Start Scene: Connected 'pressed' signal for Load Game button.")
|
||||||
# 示例:根据存档是否存在禁用加载按钮 (需要 SaveLoadManager Autoload)
|
# 示例:根据存档是否存在禁用加载按钮 (需要 SaveLoadManager Autoload)
|
||||||
# if ProjectSettings.has_setting("autoload/SaveLoadManager"):
|
# if ProjectSettings.has_setting("autoload/SaveLoadManager"):
|
||||||
@ -33,146 +35,124 @@ func _ready():
|
|||||||
else:
|
else:
|
||||||
printerr("Start Scene Error: Load Game button node not found at path specified in @onready var.")
|
printerr("Start Scene Error: Load Game button node not found at path specified in @onready var.")
|
||||||
|
|
||||||
# --- 连接 InitializationManager 信号 ---
|
# --- 移除 InitializationManager 信号连接 ---
|
||||||
# 确保 InitializationManager 是 Autoload 并且已经注册
|
# 不再需要在此处连接 InitializationManager 的信号,这些将由 LoadingScene 处理。
|
||||||
if ProjectSettings.has_setting("autoload/InitializationManager"):
|
# 例如,以下代码需要被移除或注释掉:
|
||||||
# 连接新游戏初始化完成信号
|
# if ProjectSettings.has_setting("autoload/InitializationManager"):
|
||||||
if not InitializationManager.is_connected("new_game_initialized", Callable(self, "_on_initialization_complete")):
|
# if not InitializationManager.is_connected("new_game_initialized", Callable(self, "_on_initialization_complete")):
|
||||||
InitializationManager.new_game_initialized.connect(_on_initialization_complete)
|
# InitializationManager.new_game_initialized.connect(self._on_initialization_complete)
|
||||||
print("Start Scene: Connected to InitializationManager.new_game_initialized signal.")
|
# if not InitializationManager.is_connected("game_loaded", Callable(self, "_on_initialization_complete")):
|
||||||
|
# InitializationManager.game_loaded.connect(self._on_initialization_complete)
|
||||||
|
# else:
|
||||||
|
# printerr("Start Scene Error: InitializationManager Autoload is not configured...")
|
||||||
|
|
||||||
# 连接加载游戏完成信号
|
|
||||||
if not InitializationManager.is_connected("game_loaded", Callable(self, "_on_initialization_complete")):
|
|
||||||
InitializationManager.game_loaded.connect(_on_initialization_complete)
|
|
||||||
print("Start Scene: Connected to InitializationManager.game_loaded signal.")
|
|
||||||
else:
|
|
||||||
# 如果没有配置 Autoload,这是一个严重错误
|
|
||||||
printerr("Start Scene Error: InitializationManager Autoload is not configured in Project Settings!")
|
|
||||||
# 在这种情况下,游戏可能无法正常启动新游戏或加载
|
|
||||||
if new_game_button: new_game_button.disabled = true
|
|
||||||
if load_game_button: load_game_button.disabled = true
|
|
||||||
|
|
||||||
# 当此节点从场景树中移除时调用
|
# 当此节点从场景树中移除时调用
|
||||||
func _exit_tree():
|
func _exit_tree():
|
||||||
# 断开与 Autoload 信号的连接,这是一个良好的实践
|
# --- 移除 InitializationManager 信号断开 ---
|
||||||
if ProjectSettings.has_setting("autoload/InitializationManager"):
|
# 同样,不再需要在此处断开 InitializationManager 的信号。
|
||||||
# 断开新游戏信号
|
# if ProjectSettings.has_setting("autoload/InitializationManager"):
|
||||||
if InitializationManager.is_connected("new_game_initialized", Callable(self, "_on_initialization_complete")):
|
# if InitializationManager.is_connected("new_game_initialized", Callable(self, "_on_initialization_complete")):
|
||||||
InitializationManager.new_game_initialized.disconnect(Callable(self, "_on_initialization_complete"))
|
# InitializationManager.new_game_initialized.disconnect(Callable(self, "_on_initialization_complete"))
|
||||||
print("Start Scene: Disconnected from InitializationManager.new_game_initialized signal.")
|
# if InitializationManager.is_connected("game_loaded", Callable(self, "_on_initialization_complete")):
|
||||||
# 断开加载游戏信号
|
# InitializationManager.game_loaded.disconnect(Callable(self, "_on_initialization_complete"))
|
||||||
if InitializationManager.is_connected("game_loaded", Callable(self, "_on_initialization_complete")):
|
pass # 如果没有其他需要在退出时清理的,可以留空或移除此函数
|
||||||
InitializationManager.game_loaded.disconnect(Callable(self, "_on_initialization_complete"))
|
|
||||||
print("Start Scene: Disconnected from InitializationManager.game_loaded signal.")
|
|
||||||
|
|
||||||
# --- UI 信号回调函数 ---
|
# --- UI 信号回调函数 ---
|
||||||
|
|
||||||
# 当“新游戏”按钮被按下时调用
|
# 当“新游戏”按钮被按下时调用
|
||||||
func _on_new_game_pressed():
|
func _on_new_game_pressed():
|
||||||
print("Start Scene: 'New Game' button pressed. Requesting new game initialization...")
|
print("Start Scene: 'New Game' button pressed. Transitioning to Loading Scene...")
|
||||||
if new_game_button: new_game_button.disabled = true
|
if new_game_button: new_game_button.disabled = true # 禁用按钮防止重复点击
|
||||||
if load_game_button: load_game_button.disabled = true
|
if load_game_button: load_game_button.disabled = true
|
||||||
|
|
||||||
if ProjectSettings.has_setting("autoload/InitializationManager"):
|
# 检查 LoadingContext Autoload 是否存在
|
||||||
# 调用 InitializationManager 启动流程
|
if not ProjectSettings.has_setting("autoload/LoadingContext"):
|
||||||
# start_new_game_process 返回 true/false 表示调用是否成功启动(例如数据加载失败)
|
printerr("Start Scene CRITICAL Error: LoadingContext Autoload not configured!")
|
||||||
if not InitializationManager.start_new_game_process():
|
# 重新启用按钮,让用户可以重试或意识到问题
|
||||||
# 如果启动流程本身就失败了(例如 InitialDataManager 无法加载数据)
|
|
||||||
printerr("Start Scene: InitializationManager.start_new_game_process() failed immediately.")
|
|
||||||
# 显示错误信息给用户
|
|
||||||
# if error_message_label: error_message_label.text = "无法启动新游戏,请检查配置。"
|
|
||||||
# 重新启用按钮
|
|
||||||
if new_game_button: new_game_button.disabled = false
|
if new_game_button: new_game_button.disabled = false
|
||||||
if load_game_button: load_game_button.disabled = false
|
if load_game_button: load_game_button.disabled = false
|
||||||
# else: # 如果启动成功,则等待 _on_initialization_complete 信号
|
# (可选) 显示错误信息给用户
|
||||||
# print("Start Scene: New game process started, waiting for completion signal...")
|
# if error_message_label: error_message_label.text = "错误:无法准备加载流程!"
|
||||||
else:
|
return
|
||||||
printerr("Start Scene Error: Cannot start new game - InitializationManager Autoload not found!")
|
|
||||||
|
# 设置 LoadingContext
|
||||||
|
LoadingContext.action_to_perform = "new_game"
|
||||||
|
LoadingContext.save_data_for_loading = {} # 确保对于新游戏,存档数据为空
|
||||||
|
|
||||||
|
# 切换到 LoadingScene
|
||||||
|
var err = get_tree().change_scene_to_file(LOADING_SCENE_PATH)
|
||||||
|
if err != OK:
|
||||||
|
printerr("Start Scene CRITICAL ERROR: Failed to switch to Loading Scene! Error code: " + str(err))
|
||||||
if new_game_button: new_game_button.disabled = false
|
if new_game_button: new_game_button.disabled = false
|
||||||
if load_game_button: load_game_button.disabled = false
|
if load_game_button: load_game_button.disabled = false
|
||||||
|
# (可选) 显示错误信息给用户
|
||||||
|
# if error_message_label: error_message_label.text = "错误:无法打开加载界面!"
|
||||||
|
|
||||||
|
|
||||||
# 当“加载游戏”按钮被按下时调用
|
# 当“加载游戏”按钮被按下时调用
|
||||||
func _on_load_game_pressed():
|
func _on_load_game_pressed():
|
||||||
var slot_to_load = 1 # <-- 硬编码加载的存档槽位 ID
|
var slot_to_load = 1 # <-- 您可以根据需要修改或添加选择存档槽的逻辑
|
||||||
print("Start Scene: 'Load Game' button pressed. Requesting load for slot " + str(slot_to_load) + "...")
|
print("Start Scene: 'Load Game' button pressed. Requesting load for slot " + str(slot_to_load) + "...")
|
||||||
|
|
||||||
if new_game_button: new_game_button.disabled = true
|
if new_game_button: new_game_button.disabled = true
|
||||||
if load_game_button: load_game_button.disabled = true
|
if load_game_button: load_game_button.disabled = true
|
||||||
|
|
||||||
# --- 需要 SaveLoadManager 来获取存档数据 ---
|
# 检查必要的 Autoloads
|
||||||
if not ProjectSettings.has_setting("autoload/SaveLoadManager"):
|
if not ProjectSettings.has_setting("autoload/SaveLoadManager"):
|
||||||
printerr("Start Scene Error: Cannot load game - SaveLoadManager Autoload not found!")
|
printerr("Start Scene CRITICAL Error: SaveLoadManager Autoload not configured!")
|
||||||
if new_game_button: new_game_button.disabled = false
|
if new_game_button: new_game_button.disabled = false
|
||||||
if load_game_button: load_game_button.disabled = false
|
if load_game_button: load_game_button.disabled = false
|
||||||
return # 无法继续
|
return
|
||||||
|
if not ProjectSettings.has_setting("autoload/LoadingContext"):
|
||||||
|
printerr("Start Scene CRITICAL Error: LoadingContext Autoload not configured!")
|
||||||
|
if new_game_button: new_game_button.disabled = false
|
||||||
|
if load_game_button: load_game_button.disabled = false
|
||||||
|
return
|
||||||
|
|
||||||
# 1. 尝试从 SaveLoadManager 加载数据 (现在期望返回字典或 null)
|
# 1. 尝试从 SaveLoadManager 加载数据
|
||||||
var loaded_data: Variant = SaveLoadManager.load_game(slot_to_load)
|
var loaded_data: Variant = SaveLoadManager.load_game(slot_to_load)
|
||||||
|
|
||||||
# 2. 检查加载是否成功 (返回 null 表示失败)
|
# 2. 检查加载是否成功
|
||||||
if loaded_data == null:
|
if loaded_data == null:
|
||||||
printerr("Start Scene: Failed to load save data from slot " + str(slot_to_load) + " (SaveLoadManager returned null).")
|
printerr("Start Scene: Failed to load save data from slot " + str(slot_to_load) + " (SaveLoadManager returned null).")
|
||||||
# 显示错误信息给用户
|
|
||||||
# if error_message_label: error_message_label.text = "加载存档失败!"
|
|
||||||
# 重新启用按钮
|
|
||||||
if new_game_button: new_game_button.disabled = false
|
if new_game_button: new_game_button.disabled = false
|
||||||
if load_game_button: load_game_button.disabled = false
|
if load_game_button: load_game_button.disabled = false
|
||||||
return # 加载失败,中止
|
# (可选) 显示错误信息给用户
|
||||||
|
# if error_message_label: error_message_label.text = "加载存档失败!"
|
||||||
|
return
|
||||||
|
|
||||||
# 2.1 (可选但推荐) 再次确认加载的数据是字典类型
|
|
||||||
if not loaded_data is Dictionary:
|
if not loaded_data is Dictionary:
|
||||||
printerr("Start Scene Error: Loaded data from SaveLoadManager is not a Dictionary. Type:", typeof(loaded_data))
|
printerr("Start Scene Error: Loaded data from SaveLoadManager is not a Dictionary. Type:", typeof(loaded_data))
|
||||||
if new_game_button: new_game_button.disabled = false
|
if new_game_button: new_game_button.disabled = false
|
||||||
if load_game_button: load_game_button.disabled = false
|
if load_game_button: load_game_button.disabled = false
|
||||||
return # 数据类型错误,中止
|
return
|
||||||
|
|
||||||
# 3. 如果存档数据加载成功 (是字典),再调用 InitializationManager 处理
|
# 3. 设置 LoadingContext
|
||||||
if ProjectSettings.has_setting("autoload/InitializationManager"):
|
LoadingContext.action_to_perform = "load_game"
|
||||||
# 将加载到的字典传递给 load_game_process
|
LoadingContext.save_data_for_loading = loaded_data # 将加载到的字典传递过去
|
||||||
if not InitializationManager.load_game_process(loaded_data): # <--- 传递字典
|
|
||||||
printerr("Start Scene: InitializationManager.load_game_process() failed.")
|
# 4. 切换到 LoadingScene
|
||||||
# 显示错误信息给用户
|
var err = get_tree().change_scene_to_file(LOADING_SCENE_PATH)
|
||||||
# if error_message_label: error_message_label.text = "应用存档状态时出错。"
|
if err != OK:
|
||||||
# 重新启用按钮
|
printerr("Start Scene CRITICAL ERROR: Failed to switch to Loading Scene! Error code: " + str(err))
|
||||||
if new_game_button: new_game_button.disabled = false
|
|
||||||
if load_game_button: load_game_button.disabled = false
|
|
||||||
# else: # 如果启动成功,则等待 _on_initialization_complete 信号
|
|
||||||
# print("Start Scene: Load game process started, waiting for completion signal...")
|
|
||||||
else:
|
|
||||||
printerr("Start Scene Error: Cannot process loaded game - InitializationManager Autoload not found!")
|
|
||||||
if new_game_button: new_game_button.disabled = false
|
if new_game_button: new_game_button.disabled = false
|
||||||
if load_game_button: load_game_button.disabled = false
|
if load_game_button: load_game_button.disabled = false
|
||||||
|
|
||||||
|
|
||||||
# --- InitializationManager 信号回调函数 ---
|
# --- InitializationManager 信号回调函数 ---
|
||||||
|
# func _on_initialization_complete(): # <--- 此方法不再需要,可以安全移除或注释掉
|
||||||
# 当 InitializationManager 完成新游戏或加载游戏流程后,此函数被调用
|
# print("Start Scene: Received initialization complete signal (New Game or Load).")
|
||||||
func _on_initialization_complete(): # 移除了 success 参数
|
# print("--------------------------------------------------")
|
||||||
print("Start Scene: Received initialization complete signal (New Game or Load).")
|
# print("Start Scene: Initialization successful!")
|
||||||
# 既然信号被发出,我们认为初始化流程是成功的
|
# print("--------------------------------------------------")
|
||||||
print("--------------------------------------------------")
|
# Go_To_GameScene()
|
||||||
print("Start Scene: Initialization successful!")
|
|
||||||
print("--------------------------------------------------")
|
|
||||||
|
|
||||||
# 切换到主游戏场景
|
|
||||||
Go_To_GameScene() # 保持不变
|
|
||||||
|
|
||||||
# 注意:这里没有处理初始化失败的情况,因为失败应该在
|
|
||||||
# start_new_game_process 或 load_game_process 返回 false 时,
|
|
||||||
# 或者在 SaveLoadManager.load_game 失败时,在调用处直接处理。
|
|
||||||
# 如果 InitializationManager 内部在发出信号前还可能失败,
|
|
||||||
# 则需要重新考虑信号设计或错误处理流程。
|
|
||||||
|
|
||||||
|
|
||||||
# --- 辅助函数 ---
|
# --- 辅助函数 ---
|
||||||
|
# func Go_To_GameScene(): # <--- 此方法不再需要,因为场景切换由 LoadingScene 处理
|
||||||
# 切换到主游戏场景 (保持不变)
|
# print("Start Scene: Attempting to switch to Game Scene:", GameScene_path)
|
||||||
func Go_To_GameScene():
|
# var err = get_tree().change_scene_to_file(GameScene_path)
|
||||||
print("Start Scene: Attempting to switch to Game Scene:", GameScene_path)
|
# if err != OK:
|
||||||
var err = get_tree().change_scene_to_file(GameScene_path)
|
# printerr("Start Scene CRITICAL ERROR: Failed to switch to main game scene!")
|
||||||
if err != OK:
|
|
||||||
printerr("Start Scene CRITICAL ERROR: Failed to switch to main game scene!")
|
|
||||||
printerr(" Path: " + GameScene_path)
|
|
||||||
printerr(" Error code: " + str(err))
|
|
||||||
# if error_message_label: error_message_label.text = "无法加载主游戏场景!"
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ InitialDataManager="*res://Autoload/InitialDataManager.gd"
|
|||||||
GameState="*res://Autoload/GameState.gd"
|
GameState="*res://Autoload/GameState.gd"
|
||||||
SaveLoadManager="*res://Autoload/SaveLoadManager.gd"
|
SaveLoadManager="*res://Autoload/SaveLoadManager.gd"
|
||||||
InitializationManager="*res://Autoload/InitializationManager.gd"
|
InitializationManager="*res://Autoload/InitializationManager.gd"
|
||||||
|
LoadingContext="*res://Autoload/LoadingContext.gd"
|
||||||
|
|
||||||
[display]
|
[display]
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user