目標マーカーは、多くのゲームでプレイヤーを次の目標や注視点にガイドするために使用されます。 このチュートリアルでは、マップ インジケーターの仕掛けと Verse を使用して、再利用可能な目標マーカーを作成する方法について説明します。
使用する Verse 言語機能
使用する Verse API
creative_prop API:
creative_propAPI は、小道具を動かすための手段を提供します。編集可能なプロパティ:迅速にテストするため、仕掛けの参照と変数値の更新の両方に複数のプロパティを使用します。
手順
次の手順に従って、複数の目標や注視点に移動できる、単一の目標マーカーの仕掛けの設定方法を確認します。 完全なスクリプトは、参照用としてこのガイドの末尾に記載されています。
レベルを設定する
この例では、次の小道具と仕掛けを使用しています。
建築小道具 × 1:マップ インジケーターの仕掛けを移動するために使用される小道具です。
マップ インジケーターの仕掛け × 1:ミニマップおよび概要マップにカスタム仕様のマーカーを表示する仕掛けです。
プレイヤー スポーン パッドの仕掛け × 1:これを小道具の近くに追加することで、近くでプレイヤーがスポーンします。
Prop API を使用する
Verse を使用して仕掛けを移動するための最初のステップは、Prop API を使用して小道具を移動することです。 以下の手順に従って、レベルで小道具を移動します。
objective_coordinator_device という新しい Verse の仕掛けを作成します。
Verse ファイルの一番上のデフォルトの
using式の下に、SpatialMath モジュールのusing式を追加します。 このモジュールには小道具を動かすために参照するコードが含まれます。Verseusing { /UnrealEngine.com/Temporary/SpatialMath }2 つの編集可能なプロパティを追加します。
動く小道具への参照を格納する
RootPropという名前のcreative_propの定数。小道具の移動先の場所を格納する
Destinationという名前のtransformの定数。Verseobjective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} @editable Destination<public> : transform = transform{}
このコードを実行し、objective_coordinator_device をレベル内にドラッグすると、2 つのプロパティが [Details (詳細)] パネルに表示されます。
小道具を実際に移動させるのは
TeleportTo[]メソッドです。TeleportTo[]は失敗する可能性がある式であるため、それを if 式 内で呼び出して、丸括弧ではなく角括弧を使用します。ifは、失敗コンテキストを作成します。Verseif(RootProp.TeleportTo[Destination.Translation, Destination.Rotation]): Print("Prop move successful") else: Print("Prop move failed")TeleportTo[]の引数は、Translation および Rotation です。 これらはどちらも Destination プロパティに由来するものです。エディタに戻り、コンテンツ ブラウザで [Fortnite (フォートナイト)] > [Galleries (ギャラリー)] > [Props (小道具)] から小道具をドラッグします。 このガイドで使用しているのは Coastal Buoy 02B という名前のものですが、「Props」フォルダのものであればどれでも構いません。
[Outliner (アウトライナー)] で目標コーディネーターの仕掛けを選択します。 [Details (詳細)] パネルで、小道具に RootProp を設定します。 この例では、RootProp は Coastal Buoy 02B に設定されています。
[Details] パネルで、[Destination (目的地)] を展開します。 [Destination] は、
transform型であるため、[Scale (スケール)]、[Rotation (向き)]、および [Translation (トランスレーション)] で構成されます。 [Translation] を変更するだけでこの小道具を移動できるため、これを展開します。 X が 5000.0 で終了するようにフィールドを設定します。コードのテスト時は、効果をわかりやすくするため、値を大きく変更すると良いでしょう。 小さい変更では、コードが期待する処理を行っているか判断するのが難しくなります。
Verseusing { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /UnrealEngine.com/Temporary/SpatialMath } objective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} # Where the marker will be moved to[Verse] をクリックして [Build Verse Code (Verse コードをビルド)] を選択し、[Launch Session (セッションを起動)] をクリックします。 最後に、[Start Game (ゲームを開始)] をクリックします。 小道具が移動するのを確認できるはずです。
親と構造体
これで、小道具はレベル内で移動するようになりましたが、本当の目標はマップ インジケーターの仕掛けを移動してプレイヤーがウェイポイントとして使用できるようにすることです。 以下の手順に従って、建築小道具およびマップ インジケーターの仕掛けをレベルに追加し、その仕掛けを建築小道具にアタッチします。
コンテンツ ブラウザ内を右クリックしてコンテキスト メニューを開きます。
コンテキスト メニューから [Blueprint Class (ブループリント クラス)] を選択します。
[Pick Parent Class (親クラスを選択)] ウィンドウで、[Building Prop (建築小道具)] をクリックします。
コンテンツ ブラウザに新しいブループリント クラスが表示されます。 その名前を「BuildingProp」に変更します。
建築小道具をレベル内にドラッグします。 この小道具にはメッシュがないため、トランスフォーム ギズモのみが表示されます。
アウトライナー内で Map Indicator Device (マップ インジケーターの仕掛け) を BuildingProp にドラッグします。 これにより、BuildingProp が Map Indicator Device の親になります。 これで、BuildingProp が移動すると、Map Indicator Device も一緒に移動するようになりました。
Verse を使用して仕掛けを作成する方法については説明しましたが、独自の仕掛けを持たない Verse ファイルを作成することもできます。
新しい Verse ファイルを作成し、名前を「objective_marker」とします。 このファイルは仕掛けを作成しません。 代わりに、前に作成した Verse の仕掛けに公開される
structの定義を含んでいます。まず、objective_marker という
structを宣言します。 これには、RootPropとMapIndicatorという 2 つのメンバーがあります。 これらの両方に@editable指定子が必要です。Verseobjective_marker<public> := struct<concrete>: @editable RootProp<public> : creative_prop = creative_prop{} @editable MapIndicator<public> : map_indicator_device = map_indicator_device{}
拡張メソッドと名前付き引数
単一のメソッドである MoveMarker を宣言します。これは、RootProp メンバーとそれにアタッチされたマップ インジケーターの仕掛けを移動します。 このメソッドは、拡張メソッドと名前付き引数という 2 つの言語の機能を導入します。
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =拡張メソッド:
MoveMarker()メソッドをobjective_marker構造体に追加します。 拡張メソッドでは識別子と型をコロンで区切り、それらを括弧で囲んで宣言します。 この場合であれば、(Marker : objective_marker)となります。名前付き引数:2 番目の引数
?OverTimeは、?を使用することでMoveMarker関数呼び出しで名前を指定する必要があることを示します。 これにより、MoveMarkerへの呼び出しを参照したり記述したりするデベロッパーにとって、float引数が行う処理が理解しやすくなります。
MoveMarker() は、先ほど使用した TeleportTo[] または MoveTo() のいずれかのメソッドを Prop API から呼び出します。 if..else ブロックを作成し、パラメータ OverTime が 0.0 より大きいかをテストします。 大きい場合は、MoveTo() を呼び出します。 これにより、すぐにテレポートするのではなく、指定した期間の経過後に目標が次の場所に移動します。
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =
if (OverTime > 0.0):
Marker.RootProp.MoveTo(Transform.Translation, Transform.Rotation, OverTime)
else:
if:
Marker.RootProp.TeleportTo[Transform.Translation, Transform.Rotation]このコードを現時点でコンパイルすると成功はしますが、コンテンツ ブラウザ内の「CreativeDevices」フォルダには新しい仕掛けが表示されません。 これは、objective_marker が struct であり、creative_device から継承されたクラスではないためです。
目標コーディネーターの仕掛けを更新する
新しいタイプの参照ができたため、今度は objective_coordinator_device を参照するように更新する必要があります。
RootPropプロパティを削除し、型がobjective_markerのPickupMarkerというプロパティで置き換えます。 これは、自分で作成した型です。MoveMarker()にはfloat型の引数が必要であるため、これをMoveTimeという名前の編集可能なプロパティとして作成します。TeleportTo[]への呼び出しを削除します。 代わりに、objective_markerのために作成したMoveMarker()メソッドを呼び出します。 これには、名前付き引数である?OverTimeが必要です。Verseobjective_coordinator_device<public> := class<concrete>(creative_device): @editable PickupMarker<public> : objective_marker = objective_marker{} # Where the marker will be moved to @editable Destination<public> : transform = transform{} # How much time the marker should take to reach its new location
このコードをコンパイルし、目標コーディネーターの仕掛けの詳細を確認します。 PickupMarker プロパティおよび MoveTime プロパティが表示されます。また、PickupMarker には RootProp および MapIndicator が含まれています。
[RootProp] フィールドを BuildingProp に、[MapIndicator] フィールドを Map Indicator Device に設定します。
コードをコンパイルし、[Launch Session] をクリックします。 ゲームが開始すると、少ししてからミニマップにマーカーが表示されます。
MoveTimeにさまざまな値 (0.0も含む) を設定してこのマーカーを試してみましょう。 さまざまなシナリオで、どのような動きが最適かを検討してください。
GetPlayers() と ActivateObjectivePulse()
プレイヤーが次の目標にたどり着けるように、手助けできる手段が用意されています。 これは目標パルスと呼ばれ、これが有効なときはプレイヤーからマップ インジケーターの仕掛けに向かって破線が表示されます。 以下の手順に従って、目標パルスを目標コーディネーターの仕掛けに追加します。
目標パルスを有効にするために必要なメソッドは ActivateObjectivePulse() で、これには agent 型の引数が 1 つ必要です。 まず、プレイヤーのキャラクターを表す agent のインスタンスを取得するメソッドの作成から始めましょう。
FindPlayer()という関数を<private>に設定して宣言し、戻り値はvoidにします。Self.GetPlayspace().GetPlayers()を使用し、レベル内のすべてのプレイヤーの配列を取得します。AllPlayersという変数にこの配列を格納します。VerseFindPlayer<private>() : void = AllPlayers := Self.GetPlayspace().GetPlayers()レベル内のプレイヤーが 1 人のみの場合にその参照を取得するには、最初の配列要素を独自の変数に割り当てます。 配列へのアクセスは失敗する可能性がある式であるため、
if式の中に配置します。Verseif (FirstPlayer := AllPlayers[0]):変数への
playerの割り当ては失敗する可能性があるため、コード内でプレイヤーを参照する際には、オプション型の変数を使用することもできます。 任意のプレイヤー変数?playerを宣言します。 他のメンバー変数とともに使用する必要があります。Verseobjective_coordinator_device<public> := class<concrete>(creative_device): var PlayerOpt<private> : ?player = false @editable PickupMarker<public> : objective_marker = objective_marker{} # Where the marker will be moved to @editable Destination<public> : transform = transform{}新しい変数を設定し、
Print()式を使用してelseブロックを作成し、プレイヤーが見つからない場合には通知を表示するようにします。 これで、FindPlayer()関数が完成しました。VerseFindPlayer<private>() : void = # Since this is a single player experience, the first player [0] # should be the only one available. AllPlayers := Self.GetPlayspace().GetPlayers() if (FirstPlayer := AllPlayers[0]): set PlayerOpt = option{FirstPlayer} Print("Player found")
OnBegin() 関数に戻り、次の 2 つの変更を加える必要があります。
FindPlayer()関数を呼び出します。VerseOnBegin<override>()<suspends> : void = FindPlayer()MoveMarker()の呼び出し後、別のif式を使用してオプションのプレイヤーの変数を新しい変数に設定し、それをPickupMarker.MapIndicator.ActivateObjectivePulse()の引数として渡します。Verseif (FoundPlayer := PlayerOpt?): PickupMarker.MapIndicator.ActivateObjectivePulse(FoundPlayer)
これでコードを実行すると、キャラクターからレベル内の目標マーカーの位置を指す目標パルスが表示されます。
完全なスクリプト
Objective_marker.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Fortnite.com/Devices/CreativeAnimation }
objective_marker<public> := struct<concrete>:
# The prop that will be moved
@editable
RootProp<public> : creative_prop = creative_prop{}
Objective_coordinator_device.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /Fortnite.com/Playspaces }
using { /UnrealEngine.com/Temporary/SpatialMath }
objective_coordinator_device<public> := class<concrete>(creative_device):
var PlayerOpt<private> : ?player = false
@editable
応用編
ここで記述した移動のコードはどの小道具に対しても有効です。 移動可能な小道具を仕掛けの親として作成すれば、その仕掛けは小道具とともに移動します。 他の小道具や仕掛けも移動させてみましょう。また、これらを利用したゲームが考えられないか検討しましょう。
次のステップ
このガイドに沿って集荷/配達ゲームを開発している場合は、次のステップとしてカウントダウン タイマー機能の作成方法を学習しましょう。