2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UEFN / VerseAdvent Calendar 2023

Day 13

【UEFN】VerseでUIを作ってみる

Posted at

背景

最近の上位に出てきている島には大体オリジナルUIがあります。そこでどのように実装するのか知りたくなったので書き残しておきます。

image.png

image.png

やること

プレイヤーごとにスコアを表示するオリジナルUIを表示させるようにしました。

動画

実装

スコアが増えるトリガーの実装

トリガーとスコアマネージャーを配置
image.png

スコアマネージャーとトリガーを結び付けてトリガーが押されたらスコアが追加されるようにします。
image.png

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に関しては要素の位置調整がとても大変です。marginanchorsの数字を少しずつずらしてはフォートナイト起動の繰り返しになります(笑)このあたりもテンプレート化できそうなのでもっと調査していきたいと思います。

余談

この度UEFN/Verseに関するオープンコミュニティサーバーを建ち上げました。ちょっとでも興味があれば奮ってご参加くださいませ。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?