DiabloライクのTop-DownViewカメラを作る
Twitterでサンプルを公開したところ、反響が多かったため、Top-DownViewカメラの作り方を紹介します。 今回の完成映像はこちらになります。

UEFNで俯瞰視点のゲームを作るためにトップダウンカメラを作ってみます。
実装方法
簡単な実装方法は以下の流れになります。
俯瞰カメラを作成し、LevelSequenceでゲーム開始時にそのカメラに切り替わるようにする
Verseで現状動かせるオブジェクトはCreativePropになるので、俯瞰カメラをCreativePropの子供にする
プレイヤーの位置をみて、CreativePropを移動させる
シーン準備
カメラの親となるCreativePropを一つシーン上に配置します。FortniteのPropsの下のものを配置してもいいですが、今回は独自にPropを準備しました。
このページに従い、破壊されない小道具(Indestructible Prop)を作成します。 この際、メッシュは特に使用する必要はないため、空にしておきます。

次に、カメラをシーン上に作成します。
先ほど作成したPropもシーン上に配置し、カメラをPropの子供にします。
カメラの座標値はすべて0に、角度は下向きにしておきます。

次に、LevelSequenceを作成し、先ほど作成したカメラをこのトラックに追加します。

シーン上にCinematic Sequence Deviceを配置します。

- Sequecneに先ほど作成したレベルシーケンスをセット
- LoopPlayback,AutoPlayをONにします。
これで基本準備は完了です。
Verse コード
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Characters }
using { /UnrealEngine.com/Temporary/SpatialMath }
# A Verse-authored creative device that can be placed in a level
track_player_manager := class(creative_device):
@editable
_Target : creative_prop = creative_prop{}
@editable
_OffsetX : float = -3000.0
@editable
_OffsetY : float = 0.0
@editable
_OffsetZ : float = 3000.0
OnBegin<override>()<suspends>:void=
Offset:vector3 = vector3{X:=_OffsetX, Y:=_OffsetY, Z:=_OffsetZ}
## start update loop
spawn{UpdateTargetPosition(Offset)}
UpdateTargetPosition(Offset:vector3)<suspends>:void=
loop:
## get player and player position
Players : []player = GetPlayspace().GetPlayers()
if(Player : player = Players[0]):
if(FortniteCharacter : fort_character = Player.GetFortCharacter[]):
PlayerPosition : vector3 = FortniteCharacter.GetTransform().Translation
TargetPositionX : float = PlayerPosition.X
TargetPositionY : float = PlayerPosition.Y
TargetPositionZ : float = PlayerPosition.Z
TargetPosition:vector3 = vector3{X:=TargetPositionX, Y:=TargetPositionY, Z:=TargetPositionZ} + Offset
## move target to player position
_Target.MoveTo(TargetPosition, IdentityRotation(), 0.5)
# Not Good
# if(_Target.TeleportTo[TargetPosition, IdentityRotation()]):
# void
Sleep(0.5)
# Not Good
# Sleep(0.0)
コード解説していきます。
OnBegin時に位置を更新するための非同期処理を開始しています。 このあたりの処理に関しては、alweiさんが非常に分かりやすく書いてくださっていたので、参考にされるといいと思います。
ここでプレイヤーと、プレイヤーの現在値を取得しています。
Players : []player = GetPlayspace().GetPlayers()
if(Player : player = Players[0]):
if(FortniteCharacter : fort_character = Player.GetFortCharacter[]):
PlayerPosition : vector3 = FortniteCharacter.GetTransform().Translation
その位置にオフセットをつけてpropのMoveTo関数で移動しています。
## move target to player position _Target.MoveTo(TargetPosition, IdentityRotation(), 0.5) # Not Good # if(_Target.TeleportTo[TargetPosition, IdentityRotation()]): # void Sleep(0.5) # Not Good # Sleep(0.0)
TeleportとSleep(0.0)の部分はコメントアウトしていますが、あえて残しています。 当初、これで実装してみたのですが、かなりガタガタしてしまい、あまりいい動きとなりませんでした。 0.5秒間隔でMoveToするくらがちょうどいい塩梅かなと感じています。
ちなみにSleep(0.0)にしたときに、どれくらいレートが出ているのか、計測するためのスクリプトを公開してくれている人がいました。 参考に貼っておきます。
最終シーンセットアップ
ビルドして出来上がったtrack_player_manager をシーン上に配置します。

- _Targetにカメラの親となっているPropをセット
- 適宜オフセットをセット
- Visible in Gameをオフにセット

まとめ
これで実行すれば、サンプルのようなプレイヤーに追従する俯瞰カメラが出来上がります。 問題として、Fortniteはそもそも俯瞰カメラに対応した操作になっていないため、プレイヤーをカメラ前方向に向けておかないと、カメラの向きとプレイヤーの操作が一致せず、非常に操作がやりにくい形になります。この辺りは少しゲーム内で工夫する必要があります。

次の記事で、カメラの向きと操作を一致させるようスクリプトを改修します。
今後もさまざまな情報を発信していきますので、Twitterフォローしていただけると嬉しいです。 twitter.com