背景
最近の上位に出てきている島には大体オリジナルUIがあります。そこでどのように実装するのか知りたくなったので書き残しておきます。
やること
プレイヤーごとにスコアを表示するオリジナルUIを表示させるようにしました。
動画
実装
スコアが増えるトリガーの実装
スコアマネージャーとトリガーを結び付けてトリガーが押されたらスコアが追加されるようにします。
UI実装部分全体コード
以下の記事を参考にしました。
player_widgetクラス
using { /Fortnite.com/UI }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Colors }
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/SpatialMath }
player_widget := class():
score_manager:score_manager_device
ScoreText<localizes>(Score: int) : message = "{Score}"
score_widget : text_block = text_block{DefaultTextColor:= color{R:=1.0, G:=1.0, B:=1.0},DefaultJustification:=text_justification.Center}
CreateWidget(Score : int) : canvas =
score_widget.SetText(ScoreText(Score))
MyCanvas : canvas = canvas:
Slots := array:
canvas_slot:
Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.5}, Maximum := vector2{X := 0.0, Y := 0.5}}
Offsets := margin{Top := 24.0, Left := 150.0, Right := 100.0}
Alignment := vector2{X := 0.0, Y := 0.0}
SizeToContent := false
ZOrder := {Z := 2}
Widget := score_widget
ShowWidget(Agent : agent) : void =
Print("ShowUI")
#AgentからPlayerUIを取得する
if (Player := player[Agent], PlayerUI := GetPlayerUI[Player]):
Print("Create UI")
NewUI := CreateWidget(0)
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.None})
spawn {UpdateWidget(Agent)}
UpdateWidget(Agent : agent)<suspends>: void =
loop:
Sleep(1.0)
score := score_manager.GetCurrentScore(Agent)
score_widget.SetText(ScoreText(score))
このクラスでUIにどのような要素をどのように配置するか指定しています。
MyCanvas : canvas = canvas:
Slots := array:
配列型で指定してるということでここに入れたいUIの要素とそれをどのような場所に入れるのか指定しています。UIをもう一つ追加したいなら以下のようになります。
MyCanvas : canvas = canvas:
Slots := array:
canvas_slot:
Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.5}, Maximum := vector2{X := 0.0, Y := 0.5}}
Offsets := margin{Top := 24.0, Left := 150.0, Right := 100.0}
Alignment := vector2{X := 0.0, Y := 0.0}
SizeToContent := false
ZOrder := {Z := 2}
Widget := score_widget
canvas_slot:
Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.5}, Maximum := vector2{X := 0.0, Y := 0.5}}
Offsets := margin{Top := 20.0, Left := 150.0, Right := 100.0}
Alignment := vector2{X := 0.0, Y := 0.0}
SizeToContent := false
ZOrder := {Z := 2}
Widget := sample_widget
今回は以下のようなただのテキストブロックだけですがスライダーやボタンなどもUIに追加できたりします。またの機会に紹介します。
score_widget : text_block = text_block{DefaultTextColor:= color{R:=1.0, G:=1.0, B:=1.0},DefaultJustification:=text_justification.Center}
UpdateWidget
ではUIに表示するスコアの更新をしています。一秒ごとにスコアを確認しそれをUIに代入している感じです。
player_widget_managerクラス
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
player_widget_manager := class(creative_device):
@editable
score_manager:score_manager_device=score_manager_device{}
var PlayerModel: [player]?player_widget = map{}
OnBegin<override>()<suspends>:void=
spawn {CheckForPlayers()}
CheckForPlayers()<suspends>: void =
loop:
Sleep(1.0)
AllPlayers := GetPlayspace().GetPlayers()
for (Player : AllPlayers):
if (not PlayerModel[Player]):
if (Agent := agent[Player]):
PlayerWidgetInstance := player_widget { score_manager := score_manager }
if (set PlayerModel[Player] = option{PlayerWidgetInstance}):
PlayerWidgetInstance.ShowWidget(Agent)
spawn {PlayerWidgetInstance.UpdateWidget(Agent)}
このクラスはUIを生成するエントリーポイントを提供しています。CheckForPlayers
という関数で現在同じセッションにいるすべてのプレイヤー情報を取得してPlayerModel
というmap型
に登録しています。すでにPlayerModel
に登録されUIを生成しているプレイヤーに重ねてUIを表示しないようにif (not PlayerModel[Player]):
で生成されないようになっています。
まとめ
UIに関しては要素の位置調整がとても大変です。margin
やanchors
の数字を少しずつずらしてはフォートナイト起動の繰り返しになります(笑)このあたりもテンプレート化できそうなのでもっと調査していきたいと思います。
余談
この度UEFN/Verseに関するオープンコミュニティサーバーを建ち上げました。ちょっとでも興味があれば奮ってご参加くださいませ。