🎢

第22回UE5ぷちコン 技術的な振り返り② ~ジェットコースターの回転編~

2024/09/21に公開

この記事について

株式会社ヒストリア様主催の第22回UE5ぷちコンに参加した技術的な振り返りを記録したものです。

今回ははじめてXRミートアップ鹿児島のメンバーと一緒にチームを組んで参加してみました。

提出した作品

https://www.youtube.com/watch?v=L5rYlT0Atkk

ツイートまとめ

https://togetter.com/li/2431939

その他の技術的な振り返り記事

この記事で紹介するもの

ゲーム本編に登場するジェットコースターの回転・加速・減速する仕組みについて、作成手順を記録しておきます。
(こちら↓のツイートの2/2の方に出てくるもの)

https://x.com/xrm_kagoshima/status/1833105284186972588

設計

VR酔いの防止策

遥か昔VRChat初心者の頃 (今も初心者だけど)、VRでジェットコースターを体験できるワールドに連れて行ってもらいました。
その際に「このワールドでは、コースター側は静止したまま、周りの背景の方が動くことによって、ジェットコースターに乗っている気分を味わいつつ、VR酔いしにくいようになっているんだよ」ということを教えてもらいました。

果たしてこの仕組みが有効なのはVRChat限定なのか、他でも効くのかは詳しくないのでよくわかりませんが、なんとなくVRのジェットコースターはこう作るものという印象が残っているため、今回もこの設計にしました。

プレイヤー側は一切動かすことなく、背景側とプレイヤー以外のコースターを動かすことで、あたかも爽快感あるジェットコースターに乗ってる気分を味わいつつ、VR酔いを減らすという狙いになります。

複数人での作業

今回はチームを組んで制作を行いました。
そのため、各々の作業が競合しない(同じファイルに対して同時に変更を加えない)ようにして作業を進める必要がありました。

(余談ですが、チーム内でのファイル共有にはAzure DevOpsのGitを使いました。
5人までなら無料で使えて便利!)

https://www.docswell.com/s/abricheese/5R4VE5-2022-08-13-181950

ブループリントでの機能実装は私が、マップ上の背景にメッシュを配置するのは別のメンバーが担当したため、各々が触るマップをサブクラスに分けて、作業が競合しないようにしました。


背景用の「EnvironmentMap」とギミック用の「GimmickMap」をサブレベルとして作成。うっかり他のマップを触らないようにロックをかけておくとなお良し

プレイヤーの位置と見比べて、回転の中心にしたい位置にCubeを配置しておきました。
背景担当者には、このCubeに回転させたい背景用のメッシュをアタッチさせつつメッシュを並べてもらいました。

Cube側はゲーム内に見せない設定(Hidden in Game:True、コリジョン:No Collision、Cast shadow:オフにし忘れてた)にしつつ、ブループリントでCubeを回転させる仕組みを作りました。

Cubeを回転させるActor

マップ上に配置したCube(とCubeにアタッチされた背景用のメッシュたち)を回転させる処理を実装したActorについて解説します。

Cubeの取得

回転処理をするActor自身を回転させて、それに背景用のメッシュをアタッチしても良かったのですが、今回は作業優先度の都合上、先にMap上にとりあえずCubeを置いて背景を作ってもらってから回転処理を実装し始めました。そのため、回転体(Cube)と回転処理をするActorが別になっています。

回転処理をするActorにCubeの参照を持たせる変数「RotateTarget」を作り、「インスタンス編集可能」をオンにしました。
こうすることでマップ上に配置してあるCubeを割り当てることができるようになります。

Actorをマップに配置し、RotateTarget変数にCubeを割り当てました。

回転処理

続いて回転の処理をブループリントで実装します。
こちらはいたってシンプル。

回転の加減速

ゲームスタート時に徐々に回転を加速させ、終了時には徐々に減速させて停止させます。

いろいろやり方はありますが、今回はタイムラインを使用しました。
0~360の値をループして回転の角度を指定する回転用のタイムラインと、回転用タイムラインの速さ(Play Rate)を変化させる加減速用のタイムライン2個を作りました。

タイムラインの中身は下図の通りです。

値の調整はタイムライン内でやるよりも、タイムラインで出力される値に乗算する方が作業効率がいいです。
(今回だと上記画像のRotateSpeed変数をかけているところ。1秒の加減速でちょうどよかったため、今回は加減速のタイムラインのPlayRateは変更せず)

そのため、基本的にタイムラインは時間が0~1秒、値が0~1の間になるようにして、波形のみをタイムライン内で調整する派です。
(今回は回転のタイムラインのみは値が0度~360度であることが明確なので、初めから値を0~360の範囲で作りました。)


回転用のタイムライン(0, 0)→(1, 360)


加速用のタイムライン(0, 0)→(1, 1)


減速用のタイムライン(0, 1)→(1, 0)

加速の開始(ゲームの開始)と減速の開始(ゲームの終了)の管理はGameModeで行い、イベントディスパッチャーで各ブループリントに通知しています。
そのため、回転処理をするActorでもGameModeの通知にバインドして加減速の処理を呼び出しています。

これらの処理をBeginPlayで呼び出して、下記のような実装になりました。

おわりに

このような感じで、冒頭に紹介したジェットコースターの回転・加速・減速する(ように見せるための背景の回転処理)を作りました。
(こちら↓のツイートの2/2の方に出てくるもの)

https://x.com/xrm_kagoshima/status/1833105284186972588

加減速のタイムラインは直線じゃない方が良かったのかなとか、回転処理自体はタイムライン使わなくても良かったかなとか、今考えるといろいろ反省点もありますが、ぷちコン期間中の限られたリソースでそれっぽく動くものが作れたのでまあヨシ!()


皆様の応援が投稿のモチベーションになります。

記事が参考になりましたら、ぜひ♡ボタンを押したり、記事の拡散、X(Twitter)のフォローなどしていただけますと嬉しいです。

GitHubで編集を提案

Discussion