Unreal EngineにおけるアクタをSplineの軌跡に沿って移動させる方法 ~後編~

 本投稿は,Unreal Engine(UE)におけるアクタに対し,Splineによって描いた軌跡に沿って移動させる方法に関する投稿です.そして前編と後編すべてを合わせたゴールとして,構造体型の配列で管理する複数のアクタをSpilneの軌跡に沿って移動させる方法を説明します.
  後編の内容は,前編で作成した環境にさらに手を加えてゆきます.BP_MoveCuveクラスに構造体型の配列を持たせ,それによって複数のアクタを管理しながら,Splineの軌跡に沿って移動させる方法です(図1).
 筆者自身における本投稿で一番のポイントは「アクタ型BPクラス内でさらにアクタ型変数を使用する際の扱い」です.筆者はここで数時間填まってしまいました.
  使用しているUEのバージョンは4.25.4です.

図1 後編の結果

目次

  1. 複数のアクタを構造体型の配列で移動させる仕組みの概念
  2. 実装手法

1. 複数のアクタを構造体型の配列で移動させる仕組みの概念

 この第1章では,次章で実際に実装してゆく仕組みの概念を説明します(図2).
 この後編で実装するものは,ST_Cube構造体と,ST_Cube構造体型を持たせるBP_MoveCubeの改変,さらに空のアクタ型BPクラスBP_Tempのみです.Splineに関するBP_Splineは前編のままです.

図2 本投稿で実装する仕組みの概念

2. 実装手法

 移動させる複数のアクタ用構造体「ST_Cube」の作成

 BP_MoveCubeに内包する事を目的としたST_Cube構造体を作成します.まずはコンテンツブラウザ上で右クリックし,「ブループリント>構造体」を選択し,作成した構造体の名前をST_Cubeとします.そして作成したST_Cubeに,図3のように変数を持たせます.
 デフォルト値において,speed変数においては前編と同じ理由で,ここでは例として100としておきます.

図3 ST_Cube構造体
表1 ST_Cube構造体の変数と内容
変数名

内容

cubeActor変数 Actor型のクラス変数.このST_Cube構造体型の配列をBP_MoveCubeで宣言した際に,実際に動かすアクタとなる変数です
moveDistance変数 float型のクラス変数.オブジェクトした際に,そのオブジェクトの移動量を表します(Spline上の始端のとき0となり,終端で最大値)
前編ではBP_MoveCubeでクラス変数として宣言していたものです
speed変数 float型のクラス変数.移動する速さを表します.本投稿ではプレイ中にspeedの値を更新する仕組みはないため,デフォルト値で0より大きな値を代入してください(0だと停止したまま移動しません.筆者は喩えとして100にしました)
前編ではBP_MoveCubeでクラス変数として宣言していたものです
interval変数 複数のアクタを扱うため,各アクタが同一座標で重なって表示されないよう,アクタ間の間隔として使用する変数です

 移動させるアクタ用クラス「BP_MoveCube」の改変

 後編となる本投稿でも,Splineの軌跡に沿って動かすアクタの制御このBP_MoveCUbeクラスで行います.まずは BP_MoveCUbeクラスのクラス変数を改変します(図4).
 前編では宣言していたがこの後編では不要であり削除する変数やコンポーネントがあります.コンポーネントのStaticMesh,moveDistance変数,speed変数を削除します.これに相当するものとして,後編ではそれぞれST_Cube構造体で宣言しています(図3).

図4 BP_MoveCubeクラスのクラス変数
表2 BP_MoveCubeクラスのクラス変数と内容
変数名 内容
spline変数 BP_Spline型のクラス変数.「マイブループリント」タブ上で目のマークをONにし,パブリック変数化します
cubesArray変数 ST_Cube構造体型の配列.これにより,1つの要素にTransformやメッシュ,移動距離,速さ等を格納できる配列となり,複数の移動するアクタを管理できます
cubes変数 integer型のクラス変数.Splineの軌跡に沿って移動させるアクタの数を表します.BP_MoveCubeをレベル上にドラッグ&ドロップしてオブジェクト化したあと,詳細タブからでも個数を設定できた方が楽なので,パブリック化しています
currentIndex変数 integer型のクラス変数.複数のアクタを配列で管理するため,ループ処理中に特定の要素にアクセスする際に使用します

 これからBP_MoveCubeクラスのブループリントを組んでゆきます.前編では「イベントTick」ノードによる,毎フレーム実行される処理のみでしたが,この後編では,「イベントBeginPlay」ノードにて配列の宣言とオブジェクト化を実行時に1度行います(図5).
 本投稿では,配列の長さを例として3にしています.そして図5中の処理の最後にてスタティックメッシュのコンポーネントと,実際にスタティックメッシュを持たせており,その際わざわざ図6のように3つのスタティックメッシュとマテリアルを用意しています.しかしこれはあくまで,本投稿用に視覚的に分かりやすくするために,配列の長さの分だけ異なるメッシュを用意しているにすぎません.そのため「Splineの軌跡に沿って複数のアクタを移動させる」だけならば,本投稿と同じようにわざわざ複数のメッシュを用意しなくとも大丈夫です.

図5 BP_MoveCubeクラスのイベントグラフ(イベントBeginPlay)
図6 CubesArrayの要素0番目から2番目に順に赤・緑・青の立方体のメッシュを割り当てプレイしている様子

 【余談】
半ば余談になりますが,図5における「オブジェクト化して配列に要素を追加」のコメントで括った部分にて,「SpawnActor」ノードをオブジェクト化しておく必要があったことに,筆者は気づけず数時間填まってしまいました.
  前編のように「アクタ型BPクラスをレベル上に配置してオブジェクト化し,そのオブジェクト自体にメッシュを持たせたりTransform(Location,Rotation,Scale)値を操作する」場合は,現に既にオブジェクト化されています.
 しかしこの後編では「BP_MoveCubeクラスをオブジェクト化しても,その中にあるST_Cube構造体型配列の要素がそれぞれ持っているアクタ型のCubeActor変数は,宣言されただけでオブジェクト化はされていない」状態です.
 そのため図5のように,予め「SpawnActor」ノードでオブジェクト化しておかないと, アクタ型のCubeActor変数のTansformに某かの値を代入したり,スタティックメッシュのコンポーネントを代入しても,結果として反映されません.

 さて,次に「イベントTick」ノードによる,毎フレーム実行される処理について記載します(図7).処理内容そのものは前編でやったいたことと同じ事しかしていません.前編で扱っていた各変数のノードをそれぞれ配列にそれに置き換え,配列の長さの分だけ繰り返すようにループ処理をかけているだけです.

図7 BP_MoveCubeクラスのイベントグラフ(イベントTick)

 最後に,BP_MoveCubeをレベル上にドラッグ&ドロップしてオブジェクト化すれば終了です.このBP_MoveCubeオブジェクトのLocationの値はいずれでもかまいません.配列で宣言されている各要素のCubeActorのオブジェクトのLocationは,プレイ中はSplineの軌跡上へと書き換えられるためです.