classDiagram note for HUD "HUDは全てを含む" note for AuraUserWidget "AuraUserWidgetはControllerを持っている" note for AuraUserWidgetController "ControllerはWidgetを知る必要がない" class HUD{ +OverlayWidget -OverlayWidgetController -OverlayWidgetClass -OverlayWidgetControllerClass +GetOverlayWidgetController() +SetOverlayWidgetController(FWidgetControllerParams) +InitOverlay(APlayerController* PC, APlayerState* PS, UAbilitySystemComponent* ASC, UAttributeSet* AS) } class AuraUserWidget { +WidgetController +SetWidgetController() -WidgetControllerSet() } class AuraUserWidgetController { -SetWidgetControllerParams() +PlayerController +PlayerState +AbilitySystemComponent +AttributeSet } class FWidgetControllerParams { +PlayerController +PlayerState +AbilitySystemComponent +AttributeSet } class BP_OverlayWidget{ } class OverlayWdigetController { } OverlayWdigetController --|> AuraUserWidgetController : Inheritance BP_OverlayWidget --|> AuraUserWidget : Inheritance AuraUserWidgetController --* AuraUserWidget : Composition OverlayWdigetController --* BP_OverlayWidget : Composition BP_OverlayWidget --* HUD : Composition FWidgetControllerParams ..> AuraUserWidget : Defined in this
概要
section 05 UI
- Use UUserWidget BP Class to implement Widgets
- Creating Widget and Widget Controller C++ class.
- Creating a WBP derived from Widget class.
- Making WBP reusable in other classes, Setting up contents in Hierachybars Variable.
- Setting up those variables by Blueprint
- When setting up padding “Slot as Overlay Slot” was used.
- Making HUD Class.
- In the HUD class, make a overlay variable.
- BP_HUD class.
- Also creating a HUD Controller class
- Creating and add to viewport overlay widget
- Setting up Widget Controller
- Creating
struct FWidgetControllerParams
- Creating Setter for controller based on FWidgetControllerParams.
- Creating
- Init Widgets Function in HUD. Execute in CharacterController
- Create Delegate for OnHealthChange
- Use DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam
- Setup Broadcast in Init
- Bindcallback in Controller
- ASC already has a delegate for valuechange:
GetGameplayAttributeValueChangeDelegate
- Bind Function to it and in that funtion, broadcasting controller’s onchanged delegate is a good way
- ASC already has a delegate for valuechange:
- Setup Mana
発見
Setting up Images by Slate Brush
Slate Brushを使ってImagesのSet Brush関数で画像を定義した。
Hierarchie of HUD
Delegate について続き。
Delegateは、いろんな関数のAdressをStoreしたもの。で、UEの場合、そのDelegateの定義は
OverlayWidgetController.cpp
(FOnHealthChangedSignature, float, NewHealth); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam
のようにする。これで定義したDelegateの変数の定義は
OverlayWidgetController.cpp
(BlueprintAssignable, Category = "GAS|Attributes")
UPROPERTY; FOnHealthChangedSignature OnHealthChanged
のようにしておき、この変数の中に関数のアドレスを入れるのに使うのは、他のcppファイルでやる。例えばWidgetはControllerを知っているけど、Controllerは知らないので、
OverlayWidget.cpp
void UOverlayWidget::WidgetControllerSet()
{
->OnHealthChanged.AddDynamic(this, &UOverlayWidget::OnHealthChanged)
WidgetController}
void UOverlayWidget::OnHealthChanged(float NewHealth)
{
= NewHealth / MaxHealth;
percent }
こんな感じに設定する。それで、このOnHealthChanged
を呼びたいときは、
OverlayWidgetController.cpp
void UOverlayWidgetController::DealDamage()
{
-= 10;
Health
.Broadcast(Health)
OnScoreChangedDelegate}
としている。けど、なんでControllerはWidget本体を知らない方がいいのか……?
これらについてもう少し考えてみる。
つまりは、ControllerがCharacterとかのデータのやり取りを全てしており、WidgetがControllerにアクセスすればすべての欲しいものがあると。それから、全部のWidgetをTickさせながらアクセスするのは馬鹿らしいので、ControllerがDelegateを持って、Widget側がそれに関数をAssignさせ、Widgetに依存せずに知らないControllerが淡々とTickとUpdateをしていくわけだ。
こうすることによって、Widgetの数が増えても、考えるべきなのはWidgetの中でDelegateにAssignする関数だけで済むし、Controllerは淡々と必用なVariablesを必用に応じてUpdateして、Delegateの実行、つまりBroadCastをしていくだけである。複雑になってもこれは変わらないので、Module性が高まる。
Slot as Overlay SlotなどのUI関連
Comprehensiveなチュートリアルとかドキュメントとかを読む必要あり。