Help us understand the problem. What is going on with this article?

[UE4] C++で動的にアクターを生成(スポーン)する方法で一番実用的だった方法

More than 1 year has passed since last update.

環境

  • OS:Ubuntu 16.04 LTS
  • UE4バージョン:4.22.1
  • エディタ:Visual Studio Code

はじめに

UE4でアクターを動的にスポーンする必要があったので調査・実装した。実装方法は複数見受けられたが、その中で一番実用的だと思ったものを紹介する。

結果(再生→アクタースポーン)
1.png
2.png

スポーン方法

一番実用的だった方法

さっそく、一番実用的だった方法を紹介する。

スポーンしたいアクターブループリントのパスを指定してクラスを取得し、そのクラスのアクターをスポーンする方法である。

  • アクターブループリントを作成しておく(今回は test という名前で作成)
  • アクターをスポーンするために利用する cpp ファイルに後述のコードを記述する
  • 上記処理をブループリントから呼び出す(今回はレベルブループリントの BeginPlay に記述した)
FString path = "/Game/test.test_C"; // /Content 以下のパスが /Game 以下のパスに置き換わり、コンテントブラウザーで名前が test なら test.test_C を指定する。
TSubclassOf<class AActor> sc = TSoftClassPtr<AActor>(FSoftObjectPath(*path)).LoadSynchronous(); // 上記で設定したパスに該当するクラスを取得
if (sc != nullptr)
{
    AActor* a = GetWorld()->SpawnActor<AActor>(sc); // スポーン処理
    a->SetActorLocation(FVector(-600, 200, 200)); // 確認しやすいように座標を設定
}

この方法は後述の方法と比べ、以下が優れていると感じた。

  • アクターブループリントのパスを変数とすれば任意のアクターを動的生成できる
  • 記述、振る舞いともにシンプル

その他のスポーン方法①

スポーンしたいアクターブループリントのパスを指定してブループリントを取得し、そのブループリントのクラスのアクターをスポーンする方法。

  • cppに記述する内容を下記のものに変更する
FString path = "/Game/test.test"; // この方法のときは、パスの末尾に _C を付与しない
UBlueprint* bp = FindObject<UBlueprint>(NULL, *path); // 上記で設定したパスに該当するブループリントを見つける
if (bp != nullptr)
{
    AActor* a = GetWorld()->SpawnActor(bp->GeneratedClass); // スポーン処理
    a->SetActorLocation(FVector(-600,200,200)); // 確認しやすいように座標を設定
}

※ この方法ではアクターブループリントが読み込まれていないときに実行してもアクターがスポーンされないため、一度対象のアクターをクリックするか、アセットを再ロードするか、ワールドに配置しておく等で読み込まれている状態にしておく必要がある

再ロードの例
4.png

上記の※で記した内容がこの方法のデメリットである。

その他のスポーン方法②

コンストラクタで事前にスポーンしたいアクターブループリントのクラスを取得しておき、そのクラスのアクターをスポーンする方法。

  • 処理を記載するcppクラスのヘッダファイルにクラスのメンバ変数として以下のコードを記述する
// クラスのメンバ変数として以下を記述する
TSubclassOf< class AActor > sc = nullptr;
  • 該当クラスのコンストラクタに以下のコードを記述する
FString path = "/Game/test.test_C";
static ConstructorHelpers::FObjectFinder< UClass > found(*path); // 上記で設定したパスのオブジェクトを取得する
sc = found.Object; // 上記で発見したオブジェクトのクラスを取得する
  • cppに以下のスポーン処理のコードを記述する
if (sc != nullptr)
{
    AActor* a = GetWorld()->SpawnActor<AActor>(sc); // スポーン処理
    a->SetActorLocation(FVector(-600,200,200)); // 確認しやすいように座標を設定
}

この方法のデメリットは、記述箇所が複数に渡るのと、コンストラクタに引数をつけることが若干手間であるのと、コンストラクタ内に処理を記載しなければならないため不便であることである。

その他

上記の方法以外にも、アクター自体をC++で記述してスポーンする方法もあった。アクターのスポーン自体は非常に簡単な記述になるが、アクターに様々なスタティックメッシュコンポーネントやマテリアルを設定するときにコードで記述すると見た目の調整が難しいことが課題であった。

まとめ

繰り返しになってしまうが、最初に紹介した手法が以下の点で優れているため、アクターをスポーンするときの参考にしてほしい。

  • アクターブループリントのパスを変数とすれば任意のアクターを動的生成できる
  • 記述、振る舞いともにシンプル

最後に

ヒトやモノをデータ化&解析してみたい、という方。
3D技術と深層学習を組み合わせて、何か面白いサービスを作ってみたい!、という方。

弊社では一緒に働いてくれる仲間を大募集しています。

ご興味がある方は下記リンクから是非ご応募ください!
https://about.sapeet.com/recruit/

参考

アクタのスポーン
Unreal Engine Spawn Blueprint Actors with C++
UE4: C++ コード から C++ クラスまたは Blueprint のアクターを FindObject して SpawnActor する方法

Kuroyanagi96
SapeetのDepth使い。スキャナー開発のための、マルチカメラ解析、ポイントクラウド処理に従事する。C++、Javaと仲良し。ボルダリングやトレッキング程度の登山をする。 https://about.sapeet.com/
https://about.sapeet.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした