質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unreal Engine

Unreal Engineは、Epic Games社によって開発されたゲームエンジンです。高レベルの移植性を持っており、様々なプラットフォームのゲーム開発が可能。GitHubアカウントを登録すれば無料でダウンロードできます。

インターフェース

インターフェイスという用語はハードウェア・ソフトウェアの両方に使うことができます。 一般的に、インターフェイスは内部処理の詳細を見せないように設定されます。オブジェクト指向プログラミングにおいて、インターフェイスはabstractクラスとして定義されます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

UE4

UE4はUnreal Engine(アンリアルエンジン)の第4世代です。 UEは、Epic Gamesより開発されたゲームエンジンです。

Q&A

解決済

1回答

2253閲覧

UE4 インターフェースを実装したBlueprintをスポーンさせたい

torano

総合スコア92

Unreal Engine

Unreal Engineは、Epic Games社によって開発されたゲームエンジンです。高レベルの移植性を持っており、様々なプラットフォームのゲーム開発が可能。GitHubアカウントを登録すれば無料でダウンロードできます。

インターフェース

インターフェイスという用語はハードウェア・ソフトウェアの両方に使うことができます。 一般的に、インターフェイスは内部処理の詳細を見せないように設定されます。オブジェクト指向プログラミングにおいて、インターフェイスはabstractクラスとして定義されます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

UE4

UE4はUnreal Engine(アンリアルエンジン)の第4世代です。 UEは、Epic Gamesより開発されたゲームエンジンです。

0グッド

0クリップ

投稿2020/05/23 09:34

編集2020/05/25 11:47

やりたいこと

C++で作成したインターフェースを実装したBlueprintをGameModeにいくつか渡し、スポーンしたい。

MMashiroさんから、GameModeからアクターをスポーンさせるのはレベルに紐づくのでよくないと指摘をいただきました。その通りだと思うのですが、今回は初心者用のチュートリアルの拡張ですので、GameModeをスポーンのための便利屋として使っていました。以下GameModeはただ単にスポーン用のアクターとお考え下さい。

試したこと & 問題

今まではアクターをそのままGameModeに渡しスポーンしていたのですが、いくつか異なるアクターをスポーンしたいと考え、以下のようにスポーンさせるアクターに実装させるインターフェースクラスをつくりました。

C++

1#include "CoreMinimal.h" 2#include "UObject/Interface.h" 3#include "SpawnableItemInterface.generated.h" 4 5// This class does not need to be modified. 6UINTERFACE(MinimalAPI, Blueprintable) 7class USpawnableItemInterface : public UInterface 8{ 9 GENERATED_BODY() 10}; 11 12/** 13 * 14 */ 15class BATTERYMAN_API ISpawnableItemInterface 16{ 17 GENERATED_BODY() 18 19 // Add interface functions to this class. This is the class that will be inherited to implement this interface. 20public: 21 UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "SpawnableItemInterface") 22 float GetSpawnRate(); 23 24 UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "SpawnableItemInterface") 25 void SetSpawnRate(float Rate); 26}; 27

GameModeにこれを実装したアクターBlueprint(新しくアクターBlueprintを作成しclass settingsのところから実装するインターフェースを選択しています。)をわたし、GetSpawnRate()でスポーンの頻度をそれぞれ変えつつスポーンするような感じです。しかし、ここで問題となったのが以下の点です。

  1. いくつかアクターBlueprintをつくりISpawnableItemInterfaceを実装したものの、どうやってGameModeに渡したらいいかわからない。
  2. ISpawnableItemInterfaceのスポーンの仕方がわからない。

1について

GameModeのC++クラスの.hで以下のように宣言し、エディターからアクターを渡したかったのですができませんでした。

C++

1 2 3 UPROPERTY(EditAnywhere) 4 TSubclassOf<ISpawnableItemInterface> ISpawnableItem;

エラーはでないものの、エディターの詳細欄から渡すことができません。
またGameModeのBlueprintから新しくSpawnableItemの変数を作成し、配列にして外部に公開し、アクターを渡そうと思ったのですがこれもできませんでした。

2について

仮に渡せたとしてもinterfaceを実装したアクターのスポーンの仕方がわからないです。
以下のようにしてもエラーがでてしまいます。

C++

1GetWorld()->SpawnActor(SpawnableItem, &SpawnPosition, &SpawnRotation);

そもそもインターフェースを実装させようと思ったのは、1)いくつも同じ機能をもつアクターをつくる 2) 上位クラスであるGameMode側を下位クラスのアクターに依存させたくない といった理由なのですが、インターフェースにしたせいでうまくいかなくなってしまいました。

一応一つの解決策としてはGameModeでTArray<AActor>をUPROPERYにして公開し、GameModeがそれらをイテレートしてISpawnableItemInterfaceかどうか確認する、というやり方があると思うのですが、これはエディター側からどのアクターでも設定できてしまうのでよくなさそうです。

UE4はじめたばかりで初歩的なことがわからないのですが、解決したいです。よろしくお願いします。

追記

MMashiroさんのアドバイスの元、修正したらExecute_GetSpawnRate()関数でクラッシュするように。以下どこでエラーが起きているか。

クラッシュ箇所

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MMashiro

2020/05/23 15:32 編集

GameModeの変数にアクターを入れようとしたとのことですが、これはレベル上に存在するアクターをGameModeに入れようとしたという事でしょうか? また入れようとしている画面はどこでしょうか?(どこの画面から変数を代入しようとしてましたか?) またGameModeはそのゲーム全般で使用・内容が維持されるものなので特定のレベルと紐づくような仕組みはあまり望ましくないです
torano

2020/05/24 01:34 編集

GameModeのBlueprintをコンテンツブラウザからダブルクリック、開いたところから新しくVariableを作成(ドラッグ&ドロップしてBlueprintのノードとして使えるようにするアレです。)、publicにして変数のTypeをSpawnableItemに変更しコンパイル、その変数の詳細欄の下から入れようとしてました。入れようとしているアクターはレベルに存在するアクターではなく、新たに作成しinterfaceを実装させたアクターBlueprintです。このBlueprintをレベルにスポーンしたいためにGameModeに入れたいのです。 勝手がまったくわからなかったので出来そうなことを全て試してみたのですが、Unrealを普段使っている方からは意味のわからないことだったかもしれません、すいません。 GameModeの使い方が間違っているという指摘はその通りだと思います。本当ならスポーン専用のSpawnerアクターのようなものをつくるべきなのでしょうか。ただ、今回は初心者用のチュートリアルプロジェクトを拡張していただけなのでGameModeを便利アクターとして使用してもそんな問題ないのかと思いGameModeを使っていました。回答者側からはわかりずらいと思うので修正しておきます。
guest

回答1

0

ベストアンサー

1に関して

こちらはMeta属性を使用することで実現可能ですただEventGraphからSetする場合は関係ないアクターも出てしまう等挙動は少し微妙です(詳細パネルから指定する分にはインターフェースを実装したもののみ一覧に出てくるようです)

UPROPERTY(EditAnywhere, BlueprintReadwrite, meta = (MustImplement = "SpawnableItemInterface")) TSubclassOf<AActor> SpawnItem;

2に関して

こちらはSpawn方法はあっており、上記方法で指定したActorをSpawnできることを確認しています。
SpawnPositionやSpawnRotationの定義や指定方法は正しいでしょうか?
エラー内容を提示していただければよりわかるかと思います。

投稿2020/05/24 09:52

MMashiro

総合スコア2378

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torano

2020/05/25 02:12

エラーは出てなかったです。ビルドは問題なくできるのですがスポーンができないです。 ``` UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (MustImplement = SpawnableItemInterface)) TArray<TSubclassOf<AActor>> SpawnableItems; ``` 配列としてほしかったので上記のように宣言、エディターで設定し、 ``` for (int i = 0; i < SpawnableItems.Num(); i++) { TSubclassOf<AActor>& Item = SpawnableItems[i]; /// スポーンするものを一つだけ選ぶ計算 省略 /// if (Item->GetClass()->ImplementsInterface(USpawnableItemInterface::StaticClass())) { GetWorld()->SpawnActor(Item, &SpawnPosition, &SpawnRotation); break; } } ``` このようにしたのですがうまくいかず。。。TArrayなしのTSubclassOf<AActor>の方も試してみたのですがインターフェースを実装しているかの確認部分、Item->GetClass()->ImplementsInterface(USpawnableItemInterface::StaticClass()がtrueにならないです。どのように解決すればいいでしょうか。
MMashiro

2020/05/25 08:00

エラーは出てなかったのですね。 ImplementsInterfaceですが、TSubclassOfで宣言した変数の中に入っているものは実体ではない為GetClassをする必要はありません Item->ImplementsInterface... で正常にtrueになると思われます
torano

2020/05/25 11:45

試してみたところ、クラッシュするようになってしまいました。デバッグしてみるとどうやら原因はinterfaceの関数であるExecute_GetSpawnRate()でクラッシュしているようです。Execute_GetSpawnRate()はスポーンするのに必要なのでItem->GetClass()->ImplementsInterface(USpawnableItemInterface::StaticClass())とSpawnActorの間に使用しています。 質問文の最後に追記としてのせますが、ブレークポイント張ってひとつひとつ追ってみたところSpawnableItemInterface.gen.cppに記述してあるExecute_GetSpawnRate()の内部で再度Item->GetClass()->ImplementsInterface(USpawnableItemInterface::StaticClass()を確認しているようで、そのせいでエラーが起きているようです。。。 よくわからないですが、おそらくSpawnActorしてからじゃないと実装した関数は使えない、ということでしょうか。スポーンするために使いたい関数なのにスポーンしてからじゃないと使えず、となっているのでどうすればいいのかわかりません。。。何か他の方法を探すか、そもそもの設計のほうを見直すしかないのでしょうか。 すいません、もう少しだけお助けおねがいします。
MMashiro

2020/05/25 15:24

GetSpawnRateを呼び出している箇所のコードが気になります。 スポーンするための関数をInterface側に定義するのは少し疑問が残ります。 コード上からは結局何がしたいのかがあまり見えてこない為的確なアドバイスは出来かねます。 ただそのInterfaceを実装したクラスの関数を呼ぶには実体は必要の為スポーンする必要があると思います (staticであればその限りではありませんが)
torano

2020/05/26 08:38

自己解決できました。 やっていたことは各SpawnableItemのGetSpawnRateでスポーン率(スポーンするレア度)を見て、ランダム数使ってスポーンする物を決定、その後スポーンです。 いろいろ自分で調べてみた結果スポーン前のアクターのデータをあらかじめ定義しておくならDataAssetを使うのがいいとわかったので、SpawnRateやらアクターやらを入れたDataAssetクラスと実際にデータをいれたDataAssetをいくつか作成し、それらをGameModeに渡しSpawnすることでうまくいきました。 いろいろ助けてくださりありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問