Trackerの進行状況をUIで出力する方法
はじめに
今回ご説明するのは、Trackerの現在の情報をVerseを通してUIとして表示させるコードです。Tycoonなどでよく使われる技術です。
手順は以下の通りです。
- Verseを使用して、各プレイヤーのUI情報を作成します。
- UEFNに戻り、ステップ1で作成したUI情報をトラッカーに結びつけます。
- トラッカーの設定を行い、ボタンデバイスなどを使用してトラッカーの進捗が進む仕組みを構築します。
- ゲームを開始し、ボタンを押すとUIが更新されるようにします(上記の画像を参照)
参考動画
全体コード
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/UI }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Fortnite.com/UI }
using { /Verse.org/Colors }
using { /Verse.org/Colors/NamedColors }
resource_count := class(creative_device):
SeparateNumberWithCommas(Number:int):string=
var ConvertedString : string = "{Number}"
var ReturnString : string = ""
for(Index:=0..ConvertedString.Length-1):
if(Mod[ConvertedString.Length-Index,3]= 0 and Index<>0):
set ReturnString = ReturnString + ","
if(Char:=ConvertedString[Index]):
set ReturnString = ReturnString + "{Char}"
return ReturnString
var UIStuffPerAgent:[agent]?tuple(canvas,text_block,text_block,text_block,text_block) = map{}
@editable RefreshRate : float = 0.5
@editable ConditButton : conditional_button_device = conditional_button_device{}
@editable ElimTracker : tracker_device = tracker_device{}
@editable XPTracker : tracker_device = tracker_device{}
@editable HackTracker : tracker_device = tracker_device{}
@editable PlayerSpawners : []player_spawner_device = array{}
OnBegin<override>()<suspends>:void=
for(PS:PlayerSpawners):
PS.SpawnedEvent.Subscribe(PlayerSpawned)
S2M<localizes>(S:string):message="{S}"
UpdateUI(Agent:agent):void=
if(Stuff:=UIStuffPerAgent[Agent]?):
MyGold:=ConditButton.GetItemCount(Agent,0)
Stuff(1).SetText(S2M("${SeparateNumberWithCommas(MyGold)}"))
MyElims:=ElimTracker.GetValue(Agent)
Stuff(2).SetText(S2M("{SeparateNumberWithCommas(MyElims)} Elims"))
MyXP:=XPTracker.GetValue(Agent)
Stuff(3).SetText(S2M("{SeparateNumberWithCommas(MyXP)}"))
MyHack:=HackTracker.GetValue(Agent)
Stuff(4).SetText(S2M("{SeparateNumberWithCommas(MyHack)}"))
PlayerSpawned(Agent:agent):void=
if(Stuff:=UIStuffPerAgent[Agent]?):
else:
AddUI(Agent)
RemoveUI(Agent:agent):void=
if:
PlayerUI:=GetPlayerUI[player[Agent]]
Stuff:=UIStuffPerAgent[Agent]?
then:
PlayerUI.RemoveWidget(Stuff(0))
if(set UIStuffPerAgent[Agent] = false){}
AddUI(Agent:agent):void=
if:
PlayerUI:=GetPlayerUI[player[Agent]]
then:
Stuff:=MakeCanvas()
Canvas:=Stuff(0)
GoldBlock:=Stuff(1)
ElimBlock:=Stuff(2)
XPBlock:=Stuff(3)
HackBlock:=Stuff(4)
PlayerUI.AddWidget(Canvas)
if(set UIStuffPerAgent[Agent] = option{Stuff}){}
spawn{LoopUpdate(Agent)}
LoopUpdate(Agent:agent)<suspends>:void=
loop:
Sleep(RefreshRate)
UpdateUI(Agent)
if(not UIStuffPerAgent[Agent]?):
return
MakeCanvas():tuple(canvas,text_block,text_block,text_block,text_block)=
GoldTextBlock:=text_block{DefaultText:=S2M(""),DefaultTextColor:=White,DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
GoldTextBlock.SetShadowOpacity(1.0)
ElimTextBlock:=text_block{DefaultText:=S2M(""),DefaultTextColor:=White,DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
ElimTextBlock.SetShadowOpacity(1.0)
XPTextBlock:=text_block{DefaultText:=S2M(""),DefaultTextColor:=White,DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
XPTextBlock.SetShadowOpacity(1.0)
HackTextBlock:=text_block{DefaultText:=S2M(""),DefaultTextColor:=White,DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
HackTextBlock.SetShadowOpacity(1.0)
MyCanvas:= canvas:
Slots:=array:
canvas_slot:
Anchors:=anchors{Minimum:=vector2{X:=0.0,Y:=0.8},Maximum:=vector2{X:=0.0,Y:=0.8}}
Offsets:=margin{}
Alignment:=vector2{X:=0.0,Y:=1.0}
SizeToContent:=true
Widget:=stack_box:
Orientation:= orientation.Vertical
Slots:=array:
stack_box_slot:
HorizontalAlignment:=horizontal_alignment.Left
VerticalAlignment:=vertical_alignment.Fill
Widget:=overlay:
Slots:=array:
overlay_slot:
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Fill
Widget:=texture_block:
DefaultImage:=IMG.back_black2
DefaultDesiredSize:=vector2{X:=0.0,Y:=90.0}
overlay_slot:
Widget:=stack_box:
Orientation:=orientation.Horizontal
Slots:=array:
stack_box_slot:
Widget:=texture_block:
DefaultImage:=IMG.ai_robot2
DefaultDesiredSize:=vector2{X:=55.0,Y:=55.0}
stack_box_slot:
Widget:=GoldTextBlock
Padding:=margin{Left:=20.0}
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Center
Padding:=margin{Left:=30.0,Right:=30.0}
HorizontalAlignment:=horizontal_alignment.Center
VerticalAlignment:=vertical_alignment.Center
stack_box_slot:
HorizontalAlignment:=horizontal_alignment.Left
VerticalAlignment:=vertical_alignment.Fill
Padding:=margin{Top:=10.0,Bottom:=10.0}
Widget:=overlay:
Slots:=array:
overlay_slot:
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Fill
Widget:=texture_block:
DefaultImage:=IMG.back_black2
DefaultDesiredSize:=vector2{X:=0.0,Y:=90.0}
overlay_slot:
Widget:=stack_box:
Orientation:=orientation.Horizontal
Slots:=array:
stack_box_slot:
Widget:=texture_block:
DefaultImage:=IMG.ai_robot3
DefaultDesiredSize:=vector2{X:=55.0,Y:=55.0}
stack_box_slot:
Widget:=ElimTextBlock
Padding:=margin{Left:=20.0}
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Center
Padding:=margin{Left:=30.0,Right:=30.0}
HorizontalAlignment:=horizontal_alignment.Center
VerticalAlignment:=vertical_alignment.Center
stack_box_slot:
HorizontalAlignment:=horizontal_alignment.Left
VerticalAlignment:=vertical_alignment.Fill
Padding:=margin{Top:=10.0,Bottom:=10.0}
Widget:=overlay:
Slots:=array:
overlay_slot:
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Fill
Widget:=texture_block:
DefaultImage:=IMG.back_black2
DefaultDesiredSize:=vector2{X:=0.0,Y:=90.0}
overlay_slot:
Widget:=stack_box:
Orientation:=orientation.Horizontal
Slots:=array:
stack_box_slot:
Widget:=texture_block:
DefaultImage:=IMG.AIGirl_01
DefaultDesiredSize:=vector2{X:=55.0,Y:=55.0}
stack_box_slot:
Widget:=XPTextBlock
Padding:=margin{Left:=20.0}
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Center
Padding:=margin{Left:=30.0,Right:=30.0}
HorizontalAlignment:=horizontal_alignment.Center
VerticalAlignment:=vertical_alignment.Center
stack_box_slot:
HorizontalAlignment:=horizontal_alignment.Left
VerticalAlignment:=vertical_alignment.Fill
Padding:=margin{Top:=10.0,Bottom:=10.0}
Widget:=overlay:
Slots:=array:
overlay_slot:
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Fill
Widget:=texture_block:
DefaultImage:=IMG.back_black2
DefaultDesiredSize:=vector2{X:=0.0,Y:=90.0}
overlay_slot:
Widget:=stack_box:
Orientation:=orientation.Horizontal
Slots:=array:
stack_box_slot:
Widget:=texture_block:
DefaultImage:=IMG.Compute1r
DefaultDesiredSize:=vector2{X:=55.0,Y:=55.0}
stack_box_slot:
Widget:=HackTextBlock
Padding:=margin{Left:=20.0}
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Center
Padding:=margin{Left:=30.0,Right:=30.0}
HorizontalAlignment:=horizontal_alignment.Center
VerticalAlignment:=vertical_alignment.Center
return(MyCanvas,GoldTextBlock,ElimTextBlock,XPTextBlock,HackTextBlock)
一つずつ説明していきます。
コンマの自動挿入機能
数字が4桁以上になると、3桁ごとにコンマが入ります。
例:1000は「1,000」と表示されます。
SeparateNumberWithCommas(Number:int):string=
この行では、整数型(int型)の数字を引数として受け取り、それをNumberという変数に格納します。
var ConvertedString : string = "{Number}"
この行では、整数型(int型)のNumberを文字列型(string型)に変換し、ConvertedStringという変数に代入しています。たとえば、Numberが124の場合、「124」という文字列がConvertedStringに格納されます。
文字列に変換する理由は、数字の特定の位置にコンマを挿入する必要があるためです。文字列型では、文字の位置へのアクセスや操作が容易になるため、このような変換が有効です。
var ReturnString : string = ""
この行で、ReturnStringという変数を空の文字列("")で初期化しています。この変数を「空の箱」と考えてください。処理を進めるにつれて、この箱に数字やカンマを一つずつ追加していきます。すべての処理が完了した後、この箱に入った内容(整形された文字列)が最終的な出力として提供されます。
for(Index:=0..ConvertedString.Length-1):
このコード行では、forループを使用して、ConvertedStringに格納された文字列を最初(インデックス0)から最後の文字まで(ConvertedString.Length-1)一文字ずつ順番に処理しています。例えば、文字列が「12345」の場合、その長さは5ですが、コンピュータは0から数え始めるため、インデックスは0から4までとなります。ループ内で、Index変数はこれらのインデックスを順に取得し、ConvertedStringの各文字にアクセスします。
if(Mod[ConvertedString.Length-Index,3]= 0 and Index<>0):
set ReturnString = ReturnString + ","
この行では、文字列の後ろから3文字ごとにカンマを挿入しています。ただし、文字列の最初の位置(インデックス0)にはカンマを入れません。条件 Mod[ConvertedString.Length-Index,3] = 0 and Index<>0 が満たされる場合、カンマが追加されます。これにより、例えば「1234567」は「1,234,567」と表示されます。
if(Char:=ConvertedString[Index]):
set ReturnString = ReturnString + "{Char}"
このコード行では、ConvertedStringの各文字を確認し、空でない文字(Char)がある場合、それをReturnStringに追加しています。つまり、文字列内の各文字を順にReturnStringに組み込んでいきます。この処理はConvertedStringのすべての文字に対して行われます。
return ReturnString
ReturnStringを返します。
var UIStuffPerAgent:[agent]?tuple(canvas,text_block,text_block,text_block,text_block) = map{}
この行では、UIStuffPerAgentというマップ(辞書型のデータ構造)を定義しています。このマップは、ゲーム内の各プレイヤー(エージェント)に割り当てられるUI要素を管理します。具体的には、各エージェントに対して一つのキャンバスと四つのテキストブロックを格納するためのタプル(固定長のコンテナ)を保持します。この構造により、プログラムは各プレイヤーのUI情報を効率的に追跡し、更新できるようになります。
使用するデバイス
@editable RefreshRate : float = 0.5
@editable ConditButton : conditional_button_device = conditional_button_device{}
@editable ElimTracker : tracker_device = tracker_device{}
@editable XPTracker : tracker_device = tracker_device{}
@editable HackTracker : tracker_device = tracker_device{}
@editable PlayerSpawners : []player_spawner_device = array{}
使用するデバイス
1.トラッカー ※必須
2.条件付きボタン 任意
3.プレイヤースポナー 任意
ゲーム開始
OnBegin関数
for(PS:PlayerSpawners):
PS.SpawnedEvent.Subscribe(PlayerSpawned)
このコードは、ゲームマップ上の全プレイヤースポナーをループ処理し、それぞれにPlayerSpawned関数の購読を設定します。
これにより、新しいプレイヤーが生成される度に、"PlayerSpawned"関数が呼び出されます。
S2M<localizes>(S:string):message="{S}"
この関数"S2M"は、文字列Sを引数として受け取り、その文字列をメッセージ形式で返します。ウィジェットを画面に追加する際にこの関数を使用して、表示するテキストをローカライズ(地域化)の対象として準備します。これにより、ウィジェットに表示する内容を柔軟に管理できます。
PlayerSpawned関数
PlayerSpawned(Agent:agent):void=
#UIを持っているかどうかを確認する。
if(Stuff:=UIStuffPerAgent[Agent]?):
#持ってるから何もしない。
else:
#追加
AddUI(Agent)
この"PlayerSpawned"関数は、新たに生成されたプレイヤー(エージェント)ごとに実行されます。関数ではまず、そのプレイヤーが既にUIを持っているかどうかを確認します。
"UIStuffPerAgent[Agent]?"を用いてプレイヤーのUI情報がマップ内に存在するかをチェックし、すでに存在する場合は何もしません。UIがなければ、"AddUI(Agent)"を呼び出して新しいUIを追加します。これにより、すべてのプレイヤーが必要なUIを持つように保証されます。
AddUI関数
AddUI(Agent:agent):void=
if:
PlayerUI:=GetPlayerUI[player[Agent]]
then:
Stuff:=MakeCanvas()
Canvas:=Stuff(0)
GoldBlock:=Stuff(1)
ElimBlock:=Stuff(2)
XPBlock:=Stuff(3)
HackBlock:=Stuff(4)
PlayerUI.AddWidget(Canvas)
if(set UIStuffPerAgent[Agent] = option{Stuff}){}
spawn{LoopUpdate(Agent)}
AddUI関数は、指定されたエージェント(プレイヤー)にUIを追加するためのものです。
最初にプレイヤーのUI情報を取得し(GetPlayerUI)、その後、新たにキャンバスとテキストブロック(金額、排除数、経験値、ハック数を表示するブロック)を作成します(MakeCanvas)。
これらの要素をプレイヤーのUIに追加し、その情報をUIStuffPerAgentマップに登録します。このプロセスにより、プレイヤーのUIが適切に設定され、ゲーム中の状態変化に応じてUIが更新されるよう準備されます。最後に、UIの状態更新を周期的に行うLoopUpdate関数をスポーンします。これにより、プレイヤーのUIは常に最新の情報を反映するようになります。
LoopUpdate関数
LoopUpdate(Agent:agent)<suspends>:void=
loop:
Sleep(RefreshRate)
UpdateUI(Agent)
if(not UIStuffPerAgent[Agent]?):
return
LoopUpdate関数は、指定されたエージェント(プレイヤー)のUIを定期的に更新するために設計されています。この関数は無限ループ内で次の処理を繰り返します。
- 待機:Sleep関数を使用して、設定された更新レート(RefreshRate)だけ処理を一時停止します。これにより、UIの更新が一定間隔で行われます。
- UI更新:UpdateUI関数を呼び出して、エージェントのUIに最新の情報を表示します。
終了条件のチェック:UIStuffPerAgent[Agent]?を評価して、エージェントがまだUIを持っているかを確認します。もしUIが存在しない場合(プレイヤーがゲームから退出したなど)、ループを終了します。
この仕組みにより、プレイヤーのUIはゲームプレイ中常に最新の状態を保ち、プレイヤーの行動やゲームの進行に応じて適切に更新されます。
UpdateUI関数
UpdateUI(Agent:agent):void=
if(Stuff:=UIStuffPerAgent[Agent]?):
MyGold:=ConditButton.GetItemCount(Agent,0)
Stuff(1).SetText(S2M("${SeparateNumberWithCommas(MyGold)}"))
MyElims:=ElimTracker.GetValue(Agent)
Stuff(2).SetText(S2M("{SeparateNumberWithCommas(MyElims)} Elims"))
MyXP:=XPTracker.GetValue(Agent)
Stuff(3).SetText(S2M("{SeparateNumberWithCommas(MyXP)}"))
MyHack:=HackTracker.GetValue(Agent)
Stuff(4).SetText(S2M("{SeparateNumberWithCommas(MyHack)}"))
"UpdateUI"関数は、特定のエージェント(プレイヤー)のUI情報を更新します。
- UI情報の取得:UIStuffPerAgentマップから該当エージェントのUI情報をStuffとして取得します。
- ゴールドの更新:ConditButton.GetItemCountを使用してエージェントが持っているゴールドの数を取得し、カンマ区切りの形式に変換してUIに表示します。
- 撃破数の更新:ElimTrackerからエージェントの撃破数を取得し、同様にカンマ区切りでUIに表示します。
- 経験値の更新:XPTrackerからエージェントの経験値を取得し、更新します。
- ハック数の更新:HackTrackerを使用してエージェントが行ったハックの数を取得し、UIに表示します。
これらの更新により、エージェントのUIはゲーム内の実際の状態を正確に反映することができます。
RemoveUI関数
RemoveUI(Agent:agent):void=
if:
PlayerUI:=GetPlayerUI[player[Agent]]
Stuff:=UIStuffPerAgent[Agent]?
then:
#UIを消す。
PlayerUI.RemoveWidget(Stuff(0))
if(set UIStuffPerAgent[Agent] = false){}
1.プレイヤーのUI情報を取得
2.エージェントのUI情報を確認。UIStuffPerAgentマップからエージェントに関連付けられたUI情報をStuffとして確認します。
3.UIの削除。条件が真の場合(UI情報が存在する場合)、PlayerUI.RemoveWidgetを呼び出してStuffに含まれるウィジェットをUIから削除します。
4.マップの更新。削除が完了した後、UIStuffPerAgentマップ内の該当エージェントのエントリを無効にします(falseに設定)。
UI情報を作成
一度UEFNに戻って、ウィジェットブループリントを使って自分好みのUIデザインを作成してください。この時に設定した階層の内容を後にVerseで再現します。
Verseに戻ります。
MakeCanvas():tuple(canvas,text_block,text_block,text_block,text_block)=
GoldTextBlock:=text_block{DefaultText:=S2M(""),DefaultTextColor:=White,DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
GoldTextBlock.SetShadowOpacity(1.0)
ElimTextBlock:=text_block{DefaultText:=S2M(""),DefaultTextColor:=White,DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
ElimTextBlock.SetShadowOpacity(1.0)
XPTextBlock:=text_block{DefaultText:=S2M(""),DefaultTextColor:=White,DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
XPTextBlock.SetShadowOpacity(1.0)
HackTextBlock:=text_block{DefaultText:=S2M(""),DefaultTextColor:=White,DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=color{R:=1.0,G:=0.0,B:=0.934273}}
HackTextBlock.SetShadowOpacity(1.0)
このMakeCanvas関数は、ゲーム内UI用に一連のテキストブロックを作成し、それらを一つのキャンバスに組み込む役割を持っています。各テキストブロック(ゴールド、排除数、経験値、ハック数を表示するブロック)は以下の特徴を持っています:
・テキストの初期化:すべてのテキストブロックはS2M("")を使用して初期化され、これにより表示するテキストが空の状態から始まります。
・テキストの色と影の設定:テキストの色は白(White)で、影の設定はvector2{X:=2.5, Y:=2.5}で指定されたオフセットと黒(Black)での影の色を持ちます。
・影の透明度:各テキストブロックの影の透明度は1.0に設定されており、これによりテキストの視認性が向上します。
これらの設定により、テキストブロックはゲーム内で明瞭に表示され、プレイヤーの各種ステータスを効果的に表示することが可能です。
ウィジェットブループリントをVerseで再現
- canvasの基礎構造を作成
- GoldTextBlockのUI構造を作成
- 「GoldTextBlock」の設定をコピーし、排除数を表示するElimTextBlock用に適宜変更します。
- 経験値を表示するXPTextBlockも同様に、既存の設定をコピーし調整して作成します。
- 最後に、それら全てをreturnで返す。
MyCanvasの内容は、以前作成したウィジェットブループリントの階層を参考にします。
MyCanvas:= canvas:
Slots:=array:
#Canvas
canvas_slot:
Anchors:=anchors{Minimum:=vector2{X:=0.0,Y:=0.8},Maximum:=vector2{X:=0.0,Y:=0.8}}
Offsets:=margin{}
Alignment:=vector2{X:=0.0,Y:=1.0}
SizeToContent:=true
Widget:=stack_box:
Orientation:= orientation.Vertical
Slots:=array:
#GoldTextBlock
(省略)
return(MyCanvas,GoldTextBlock,ElimTextBlock,XPTextBlock,HackTextBlock)
まずは、canvasのベースを作成。
#GoldTextBlock
stack_box_slot:
HorizontalAlignment:=horizontal_alignment.Left
VerticalAlignment:=vertical_alignment.Fill
Widget:=overlay:
Slots:=array:
overlay_slot:
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Fill
Widget:=texture_block:
DefaultImage:=IMG.back_black2
DefaultDesiredSize:=vector2{X:=0.0,Y:=90.0}
overlay_slot:
Widget:=stack_box:
Orientation:=orientation.Horizontal
Slots:=array:
stack_box_slot:
Widget:=texture_block:
DefaultImage:=IMG.ai_robot2
DefaultDesiredSize:=vector2{X:=55.0,Y:=55.0}
stack_box_slot:
Widget:=GoldTextBlock
Padding:=margin{Left:=20.0}
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Center
Padding:=margin{Left:=30.0,Right:=30.0}
HorizontalAlignment:=horizontal_alignment.Center
VerticalAlignment:=vertical_alignment.Center
このコードは、ゲームUI内で「GoldTextBlock」と呼ばれるテキストブロックの配置を設定しています。具体的には、以下のステップで構成されています:
- 配置とサイズ設定
水平方向は左揃え、垂直方向は埋め尽くすように配置。
オーバーレイを使用して背景画像とテキストブロックを含む複数の要素を重ねます。
背景画像は IMG.back_black2 を指定し、サイズは横幅0.0、高さ90.0のベクトルで定義。 - テキストブロックの詳細設定
テキストブロックは水平方向に並べられ、左側にはアイコン(IMG.ai_robot2)、右側には実際のテキスト(GoldTextBlock)が配置。
テキストブロックの左側には20.0のパディングを設定し、中央揃えで配置。 - 同様のブロックの作成
この「GoldTextBlock」の設定をコピーして、「HackTextBlock」と「ElimTextBlock」を同じ方法で作成します。
必要に応じて各ブロックの背景画像やパディングをカスタマイズ。 - 組み立てと返却
最後に、これらのテキストブロックを含むキャンバス全体をreturn文で返却します。
UEFNで設定
UEFNに戻り、Verseデバイスを選択し、以下の画像のように設定します。
最後に、Trackerの進行状況を進めるための設定も行います。
以上です。
まとめ
Verseを用いてTrackerの情報をUI上で視覚的に表示する方法について詳しく解説しました。
この技術を活用することで、ゲーム開発者はプレイヤーに対して直感的でリアルタイムなフィードバックを提供できるようになり、プレイヤー体験を大幅に向上させることが可能です。また、この方法はTycoonなどの様々なゲームジャンルに応用可能で、多様なゲームデザインに役立つでしょう。
Discussion