讓我們繼續《塞爾達傳說》中林克技能的制作!!!
UE版本:5.6.0
VS版本:2022
本章節的核心目標:技能面板
先讓我們看一下完成后的效果:
第14章效果
本章節項目鏈接:
通過網盤分享的文件:14_技能面板
鏈接: https://pan.baidu.com/s/1BcNuIlxd2elJZd70RfJgug 提取碼: rd7w
–來自百度網盤超級會員v3的分享
已經完成的功能:
動作 | 按鍵 | 是否完成 |
---|---|---|
移動 | W、S、A、D | 完成 |
疲勞 | 無 | 完成 |
沖刺 | Left Shift | 完成 |
滑行與跳躍 | Space | 完成 |
下落 | 無 | 完成 |
預計制作的技能:
技能(符文) | 按鍵 | 是否完成 |
---|---|---|
RBB(方向遙控炸彈) | 未設定 | 未開始 |
RBS(圓形遙控炸彈) | 未設定 | 未開始 |
Mag(磁鐵) | 未設定 | 未開始 |
Stasis(時間靜止) | 未設定 | 未開始 |
Ice(凍結) | 未設定 | 未開始 |
UI交互
UI面板 | 按鍵 | 是否完成 |
---|---|---|
打開(關閉)技能面板 | Tab | 進行中 |
本章節的項目文件:
技能的圖標:
說明:每種技能共有4個圖標,用來表示4個不同的狀態。
Disable_Hover_Pressed:表示的是鼠標在未選中的圖標上懸停和按下的效果。
Disable_Normal:表示的是未選中的圖標(正常狀態下的顯示)。
Enable_Hover_Pressed:表示的是鼠標在選中的圖標上懸停和按下的效果。
Enable_Normal:表示的是選中的圖標顯示的效果。
0.導入素材
??將文件夾內的圖片全部拖拽進UE中。
??為了防止模糊,我們將這些圖片的壓縮方式設置為UserInterface2D
具體操作為:全選圖片=》右鍵【資產操作】=》【編輯屬性矩陣中的選擇】
選擇【壓縮】=》壓縮設置【UserInterface2D】
1.ZSCharBase.h中新建符文的枚舉類
UENUM(BlueprintType)
enum class ERunes : uint8
{R_EMAX UMETA(DisplayName = "EMAX"),R_RBB UMETA(DisplayName = "方形遙控炸彈"),R_RBS UMETA(DisplayName = "圓形遙控炸彈"),R_Mag UMETA(DisplayName = "磁鐵"),R_Stasis UMETA(DisplayName = "時間靜止"),R_Ice UMETA(DisplayName = "凍結")
};UCLASS()
class ZELDARSKILLS_API AZSCharBase : public ACharacter
{GENERATED_BODY()
public:};
2.制作 - 顯示技能圖標用的格子
??目的1: 方便添加和管理圖標的顯示。
??目的2: 用于選中技能事件的邏輯交互(我們得獲知玩家點擊到了哪一個技能,然后才能執行后續的邏輯)。
2.1 新建用戶控件藍圖(命名為:UI_RuneSlot)
??命名為UI_RuneSlot,用于顯示技能圖標。
2.2 為UI_RuneSlot添加尺寸框
??尺寸框(Size Box)作用:控制子控件尺寸的核心布局容器。在這里我們用到了它的子布局:寬度重載和高度重置。
??具體而言:添加尺寸框到UI_RuneSlot下后,勾選:寬度重載和高度重載,并將其值設置為250,而后選擇屏幕上所需。
2.3 為UI_RuneSlot添加勾選框
??勾選框(Check Box)作用:在本次項目而言,主要作用為與鼠標進行交互,能夠根據鼠標當前的一個操作情況顯示圖片。它的尺寸大小由尺寸框控制。
??重命名為CB,并勾選其為變量。后續在藍圖中有用。
2.3.1(測試)為勾選框添加一張任意圖片
??目的:根據這張技能圖標顯示情況,獲取到圖片在勾選框應該顯示的大小。如下圖所示,明顯圖片填入后偏大(因為這個圖片是512x512的)。
??將圖片的大小(Image Size)設置為250和250,就剛好合適(記下這個值,后面我們在藍圖中用得到)。
2.3.2(可選)禁用鍵盤選中技能圖標
??如果你不希望玩家通過鍵盤來選擇符文,你可以取消勾選框內的該屬性。
2.3.3(可選)調整勾選框內顯示的圖片
??不調整的話,勾選框內顯示的圖片與你導入的圖片相比會偏暗。這是由勾選框的前景顏色所引起的,取消繼承,并將前景顏色改為全白既可以解決這個問題。
2.4 自定義添加圖片功能(UI_RuneSlot藍圖)
2.4.1(藍圖)觸發事件和設置的目標屬性
??是編輯器內部的功能:Event Pre Construct 觸發。設置的目標屬性是勾選框的樣式:Make Check Box Style。
2.4.2(藍圖)設置Unchcked Image
??Unchecked Image的值通過Make Slate Brush賦值。這個筆刷繪制用的“顏料”,就是我們的素材。接下來為我們的筆刷準備“顏料”
??(1)Make Slate Brush的Image_Size設置為:(250,250)。
??(2)新建變量(Texture 2D【紋理2D】),并命名為:IMG_D_N:用于接收名字帶有Disabled_Normal的圖片。Make Slate Brush的Image設置為:IMG_D_N。
2.4.3(藍圖)設置Unchecked Hovered Image和Unchecked Pressed Image
??與2.4.2的操作完全一致。
2.4.4(藍圖)設置剩下的情況
2.4.5(藍圖)變量細節設置
??為了讓這些變量可以由我們手動進行賦值(添加圖片),因此我們要勾選可編輯實例和生成時公開。
2.4.6(藍圖,可選)Foreground Color 設置
2.4.7(完成)功能完成示意圖
2.5 選中符文的邏輯交互(UI_RuneSlot藍圖)
2.5.1(藍圖)添加事件-勾選狀態變化時
??當玩家點擊UI_RuneSlot后觸發的事件。
2.5.2(藍圖)新建事件分發器
??事件分發器的作用:用于管理和調度事件的傳遞與響應。它允許廣播事件,其他對象可根據需要訂閱這些事件,從而實現對象間的消息傳遞。
??新建一個事件分發器,命名為OnClicked,我們讓它傳遞如下兩個參數:
??(1)新建變量(文本)Name:用于傳遞點擊的符文名字
??(2)新建變量(ERunes)RuneType:用于傳遞點擊的符文類型。
??PS:記得勾選 (1)可編輯實例和(2)生成時公開
2.5.3(藍圖)新建函數獲取設置格子選中狀態
??目的:方便設置當前格子的選中狀態。
??(1)新建一個函數:命名為CheckStatus
??(2)內部邏輯:設置勾選框的Checked即可。
2.5.4(完成)功能完成示意圖
??編譯執行后,回到UI_RuneSlot設計器界面,顯示如下內容,為該部分功能完成。
3.制作 - 技能面板
??目的1:顯示所有的技能(UI_RuneSlot)
??目的2:管理技能選中邏輯
3.1 新建C++腳本(命名為:ZSRuneSelections)
3.2 創建基于ZSRuneSelections的藍圖類
??右鍵ZSRuneSelections,選擇創建基于ZSRuneSelections的藍圖類,并命名為UI_RuneSelections,放到UI文件夾下。
3.3 搭建技能面板
3.3.1(UI設計)添加畫布面板
??(1)添加畫布面板;
??(2)為畫布面板,添加一個背景模糊(Background Blur),調整其參數:全覆蓋,將偏移量置為0,模糊強度設置為1。【添加背景模糊的目的:讓打開技能面板的時候,背景顯示模糊。】
3.3.2(UI設計)添加水平框
??目的:管理技能。
??參數設置:
??(1)錨點:中心
??(2)位置X:0;位置Y:0;
??(3)對齊:(0.5,0.5)【說明:中心位置】;
??(4)尺寸X:1250【說明:有5個技能,每個技能長250,因此 為5x250=1250】。
??(5)尺寸Y:250【說明:高度就是250】
??(6)重命名:HB_RuneContainer,并勾選其為變量
3.4 添加格子到技能面板中
??拖拽5個UI_RuneSlot到水平框下。
3.5 設置UI_RuneSlot的參數
??以RBS為例。
3.6 交互文本
??創建一個文本,該文本的作用是顯示當前選中的技能名字。設置成如下圖所示,并記得勾選其為變量。
4. 代碼 - 選擇技能
4.1 技能面板與角色的交互
4.1.1 角色獲知當前選中的技能
簡單來說:ZSRuneSelections:告知ZSCharBase,當前選中的技能是誰。
具體而言:
ZSCharBase.h:
// 當前選中的符文UPROPERTY(EditAnywhere, Category = "Runes")ERunes ActiveRune{ ERunes::R_EMAX };
ZSRuneSelections.h:
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "ZSCharBase.h"
#include "ZSRuneSelections.generated.h"/*** */
UCLASS()
class ZELDARSKILLS_API UZSRuneSelections : public UUserWidget
{GENERATED_BODY()public:UPROPERTY(EditAnywhere, BlueprintReadWrite)AZSCharBase* playerRef;UFUNCTION(BlueprintCallable)// 設置:角色當前選中的技能void SelectedRuneType(ERunes RuneType);
};
ZSRuneSelections.cpp:
// Fill out your copyright notice in the Description page of Project Settings.#include "UI/ZSRuneSelections.h"void UZSRuneSelections::SelectedRuneType(ERunes RuneType)
{// 玩家選擇技能if (playerRef){playerRef->ActiveRune = RuneType; // 更新玩家選中的技能}
}
4.2 UI_RuneSelections管理UI_RuneSlot
??我們希望通過UI_RuneSelections去管理所有的技能格子(UI_RuneSlot)。
4.2.1(藍圖)注冊UI_RuneSlot的OnClicked事件的響應函數
??通過UI_RuneSelections注冊UI_RuneSlot的OnClicked事件的響應函數。
??綁定的響應函數為(自定義的:SelectedRune),該函數的功能如下:
(1)告知角色當前選中的技能(SelectRuneType方法)。
(2)UIRuneSlot根據自身是否被選中設置其選中狀態(Check Status)。
(3)UI_RuneSelections的TXT_Hint顯示的內容設置為當前選中的符文名字。
??整體一覽:
5.通過Tab鍵 - 玩家與技能面板交互
5.1 為UI_ZSLayout的畫布面板創建控件切換器
5.1.1 UI_ZSLayout介紹
??UI_ZSLayout是本人文章UE5 - 制作《塞爾達傳說》中林克的技能 - 9 - 耐力條制作(涉及藍圖)中,創建的。
??內部構造很簡單,就一個耐力條,如下圖
??涉及的藍圖邏輯與耐力條的值有關,如下圖所示。
??藍圖中的Update Stamina函數的內容如下圖:
5.1.2 創建控件切換器
??選中UI_ZSLayout的畫布面板,右鍵,選擇包裹->控件切換器。
??重命名為WS,并勾選為變量
5.1.3 創建新的畫布面板
??存放PB_ST的畫布面板重命名為StatusPanel,將新建的畫布面板重命名為RunesPanel。
5.1.4 添加UI_RuneSelections
?? 將UI_RunesSelections拖拽到RunesPanel下面,調整大小,全覆蓋,偏移值設置為0,并將其勾選為變量。
5.2 輸入操作與交互邏輯
5.2.1 UE創建輸入操作資產
??命名為:IA_ToogleUI
??設置其為暫停時觸發。
??老規矩,到IMC_ZS_Settings添加,并設置為tab鍵
5.2.2 (cpp)交互邏輯
ZSCharBase.h:
// 聲明 喚出技能面板動作UPROPERTY(EditAnywhere, Category = "Inputs")UInputAction* ToggleUIAction;// 指向UZSLayout類型的UObject實例,用于管理UI布局的生命周期// 該指針由UE5垃圾回收系統自動管理,無需手動釋放UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI")TObjectPtr<UZSLayout> LayoutRef;#pragma region ToggleUIUFUNCTION()// Tab - 按下 - 觸發的函數void ToggleUI_Started(const FInputActionValue& val);
#pragma endregionUFUNCTION(BlueprintImplementableEvent)// 獲取角色當前切換的【畫布面板】編號// 如當前的Status Panel 編號為:0int32 GetWSIndexInfo();UFUNCTION(BlueprintImplementableEvent)// 設置角色當前切換的【畫布面板】編號,用于與UI交互// 如我設置為 0:則關閉技能面板顯示void SetWSIndex(int32 index);
ZSCharBase.cpp:
void AZSCharBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{Super::SetupPlayerInputComponent(PlayerInputComponent);// UIEIComp->BindAction(ToggleUIAction, ETriggerEvent::Started, this, &AZSCharBase::ToggleUI_Started);}void AZSCharBase::ToggleUI_Started(const FInputActionValue& val)
{AZSPlayerController* PC = Cast<AZSPlayerController>(Controller);// 判斷當前顯示的面板是否為 技能面板if (GetWSIndexInfo() == 1){// ----- 隱藏技能面板 ------// 關閉鼠標顯示PC->bShowMouseCursor = false;// 將玩家控制器的輸入模式設置為僅游戲模式PC->SetInputMode(FInputModeGameOnly());// 繼續游戲PC->SetPause(false);// 隱藏技能面板 - 將控件切換器的索引設置為0(狀態面板)SetWSIndex(0);}else{// ----- 顯示技能面板 ------// 顯示鼠標 - 我們要用來選技能PC->bShowMouseCursor = true;// 設置玩家控制器為游戲與UI混合輸入模式,并聚焦到指定UI組件// 讓玩家能夠通過鼠標與UI元素進行交互FInputModeGameAndUI InputHandle;InputHandle.SetWidgetToFocus(LayoutRef->TakeWidget());PC->SetInputMode(InputHandle);// 暫停游戲PC->SetPause(true);// 顯示技能面板 - 將控件切換器的索引設置為1SetWSIndex(1);}}
5.2.3(藍圖)交互邏輯
??先添加IA_ToogleUI到BP_Player中。
??實現GetWSIndexInfo:
(1)獲取到Layout Ref(也就是咱們的ZSLayoutUI)。
(2)拿到其下的WS,返回激活的Index。
(3)若是LayoutRef的值無效,返回-1(即:什么都不會做)
??實現SetWSIndex:
(1)獲取到Layout Ref(也就是咱們的ZSLayoutUI)。
(2)(2)拿到其下的WS,設置其Index(為傳入的Index)。
第14部分完成啦!!
十分感謝大家的閱讀、點贊、收藏!!
如果有不足之處,有疑問之處,有錯誤地方,歡迎大家在評論區討論、批評、指正!!!