# 新手引导系统设计文档 ## 一、系统整体架构 ### 1.1 核心组件 ``` TutorialSystem/ ├── TutorialSubsystem (UGameInstanceSubsystem) │ ├── 管理引导流程状态 │ ├── 协调各个系统的引导行为 │ └── 持久化引导进度 │ ├── TutorialStepAsset (UDataAsset) │ ├── 定义每个引导步骤的配置 │ ├── 触发条件和完成条件 │ └── UI显示配置 │ ├── TutorialUIController (UObject) │ ├── 管理UI遮罩层 │ ├── 控制高亮区域 │ └── 显示引导提示 │ ├── TutorialModeInterface (Interface) │ ├── UI组件实现此接口 │ ├── 提供正常模式/引导模式切换 │ └── 提供UI元素过滤逻辑 │ └── TutorialEventListener (UObject) ├── 监听游戏事件 ├── 触发引导步骤推进 └── 验证玩家操作 ``` ### 1.2 数据流设计 ``` TutorialSubsystem (中央控制器) ↓ ├→ TutorialStepAsset (步骤配置) ├→ TutorialUIController (UI控制) ├→ QuestManager (任务系统集成) ├→ DialogueAsset (对话系统集成) ├→ FishingMapSubSystem (地图系统集成) └→ GameInfoManager (进度存档) ``` --- ## 二、核心系统设计 ### 2.1 引导子系统 (TutorialSubsystem) #### 头文件结构 ```cpp // TutorialSubsystem.h #pragma once #include "CoreMinimal.h" #include "Subsystems/GameInstanceSubsystem.h" #include "TutorialSubsystem.generated.h" // 引导步骤状态 UENUM(BlueprintType) enum class ETutorialStepState : uint8 { NotStarted, // 未开始 InProgress, // 进行中 WaitingForUser, // 等待用户操作 Completed // 已完成 }; // 引导步骤类型 UENUM(BlueprintType) enum class ETutorialStepType : uint8 { Dialogue, // 对话步骤 UIInteraction, // UI交互步骤 Gameplay, // 游戏玩法步骤 Battle, // 战斗步骤 Custom // 自定义步骤 }; // 引导事件委托 DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnTutorialStepChanged, int32, StepIndex, ETutorialStepState, NewState); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTutorialModeChanged, bool, bInTutorialMode); UCLASS() class PROJECTFISH_API UTutorialSubsystem : public UGameInstanceSubsystem { GENERATED_BODY() public: virtual void Initialize(FSubsystemCollectionBase& Collection) override; virtual void Deinitialize() override; // 引导控制 UFUNCTION(BlueprintCallable, Category = "Tutorial") void StartTutorial(); UFUNCTION(BlueprintCallable, Category = "Tutorial") void StopTutorial(); UFUNCTION(BlueprintCallable, Category = "Tutorial") void AdvanceToNextStep(); UFUNCTION(BlueprintCallable, Category = "Tutorial") void CompleteCurrentStep(); UFUNCTION(BlueprintCallable, Category = "Tutorial") bool IsInTutorialMode() const { return bInTutorialMode; } UFUNCTION(BlueprintCallable, Category = "Tutorial") int32 GetCurrentStepIndex() const { return CurrentStepIndex; } // 条件检查 UFUNCTION(BlueprintCallable, Category = "Tutorial") bool CanShowUIElement(FName ElementTag) const; UFUNCTION(BlueprintCallable, Category = "Tutorial") bool ShouldHighlightUIElement(FName ElementTag) const; // 事件委托 UPROPERTY(BlueprintAssignable, Category = "Tutorial") FOnTutorialStepChanged OnTutorialStepChanged; UPROPERTY(BlueprintAssignable, Category = "Tutorial") FOnTutorialModeChanged OnTutorialModeChanged; protected: // 引导步骤列表 UPROPERTY(EditDefaultsOnly, Category = "Tutorial") TArray TutorialSteps; // 当前状态 UPROPERTY() bool bInTutorialMode = false; UPROPERTY() int32 CurrentStepIndex = -1; UPROPERTY() ETutorialStepState CurrentStepState = ETutorialStepState::NotStarted; // UI控制器 UPROPERTY() class UTutorialUIController* UIController; private: void ExecuteStep(int32 StepIndex); void OnStepCompleted(); }; ``` --- ### 2.2 引导步骤资产 (TutorialStepAsset) #### 数据资产设计 ```cpp // TutorialStepAsset.h #pragma once #include "CoreMinimal.h" #include "Engine/DataAsset.h" #include "TutorialStepAsset.generated.h" // UI元素过滤配置 USTRUCT(BlueprintType) struct FTutorialUIFilter { GENERATED_BODY() // 可见的UI元素标签列表 UPROPERTY(EditAnywhere, BlueprintReadWrite) TArray VisibleElementTags; // 高亮的UI元素标签 UPROPERTY(EditAnywhere, BlueprintReadWrite) TArray HighlightedElementTags; // 可交互的UI元素标签 UPROPERTY(EditAnywhere, BlueprintReadWrite) TArray InteractableElementTags; // 是否使用黑名单模式(默认白名单) UPROPERTY(EditAnywhere, BlueprintReadWrite) bool bUseBlacklist = false; }; // 引导提示配置 USTRUCT(BlueprintType) struct FTutorialHintConfig { GENERATED_BODY() // 提示文本 UPROPERTY(EditAnywhere, BlueprintReadWrite) FText HintText; // 提示位置(锚定到某个UI元素) UPROPERTY(EditAnywhere, BlueprintReadWrite) FName AnchorElementTag; // 提示偏移 UPROPERTY(EditAnywhere, BlueprintReadWrite) FVector2D Offset = FVector2D::ZeroVector; // 箭头指向 UPROPERTY(EditAnywhere, BlueprintReadWrite) bool bShowArrow = true; UPROPERTY(EditAnywhere, BlueprintReadWrite) FVector2D ArrowDirection = FVector2D(0, 1); }; // 完成条件类型 UENUM(BlueprintType) enum class ETutorialCompletionType : uint8 { Manual, // 手动完成(代码调用) UIClick, // 点击指定UI TaskCompleted, // 任务完成 DialogueFinished, // 对话结束 BattleWon, // 战斗胜利 ItemCollected, // 收集物品 LocationReached // 到达位置 }; // 完成条件配置 USTRUCT(BlueprintType) struct FTutorialCompletionCondition { GENERATED_BODY() UPROPERTY(EditAnywhere, BlueprintReadWrite) ETutorialCompletionType CompletionType; // 条件参数(根据类型不同含义不同) UPROPERTY(EditAnywhere, BlueprintReadWrite) FName ConditionParameter; // 数值参数 UPROPERTY(EditAnywhere, BlueprintReadWrite) int32 NumericParameter = 1; }; UCLASS(BlueprintType) class PROJECTFISH_API UTutorialStepAsset : public UDataAsset { GENERATED_BODY() public: // 步骤基本信息 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Basic") FName StepID; UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Basic") FText StepName; UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Basic") ETutorialStepType StepType; // UI过滤配置 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI") FTutorialUIFilter UIFilter; // 引导提示 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI") FTutorialHintConfig HintConfig; // 完成条件 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Completion") FTutorialCompletionCondition CompletionCondition; // 对话资产(如果是对话步骤) UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Dialogue") class UDialogueAsset* DialogueAsset; // 特殊地图配置(如果需要) UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Map") class UMapConfigAsset* OverrideMapConfig; // 特殊战斗配置 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Battle") class UFishInfoConfigAsset* OverrideFishConfig; // 自动进入下一步的延迟时间(秒) UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Flow") float AutoAdvanceDelay = 0.0f; // 是否在此步骤暂停游戏 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Flow") bool bPauseGame = false; }; ``` --- ### 2.3 UI引导控制器 (TutorialUIController) ```cpp // TutorialUIController.h #pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "TutorialUIController.generated.h" UCLASS() class PROJECTFISH_API UTutorialUIController : public UObject { GENERATED_BODY() public: // 创建遮罩层 UFUNCTION(BlueprintCallable, Category = "Tutorial UI") void ShowMaskOverlay(); UFUNCTION(BlueprintCallable, Category = "Tutorial UI") void HideMaskOverlay(); // 高亮指定区域 UFUNCTION(BlueprintCallable, Category = "Tutorial UI") void HighlightWidget(UWidget* TargetWidget, float Padding = 10.0f); UFUNCTION(BlueprintCallable, Category = "Tutorial UI") void ClearHighlight(); // 显示引导提示 UFUNCTION(BlueprintCallable, Category = "Tutorial UI") void ShowHint(const FTutorialHintConfig& HintConfig); UFUNCTION(BlueprintCallable, Category = "Tutorial UI") void HideHint(); protected: // 遮罩Widget类 UPROPERTY(EditDefaultsOnly, Category = "Tutorial UI") TSubclassOf MaskOverlayClass; // 提示Widget类 UPROPERTY(EditDefaultsOnly, Category = "Tutorial UI") TSubclassOf HintWidgetClass; UPROPERTY() class UUserWidget* MaskOverlayWidget; UPROPERTY() class UUserWidget* HintWidget; }; ``` --- ### 2.4 UI引导接口 (ITutorialModeInterface) ```cpp // TutorialModeInterface.h #pragma once #include "CoreMinimal.h" #include "UObject/Interface.h" #include "TutorialModeInterface.generated.h" UINTERFACE(MinimalAPI, Blueprintable) class UTutorialModeInterface : public UInterface { GENERATED_BODY() }; class PROJECTFISH_API ITutorialModeInterface { GENERATED_BODY() public: // 切换到引导模式 UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Tutorial") void EnterTutorialMode(const FTutorialUIFilter& Filter); // 退出引导模式 UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Tutorial") void ExitTutorialMode(); // 检查元素是否应该显示 UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Tutorial") bool ShouldShowElement(FName ElementTag) const; // 检查元素是否应该高亮 UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Tutorial") bool ShouldHighlightElement(FName ElementTag) const; // 设置元素Tag(在UI组件中实现) UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Tutorial") void SetElementTag(FName Tag); }; ``` --- ## 三、UI双模式实现方案 ### 3.1 基础Widget改造 所有需要参与引导的Widget都应该: 1. 实现 `ITutorialModeInterface` 接口 2. 为关键子控件设置 `ElementTag` 3. 在引导模式下动态控制显示/隐藏 #### 改造示例:家园UI ```cpp // HomeUIWidget.h #pragma once #include "CoreMinimal.h" #include "Blueprint/UserWidget.h" #include "TutorialModeInterface.h" #include "HomeUIWidget.generated.h" UCLASS() class PROJECTFISH_API UHomeUIWidget : public UUserWidget, public ITutorialModeInterface { GENERATED_BODY() public: virtual void NativeConstruct() override; // ITutorialModeInterface implementation virtual void EnterTutorialMode_Implementation(const FTutorialUIFilter& Filter) override; virtual void ExitTutorialMode_Implementation() override; virtual bool ShouldShowElement_Implementation(FName ElementTag) const override; virtual bool ShouldHighlightElement_Implementation(FName ElementTag) const override; protected: // UI元素绑定 UPROPERTY(meta = (BindWidget)) class UButton* Btn_Sail; UPROPERTY(meta = (BindWidget)) class UButton* Btn_Market; UPROPERTY(meta = (BindWidget)) class UButton* Btn_Shop; UPROPERTY(meta = (BindWidget)) class UButton* Btn_Backpack; // 元素Tag映射 UPROPERTY(EditDefaultsOnly, Category = "Tutorial") TMap ElementTagMap; // 引导模式状态 bool bInTutorialMode = false; FTutorialUIFilter CurrentFilter; private: void InitializeElementTags(); void UpdateUIVisibility(); void UpdateUIHighlight(); }; ``` ```cpp // HomeUIWidget.cpp #include "HomeUIWidget.h" #include "Components/Button.h" #include "TutorialSubsystem.h" void UHomeUIWidget::NativeConstruct() { Super::NativeConstruct(); InitializeElementTags(); } void UHomeUIWidget::InitializeElementTags() { // 为每个UI元素设置Tag ElementTagMap.Add(TEXT("Btn_Sail"), Btn_Sail); ElementTagMap.Add(TEXT("Btn_Market"), Btn_Market); ElementTagMap.Add(TEXT("Btn_Shop"), Btn_Shop); ElementTagMap.Add(TEXT("Btn_Backpack"), Btn_Backpack); } void UHomeUIWidget::EnterTutorialMode_Implementation(const FTutorialUIFilter& Filter) { bInTutorialMode = true; CurrentFilter = Filter; UpdateUIVisibility(); UpdateUIHighlight(); } void UHomeUIWidget::ExitTutorialMode_Implementation() { bInTutorialMode = false; // 恢复所有元素为可见 for (auto& Elem : ElementTagMap) { if (Elem.Value) { Elem.Value->SetVisibility(ESlateVisibility::Visible); // 移除高亮效果 } } } bool UHomeUIWidget::ShouldShowElement_Implementation(FName ElementTag) const { if (!bInTutorialMode) return true; if (CurrentFilter.bUseBlacklist) { // 黑名单模式:不在列表中的显示 return !CurrentFilter.VisibleElementTags.Contains(ElementTag); } else { // 白名单模式:在列表中的显示 return CurrentFilter.VisibleElementTags.Contains(ElementTag); } } bool UHomeUIWidget::ShouldHighlightElement_Implementation(FName ElementTag) const { if (!bInTutorialMode) return false; return CurrentFilter.HighlightedElementTags.Contains(ElementTag); } void UHomeUIWidget::UpdateUIVisibility() { for (auto& Elem : ElementTagMap) { if (Elem.Value) { bool bShouldShow = ShouldShowElement_Implementation(Elem.Key); Elem.Value->SetVisibility(bShouldShow ? ESlateVisibility::Visible : ESlateVisibility::Collapsed); } } } void UHomeUIWidget::UpdateUIHighlight() { for (auto& Elem : ElementTagMap) { if (Elem.Value && ShouldHighlightElement_Implementation(Elem.Key)) { // 添加高亮效果(例如:发光边框、脉冲动画等) // 可以使用UMG动画或者材质参数 } } } ``` ### 3.2 通用UI引导基类 为了简化改造,可以创建一个基类: ```cpp // TutorialEnabledWidget.h #pragma once #include "CoreMinimal.h" #include "Blueprint/UserWidget.h" #include "TutorialModeInterface.h" #include "TutorialEnabledWidget.generated.h" UCLASS() class PROJECTFISH_API UTutorialEnabledWidget : public UUserWidget, public ITutorialModeInterface { GENERATED_BODY() public: virtual void NativeConstruct() override; virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override; // ITutorialModeInterface implementation virtual void EnterTutorialMode_Implementation(const FTutorialUIFilter& Filter) override; virtual void ExitTutorialMode_Implementation() override; virtual bool ShouldShowElement_Implementation(FName ElementTag) const override; virtual bool ShouldHighlightElement_Implementation(FName ElementTag) const override; protected: // 子类需要重写此方法来注册UI元素 UFUNCTION(BlueprintNativeEvent, Category = "Tutorial") void RegisterTutorialElements(); virtual void RegisterTutorialElements_Implementation() {} // 注册单个元素 UFUNCTION(BlueprintCallable, Category = "Tutorial") void RegisterElement(FName Tag, UWidget* Widget); // 引导模式状态 UPROPERTY(BlueprintReadOnly, Category = "Tutorial") bool bInTutorialMode = false; UPROPERTY(BlueprintReadOnly, Category = "Tutorial") FTutorialUIFilter CurrentFilter; // 元素映射 UPROPERTY() TMap ElementMap; private: void UpdateAllElements(); void ApplyHighlight(UWidget* Widget, bool bHighlight); }; ``` --- ## 四、关卡特殊配置系统 ### 4.1 战斗关卡配置扩展 为新手引导创建特殊的战斗配置: ```cpp // TutorialBattleConfig.h #pragma once #include "CoreMinimal.h" #include "Engine/DataAsset.h" #include "TutorialBattleConfig.generated.h" // 战斗事件触发点 UENUM(BlueprintType) enum class ETutorialBattleTrigger : uint8 { OnBattleStart, // 战斗开始时 OnFirstCast, // 第一次抛竿时 OnFishHooked, // 鱼上钩时 OnTurnStart, // 回合开始时 OnTurnEnd, // 回合结束时 OnVictory, // 胜利时 OnHPThreshold // HP到达阈值时 }; // 战斗中对话触发配置 USTRUCT(BlueprintType) struct FTutorialBattleDialogueTrigger { GENERATED_BODY() UPROPERTY(EditAnywhere, BlueprintReadWrite) ETutorialBattleTrigger TriggerType; UPROPERTY(EditAnywhere, BlueprintReadWrite) float TriggerValue = 0.0f; // 用于HP阈值等 UPROPERTY(EditAnywhere, BlueprintReadWrite) class UDialogueAsset* DialogueAsset; UPROPERTY(EditAnywhere, BlueprintReadWrite) bool bPauseBattle = true; }; // 强制奖励配置 USTRUCT(BlueprintType) struct FTutorialBattleReward { GENERATED_BODY() // 强制掉落的物品ID UPROPERTY(EditAnywhere, BlueprintReadWrite) TArray ForcedDropItemIDs; // 是否强制玩家拾取所有奖励 UPROPERTY(EditAnywhere, BlueprintReadWrite) bool bMustCollectAll = true; // 拾取提示文本 UPROPERTY(EditAnywhere, BlueprintReadWrite) FText CollectHintText; }; UCLASS(BlueprintType) class PROJECTFISH_API UTutorialBattleConfig : public UDataAsset { GENERATED_BODY() public: // 使用的敌人配置 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Battle") class UFishInfoConfigAsset* FishConfig; // 对话触发器列表 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Battle") TArray DialogueTriggers; // 奖励配置 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Battle") FTutorialBattleReward RewardConfig; // 禁用的UI元素 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Battle") TArray DisabledUIElements; // 是否禁用返航按钮 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Battle") bool bDisableReturnButton = false; }; ``` ### 4.2 地图系统引导模式 ```cpp // 在 FishingMapSubSystem 中添加引导模式支持 // FishingMapSubSystem.h 中添加: UCLASS() class PROJECTFISH_API UFishingMapSubSystem : public UGameInstanceSubsystem { // ... 现有代码 ... public: // 引导模式:生成固定的单节点地图 UFUNCTION(BlueprintCallable, Category = "Tutorial") void GenerateTutorialMap(const FVector2D& NodePosition); // 引导模式:只显示指定节点 UFUNCTION(BlueprintCallable, Category = "Tutorial") void SetTutorialVisibleNodes(const TArray& VisibleNodeIDs); // 引导模式:高亮指定节点 UFUNCTION(BlueprintCallable, Category = "Tutorial") void SetTutorialHighlightNode(int32 NodeID); protected: UPROPERTY() bool bInTutorialMode = false; UPROPERTY() TArray TutorialVisibleNodes; UPROPERTY() int32 TutorialHighlightNodeID = -1; }; ``` --- ## 五、实现流程步骤拆解 根据你的需求,新手引导分为15个步骤。以下是每个步骤的配置示例: ### Step 1: 家园初始对话 ```cpp // Content/DataAssets/Tutorial/Step01_HomeIntro.uasset StepID: "Tutorial_Step01" StepName: "家园初始对话" StepType: Dialogue DialogueAsset: DA_Tutorial_HomeIntro CompletionCondition: CompletionType: DialogueFinished ConditionParameter: "DA_Tutorial_HomeIntro" AutoAdvanceDelay: 0.5 ``` ### Step 2: 引导出航按钮 ```cpp // Content/DataAssets/Tutorial/Step02_SailButton.uasset StepID: "Tutorial_Step02" StepName: "引导点击出航" StepType: UIInteraction UIFilter: VisibleElementTags: ["Btn_Sail"] HighlightedElementTags: ["Btn_Sail"] InteractableElementTags: ["Btn_Sail"] HintConfig: HintText: "点击【出航】按钮开始冒险" AnchorElementTag: "Btn_Sail" bShowArrow: true CompletionCondition: CompletionType: UIClick ConditionParameter: "Btn_Sail" ``` ### Step 3: 地图界面单点 ```cpp // Content/DataAssets/Tutorial/Step03_MapSingleNode.uasset StepID: "Tutorial_Step03" StepName: "地图单节点引导" StepType: UIInteraction OverrideMapConfig: DA_Tutorial_MapConfig_SingleNode UIFilter: VisibleElementTags: ["MapNode_0"] HighlightedElementTags: ["MapNode_0"] HintConfig: HintText: "点击这个地点开始探险" AnchorElementTag: "MapNode_0" CompletionCondition: CompletionType: UIClick ConditionParameter: "MapNode_0" ``` ### Step 5: 移动按键引导 ```cpp // Content/DataAssets/Tutorial/Step05_MovementGuide.uasset StepID: "Tutorial_Step05" StepName: "移动操作引导" StepType: Gameplay HintConfig: HintText: "使用 WASD 键移动船只" Offset: (0, -200) CompletionCondition: CompletionType: LocationReached ConditionParameter: "FishingSpot_01" ``` ### Step 6-10: 战斗引导(特殊配置) ```cpp // Content/DataAssets/Tutorial/Battle01_Config.uasset FishConfig: DA_Fish_Tutorial_Bass01 DialogueTriggers: [0]: TriggerType: OnBattleStart DialogueAsset: DA_Tutorial_Battle_Intro [1]: TriggerType: OnVictory DialogueAsset: DA_Tutorial_Battle_Victory01 RewardConfig: ForcedDropItemIDs: ["Item_Bass"] bMustCollectAll: true CollectHintText: "左键选中,右键旋转,收集所有鱼获" DisabledUIElements: ["Btn_Backpack", "Btn_Return"] ``` --- ## 六、代码结构建议 ### 6.1 目录结构 ``` Source/ProjectFish/ └── Tutorial/ ├── TutorialSubsystem.h/cpp # 核心子系统 ├── TutorialUIController.h/cpp # UI控制器 ├── TutorialEventListener.h/cpp # 事件监听器 ├── TutorialModeInterface.h # UI接口 ├── DataAsset/ │ ├── TutorialStepAsset.h/cpp # 步骤资产 │ └── TutorialBattleConfig.h/cpp # 战斗配置 └── Widget/ └── TutorialEnabledWidget.h/cpp # UI基类 Content/ ├── DataAssets/ │ └── Tutorial/ │ ├── Steps/ # 引导步骤资产 │ │ ├── Step01_HomeIntro.uasset │ │ ├── Step02_SailButton.uasset │ │ └── ... │ ├── Battles/ # 战斗配置 │ │ ├── Battle01_FirstFish.uasset │ │ └── Battle02_SecondFish.uasset │ └── Maps/ # 地图配置 │ └── Tutorial_SingleNode.uasset │ └── UI/ └── Tutorial/ ├── WBP_TutorialMask.uasset # 遮罩Widget ├── WBP_TutorialHint.uasset # 提示Widget └── WBP_TutorialHighlight.uasset # 高亮效果 ``` ### 6.2 现有系统集成点 #### QuestManager 集成 ```cpp // 在 QuestManager.h 中添加: UFUNCTION(BlueprintCallable, Category = "Tutorial") void AcceptTutorialQuest(UQuestAsset* QuestAsset); ``` #### DialogueAsset 集成 ```cpp // 对话系统已经有事件委托,直接监听即可 // 在 TutorialSubsystem 中: void UTutorialSubsystem::Initialize(FSubsystemCollectionBase& Collection) { // 监听对话结束事件 // UDialogueAsset::OnDialogueFinished.AddDynamic(this, &UTutorialSubsystem::OnDialogueFinished); } ``` #### FishingMapSubSystem 集成 ```cpp // 在地图生成前检查是否引导模式 void UFishingMapSubSystem::GenerateMap() { UTutorialSubsystem* TutorialSys = GetGameInstance()->GetSubsystem(); if (TutorialSys && TutorialSys->IsInTutorialMode()) { // 使用引导专用地图配置 GenerateTutorialMap(...); return; } // 正常地图生成 ... } ``` --- ## 七、UI改造优先级 ### 高优先级(必须改造) 1. **HomeUI** - 家园界面(出航、鱼市、道具店、背包按钮) 2. **MapUI** - 地图界面(节点显示和高亮) 3. **BattleUI** - 战斗界面(技能、背包、返航按钮控制) 4. **RewardUI** - 奖励界面(强制拾取逻辑) ### 中优先级 5. **MarketUI** - 鱼市界面(任务提交) 6. **FishingSceneUI** - 钓鱼场景UI(移动提示) ### 低优先级 7. 其他辅助UI --- ## 八、实现建议 ### 8.1 分阶段实现 **Phase 1: 核心框架** - [ ] 实现 TutorialSubsystem - [ ] 实现 TutorialStepAsset - [ ] 实现 ITutorialModeInterface - [ ] 实现 TutorialUIController **Phase 2: UI改造** - [ ] 创建 TutorialEnabledWidget 基类 - [ ] 改造 HomeUI - [ ] 改造 MapUI - [ ] 改造 BattleUI - [ ] 改造 RewardUI **Phase 3: 系统集成** - [ ] 集成对话系统 - [ ] 集成任务系统 - [ ] 集成地图系统 - [ ] 集成战斗系统 **Phase 4: 配置数据** - [ ] 创建15个引导步骤资产 - [ ] 创建引导专用对话 - [ ] 创建引导专用战斗配置 - [ ] 创建引导专用地图配置 **Phase 5: 测试优化** - [ ] 流程测试 - [ ] UI表现优化 - [ ] 存档系统集成 - [ ] Bug修复 ### 8.2 关键技术点 1. **UI遮罩实现**:使用 Canvas Panel + Image(黑色半透明)+ Retainer Box(剪切高亮区域) 2. **高亮效果**: - 方案A:Material + 发光参数 - 方案B:UMG Animation(缩放脉冲) - 方案C:Border + 高亮颜色 3. **事件监听**: - 使用委托系统 - 在 TutorialEventListener 中统一管理 - 避免硬编码,使用数据驱动 4. **存档集成**: - 在 PlayerInfoSaveGame 中添加: ```cpp UPROPERTY() bool bTutorialCompleted = false; UPROPERTY() int32 LastCompletedTutorialStep = -1; ``` --- ## 九、最佳实践建议 ### 9.1 设计原则 - **数据驱动**:所有配置用 DataAsset,方便策划调整 - **解耦设计**:引导系统不侵入现有逻辑 - **接口隔离**:UI组件实现接口即可支持引导 - **事件驱动**:使用委托而非轮询 ### 9.2 性能优化 - 引导模式下禁用不必要的Tick - UI过滤用 Collapsed 而非 Hidden(减少渲染) - 遮罩层使用单例复用 ### 9.3 可扩展性 - 预留自定义步骤类型 - 支持蓝图扩展 TutorialStepAsset - UI标签系统支持动态注册 --- ## 十、示例流程图 ``` [游戏启动] ↓ [检查存档:是否完成引导] ↓ 否 [TutorialSubsystem::StartTutorial()] ↓ [Step 1: 家园对话] → DialogueAsset 播放 ↓ 对话结束 [Step 2: 出航按钮] → HomeUI.EnterTutorialMode({Btn_Sail}) ↓ 点击出航 [Step 3: 地图界面] → MapUI.EnterTutorialMode({MapNode_0}) ↓ 点击节点 [Loading...] ↓ [Step 4-10: 战斗流程] ├→ Step 5: 移动引导 ├→ Step 6: 钓鱼引导 ├→ Step 7: 战斗1 + 收获 ├→ Step 8: 对话提示 ├→ Step 9: 战斗2(中间插入对话) └→ Step 10: 收获(魔法书) ↓ [Step 11: 返航引导] → 显示返航按钮 ↓ [Loading...] ↓ [Step 12-15: 家园流程] ├→ Step 13: 家园对话 ├→ Step 14: 鱼市引导 + 任务提交 └→ Step 15: 解锁功能 ↓ [引导完成] → 保存进度 → 退出引导模式 ``` --- ## 总结 这套新手引导系统设计具有以下特点: ✅ **非侵入式**:通过接口和子系统,不破坏现有代码结构 ✅ **数据驱动**:使用 DataAsset 配置所有步骤,策划友好 ✅ **灵活可扩展**:支持自定义步骤类型和条件 ✅ **UI双模式**:正常模式和引导模式无缝切换 ✅ **系统集成**:充分利用现有的对话、任务、地图、战斗系统 ✅ **性能友好**:按需加载,最小化运行时开销 建议按照分阶段实现计划逐步推进,优先完成核心框架和关键UI改造。