カウントダウン タイマーを実行するタイマーの仕掛けを使用することもできますが、完全に独自のものを Verse で作成することで、その動作を自分のニーズに合わせてカスタマイズすることができます。
このチュートリアルでは、Verse で独自のタイマーを作成する方法と、カウントダウンに時間を追加する際にコールアウトを使用する方法について説明します。 シンプルな作業から始めて、プロジェクトごとに改善を進めていきましょう。
使用する Verse 言語機能
block (ブロック):この例では、カウントダウン タイマーが作成された場合に UI を初期化するために
block式を使用しています。loop (ループ):
loop式は UI を更新し、カウントダウンがゼロになると終了します。spawn (スポーン):
spawn式は任意のコンテキストで非同期式を開始します。message (メッセージ):メッセージ タイプはテキストをローカライズできることを意味し、メッセージ変数の初期化に使用する文字列は、メッセージのデフォルトのテキストと言語です。
class (クラス):この例では、カウントダウンを管理、表示する Verse クラスを作成します。
constructor (コンストラクタ):コンストラクタは、関連付けられているクラスのインスタンスを作成する特別な関数です。
Access specifier (アクセス指定子):アクセス指定子を使用してコードのアクセス レベルを設定できます。
使用する Verse API
Sleep (スリープ):
Sleep()API を使用することにより、UI の更新間隔を選択できます。Event (イベント):Verse で独自のイベントを作成し、イベントの発生時にカスタム仕様の機能を追加できます。
Verse UI:プレイヤーとゲームに関する情報を表示するカスタム仕様のインゲーム UI を作成します。
手順
次の手順に従って、独自のカスタム仕様のタイマーの作成方法を学びます。 完全なスクリプトは、参照用としてこのガイドの末尾に記載されています。
レベルを設定する
この例では、次の小道具と仕掛けを使用しています。
ボタンの仕掛け × 1:プレイヤーが仕掛けとインタラクトすると、カウントダウンに時間が追加されます。
エンド ゲームの仕掛け × 1:カウントダウンが終了したとき、この仕掛けによりゲームが終了します。
次の手順に従ってレベルを設定します。
ボタンの仕掛けとエンド ゲームの仕掛けをレベルに追加します。
Verse Explorer で新しい Verse の仕掛けを作成して、「
countdown_timer_example」と名前を付けます。 手順については、「Verse を使用して独自の仕掛けを作成する」を参照してください。編集可能な参照を
countdown_timer_exampleのボタンの仕掛けに追加し、「AddMoreTimeButton」と名前を付けます。 手順については、「仕掛けのプロパティをカスタマイズする」を参照してください。Versecountdown_timer_example := class(creative_device): @editable AddMoreTimeButton : button_device = button_device{}エンド ゲームの仕掛けへの編集可能な参照を
countdown_timer_exampleに追加し、「EndGame」と名前を付けます。Versecountdown_timer_example := class(creative_device): @editable AddMoreTimeButton : button_device = button_device{} @editable EndGame : end_game_device = end_game_device{}Verse ファイルを保存して、UEFN のメインメニューの [Verse] > [Build Verse Code (Verse コードをビルド)] を選択して、レベルの仕掛けを更新することで、仕掛けの [Details (詳細)] パネルで変更を確認することができます。
カウントダウンを開始する
この例では、独自の UI を描画し、独自のカウントダウンを管理する Verse クラスを作成します。
カスタム仕様のカウントダウン タイマーを作成するには、次の手順に従います。
空白の Verse ファイルを作成して、「countdown_timer.verse」と名前を付けます。
ファイルの先頭に、次の Verse モジュールを追加します。
Verseusing { /UnrealEngine.com/Temporary/UI } using { /UnrealEngine.com/Temporary/SpatialMath } using { /Fortnite.com/UI } using { /Verse.org/Colors } using { /Verse.org/Simulation }クラスを作成して「
countdown_timer」と名前を付け、次の変数を追加します。0.0に初期化されている、「RemainingTime」という名前の Float 変数。Versevar RemainingTime : float = 0.0「
Canvas」という名前のキャンバス ウィジェット変数。Versevar Canvas : canvas = canvas{}デフォルトのテキストの色が白の、「
RemainingTimeWidget」という名前のテキスト ウィジェット。VerseRemainingTimeWidget : text_block = text_block{DefaultTextColor := NamedColors.White}整数パラメータを受け取り、
RemainingTimeで表される値を表示する「RemainingTimeText」という名前のメッセージを返す関数。VerseRemainingTimeText<localizes>(CurrentRemainingTime : int) : message = "{CurrentRemainingTime}"falseに初期化されている、「MaybePlayerUI」という名前の任意のプレイヤー UI。VerseMaybePlayerUI : ?player_ui = false
クラスは次のようになります。
Versecountdown_timer := class: MaybePlayerUI : ?player_ui = false var RemainingTime : float = 0.0 var Canvas : canvas = canvas{} RemainingTimeWidget : text_block = text_block{DefaultTextColor := NamedColors.White} RemainingTimeText<localizes>(CurrentRemainingTime : int) : message = "{CurrentRemainingTime}"block式を追加し、画面中央上部に時間が表示される UI を作成します。 クラス定義の block 式は、クラスがインスタンス化されたときにのみ実行されるため、このblock式で UI を一度作成することができます。Versecountdown_timer := class: block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors: Minimum := vector2{X := 0.5, Y := 0.05} Maximum := vector2{X := 0.5, Y := 0.05} Alignment := vector2{X := 0.5, Y := 0.0} Offsets := margin{Top := 0.0, Left := 0.0, Bottom := 0.0, Right := 0.0}UI を表示するための関数
StartCountdown()を追加します。VerseStartCountdown() : void = Print("Starting countdown") if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas)「countdown_timer_example.verse」内に、プレイヤー UI と初期のカウントダウン時間への参照のある
countdown_timerインスタンスを作成します。 ゲームが始まったらすぐにカウントダウンが表示されるように、OnBegin()でStartCountdown()を呼び出します。Verseusing { /Verse.org/Simulation } using { /Fortnite.com/Devices } countdown_timer_example := class(creative_device): @editable AddMoreTimeButton : button_device = button_device{} @editable EndGame : end_game_device = end_game_device{}この時点でプレイテストを行うと、カウントダウンの開始時に UI に残り時間が表示されないため、「countdown_timer.verse」内にUI で現在のカウントダウンの値を更新する「
UpdateUI()」という名前の関数を作成します。StartCountdown()でUpdateUI()を呼び出します。VerseStartCountdown() : void = Print("Starting countdown") if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) # Update the UI when we start the timer to see the initial RemainingTime on screen UpdateUI() UpdateUI() : void =これで初期のカウントダウンが UI に表示されますが、値は毎秒ごとに更新されません。 そうするには、次の手順を実行します。
UI の更新頻度を秒単位で表す Float 変数
TimerTickPeriodを追加します。 この例では、1 秒にしています。VerseTimerTickPeriod : float = 1.0 # The timer "precision": how often, in seconds, it ticks.suspends 指定子を持つ関数を作成して「
RunCountdown()」と名前を付け、これをStartCountdown()から呼び出します。 UI を更新する前にRunCountdown()にTimerTickPeriodの間待機させ、ループでこれを繰り返します。 ループの終了を設定して、カウントダウンが0.0になった際に、カウントダウンが UI から消えるようにします。VerseStartCountdown() : void = Print("Starting countdown") if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) # Update the UI when we start the timer to see the initial RemainingTime on screen UpdateUI() spawn:
プレイテストを行うと、カウントダウンが 30 から開始し、タイマーが 0 になるまで毎秒更新されて、その後カウントダウンが UI から消えます。
さらに時間を追加する
このカウントダウン タイマーにさらに時間を追加し、追加した時間をコールアウトとして表示するカスタム仕様の方法を追加したいと思います。 この例では、カウントダウンにさらに時間を追加する方法と、プレイヤーがボタンの仕掛けとやり取りした際に、追加時間を表示する方法を示します。
次の手順に従って、プレイヤーがボタンの仕掛けとインタラクトしたときにカウントダウン タイマーにさらに時間を追加します。
「countdown_timer.verse」内に、「
AddRemainingTime()」という名前の新しい関数を作成します。この関数は、Timeという名前の float パラメータで関数に渡される値でRemainingTime変数を更新し、その後 UI を更新して新しい残り時間を表示します。VerseAddRemainingTime(Time : float) : void = set RemainingTime += Time # Immediately update the UI for better player feedback when time is added. UpdateUI()「countdown_timer_example.verse」内でボタンの仕掛けの
InteractedWithEventをサブスクライブし、プレイヤーがボタンの仕掛けとやり取りした際にAddRemainingTime()を呼び出します。Verseusing { /Verse.org/Simulation } using { /Fortnite.com/Devices } countdown_timer_example := class(creative_device): @editable AddMoreTimeButton : button_device = button_device{} @editable EndGame : end_game_device = end_game_device{}プレイヤーがボタンの仕掛けとやり取りした際に、カウントダウンにどれだけ時間が追加されるかをコールアウト (表示) するウィジェットを
countdown_timerクラスに追加します。VerseAddedTimeWidget : text_block = text_block{DefaultTextColor := NamedColors.White} AddedTimeText<localizes>(AddedTime : int) : message = " +{AddedTime}!"新しい AddedTimeWidget には RemainingTime ウィジェットと同じ配置値を使用しますが、次の値を変更してカウントダウン タイマーの右上に時間を表示します。
AddedTimeWidget では、[Offset (オフセット)] の [Left (左)] の余白を
50.0に設定します。RemainingTimeWidget では、[Offset (オフセット)] の [Top (上)] の余白を
25.0に設定します。Versecountdown_timer := class: <# This block runs for each instance of the countdown_timer class. We can setup the canvas once here. #> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors: Minimum := vector2{X := 0.5, Y := 0.05} Maximum := vector2{X := 0.5, Y := 0.05}
AddedTimeWidget の値を更新し、ウィジェットを再び非表示にする前にコールアウトを 2 秒間表示する「
AddedTimeCallout()」という名前の新しい関数を作成します。AddRemainingTime()でAddedTimeCallout()を呼び出します。VerseAddRemainingTime(Time : float) : void = set RemainingTime += Time # Immediately update the UI for better player feedback when time is added. UpdateUI() # Fire a simple callout to show the time being added. spawn: AddedTimeCallout(Time)プレイテストを行うと、カウントダウンが 30 から開始し、タイマーが 0 になるまで毎秒更新されて、その後カウントダウンが UI から消えます。 プレイヤーがボタンとやり取りすると、カウントダウンに 20 秒が追加され、追加された時間を示すコールアウトが 2 秒間表示されます。
カウントダウン タイマーの終了を知らせる
このチュートリアルでは、ボタンの仕掛けの InteractedWithEvent を使用して、プレイヤーがいつボタンを押したかを知り、カウントダウン タイマーにさらに時間を追加しました。 しかし、コードに何かが起こったときに、他のユーザーがそれを把握するために使用できるカスタム仕様のイベントを独自に作成することもできます。
この例では、カスタム仕様のイベントの次の動作を使用する方法を示しています。
Signal():この関数は、イベントを待っているものすべてに、イベントが発生したことを知らせます。Await():この非同期関数は、イベントが通知されるまで、この関数を含むコンテキストの実行をブロックします。
この例では、エンド ゲームの仕掛けを起動できるようにカウントダウンの終了したことを通知するイベントをカウントダウン タイマーに追加します。
次の手順に従って、カウントダウン終了のためのイベントを追加します。
countdown_timerクラスに「CountdownEndedEvent」という名前のイベント フィールドを追加します。VerseCountdownEndedEvent : event() = event(){}event()は parametric type (パラメトリック型) です。つまり、値やオブジェクト インスタンスではなくクラスやインターフェースを返します。 そのため、型はevent()で、クラスのインスタンス化を模倣するために定数CountdownEndedEventをevent(){}で初期化する必要があります。RunCountdown()を更新してCountdownEndedEventに通知し、ループから出る前に他のコードにカウントダウンが終了したことを知らせます。VerseRunCountdown()<suspends> : void = # We loop with the TimerTickPeriod. # The UI is also updated each time. loop: Sleep(TimerTickPeriod) set RemainingTime -= TimerTickPeriod UpdateUI() # Timer End if (RemainingTime <= 0.0):「countdown_timer_example.verse」で、
CountdownTimerに関連付けられているCountdownEndedEventを待ち、エンド ゲームの仕掛けを起動します。これは、イベント発生時にカウントダウンが終了することがわかっているためです。VerseOnBegin<override()<suspends> : void = AddMoreTimeButton.InteractedWithEvent.Subscribe(OnButtonInteractedWith) if: FirstPlayer := Self.GetPlayspace().GetPlayers()[0] PlayerUI := GetPlayerUI[player[FirstPlayer]] then: set CountdownTimer = countdown_timer{MaybePlayerUI := option{PlayerUI}, RemainingTime := InitialCountdownTime} CountdownTimer.StartCountdown() CountdownTimer.CountdownEndedEvent.Await()プレイテストを行うと、カウントダウンが 30 から開始し、タイマーが 0 になるまで毎秒更新されます。 カウントダウンが終了するとすぐにカウントダウンが UI から消え、ゲームは終了します。 プレイヤーがボタンとやり取りすると、カウントダウンに 20 秒が追加され、追加された時間を示すコールアウトが 2 秒間表示されます。
他のコードで使用できるようにクラスを準備する
これで独自のカスタム仕様のカウントダウン タイマー クラスを作成し、タイマーのインスタンス化と制御に Verse で作成した仕掛けを使用しました。
独自のカスタム クラスを作成する場合 (実際にはどのようなコードでもそうですが)、作成したものにアクセスできるものを指定することが重要です。 たとえば、カウントダウン タイマーだけがその UI の作成と変更を行えるようにするべきです。 Verse では、アクセス指定子を使用してコードのアクセス レベルを設定できます。
パブリックとは識別子がユニバーサルにアクセス可能であることを意味するため、他のものがアクセスできるようにしたい識別子に public 指定子を追加します。 この例では、countdown_timer_example の仕掛けに次のものがすべて使用されているため、これらにはパブリック アクセスが必要です。
CountdownEndedEvent<public> : event() = event(){}StartCountdown<public>() : void =AddRemainingTime<public>(Time : float) : void =
プライベートとは識別子が現在のスコープ、つまりこの識別子を囲んでいるスコープ (この場合、countdown_timer クラス) でのみアクセス可能であることを意味するため、他のものがアクセスできないようにしたい識別子に private 指定子を追加します。
この例では、次のものにプライベート アクセスが必要です。
RemainingTimeWidget<private> : text_block = text_block{DefaultTextColor := NamedColors.White}AddedTimeWidget<private> : text_block = text_block{DefaultTextColor := NamedColors.White}AddedTimeText<localizes><private>(AddedTime : int) : message = " +{AddedTime}!"RemainingTimeText<localizes><private>(CurrentRemainingTime : int) : message = "{CurrentRemainingTime}"var Canvas<private> : canvas = canvas{}TimerTickPeriod<private> : float = 1.0RunCountdown<private>()<suspends> : void =AddedTimeCallout<private>(Time : float)<suspends> : void =UpdateUI<private>() : void =
コードをアクセス権ごとにグループ化するのは良い方法です。 アクセス権の大きいものから小さいものへとコードを並べることを推奨します。
パブリック
内部
保護
プライベート
コンストラクタを使用すると、クラスの変数を公開することなく新しいクラス インスタンスの初期値を設定することができます。 コンストラクタは、関連付けられているクラスのインスタンスを作成する特別な関数です。
RemainingTime と MaybePlayerUI 変数を更新する countdown_timer クラスのためのコンストラクタを作成します。
MakeCountdownTimer<constructor><public>(MaxTime : float, InPlayer : agent) := countdown_timer:
RemainingTime := MaxTime
MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}
コンストラクタで設定された変数 RemainingTime と MaybePlayerUI は、パブリック アクセスを無効にするべきですが、コンストラクタで設定されている場合はプライベート アクセスを有効にできません。 これらの変数には internal 指定子を使用できます。これは、現在のモジュール、つまりこの識別子を囲んでいるモジュール内のみでこの識別子にアクセスできることを意味します。
MaybePlayerUI<internal> : ?player_ui = falsevar RemainingTime<internal> : float = 0.0
完全なコード
次のコードはカスタム仕様のカウントダウン タイマーを作成するための完全なコードです。
この例では次の 2 つの Verse ファイルを作成しました。
countdown_timer.verse
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/UI }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Simulation }
using { /Fortnite.com/UI }
MakeCountdownTimer<constructor><public>(MaxTime : float, InPlayer : agent) := countdown_timer:
RemainingTime := MaxTime
MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}
countdown_timer_example.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/UI }
countdown_timer_example := class(creative_device):
@editable
AddMoreTimeButton : button_device = button_device{}
@editable
応用編
このガイドを完了したことで、カスタム仕様のカウントダウン タイマーを作成する方法を習得できました。
このガイドで学習した知識を活用して、次の操作を実行してみましょう。
タイマーのティック レートを変更し、ティックごとにイベントを追加する。
タイマーにポーズ、再開、再スタートの機能を追加する。