ACharacterクラスのスポーンができません

本文:
C++からブループリントのパス経由でACharacterクラスのスポーンができず困っています。
エラー内容としてはアクセス違反で強制終了しますが、スポーンしたアクターがNULLポインタになることが原因であることまでは突き止めました。
現状ACharacterクラスではなく、AActorやAPawnクラスならスポーンができています。
どなたかご教示いただけますでしょうか。

以下、ソースコード(+BP)とその説明


ソースコードのようにブループリントクラスが置いてある場所のパスを指定してロードし、そこからスポーンさせようとしています。aがACharacterクラスだとnullptrになってしまいます。
また、ブループリントクラスはACharacterクラスを継承した独自のEnemyCharacterクラスを継承して作成しています。コリジョンの問題かとも思ったのですが違いそうなので困っています。

Translation: Can anyone help?

Full Text:
I’m having trouble spawning ACharacter classes from C++ via Blueprint path.
As for the error content, it is forcibly terminated due to an access violation, but we found out that the cause is that the spawned actor becomes a NULL pointer.
Currently, AActor and APawn classes can spawn instead of ACharacter classes.
Can someone tell me?

Below is the source code (+BP) and its explanation.

Like the source code, I specify the path where the blueprint class is located, load it, and try to spawn it from there. If a is an ACharacter class, it will be nullptr.
Also, the Blueprint class inherits from its own EnemyCharacter class, which inherits from the ACharacter class. I thought it might be a collision problem, but it seems to be different, so I’m in trouble.

まず前提として、C++コード内に直接アセットパスを埋め込むのは非推奨である、ということをご理解ください

提示されている情報からは、 Charger_BP がACharacterを継承したクラスである、という確認が取れません
写っているのは Corpse_Spear_BP という別のBPのようです
まずは本当にACharacterを継承しているか確認してみてください

回答ありがとうございます。

まず前提として、C++コード内に直接アセットパスを埋め込むのは非推奨である 、ということをご理解ください

そうなんですね。最近趣味で始めたのであまり知識がありません。よろしければ参考までに推奨方法を教えていただけますでしょうか。(情報が載っているサイトでも)

提示されている情報からは、 Charger_BP がACharacterを継承したクラスである、という確認が取れません
写っているのは Corpse_Spear_BP という別のBPのようです
まずは本当にACharacterを継承しているか確認してみてください

載せている画像では確かに判別できませんでした、申し訳ございません。以下の画像でどうでしょうか。

新規ユーザのためメディアが1枚まで、という表記がでたのでぶら下げる形でブループリントの親クラスとして使っているEnemyCharacterのヘッダも載せておきます。

アセットパスをハードコードしてしまうと、UnrealEngineの参照管理のサポート(ロード、パッケージ等)を受けられなくなります
C++では設定せず、 UPROPERTY を通してBP側に参照の設定先を公開し、BP側で具体的なアセットを指定するのが良いでしょう

模範解答のスニペットが公開されているので参考にしてください

アセットパスをハードコードしてはいけない理由については、下記のスレッドが参考になるかと思います


手元で再現を試みていますが、提示されているコードでは事象は再現しませんでした
もう少し詳しい情報が必要です

類似事象としては、(0,0,0)付近がCollisionで埋められている場合に、Spawnが成功せず、結果nullになるケースが確認できました
これに該当する場合、回避するのであれば、Locationを確実に空いている場所に指定するか、SpawnInfoを使って SpawnCollisionHandlingOverrideAlwaysSpawn に設定する必要があります

1 Like

アセットパスをハードコードしてしまうと、UnrealEngineの参照管理のサポート(ロード、パッケージ等)を受けられなくなります
C++では設定せず、 UPROPERTY を通してBP側に参照の設定先を公開し、BP側で具体的なアセットを指定するのが良いでしょう

丁寧に教えてくださり、ありがとうございます。提示していただいたスレッドも参考にさせていただきます。

類似事象としては、(0,0,0)付近がCollisionで埋められている場合に、Spawnが成功せず、結果nullになるケースが確認できました
これに該当する場合、回避するのであれば、Locationを確実に空いている場所に指定するか、SpawnInfoを使って SpawnCollisionHandlingOverrideAlwaysSpawn に設定する必要があります

おそらくこれが原因っぽいです。確かにバトル画面では(0,0,0)に敵キャラを移すカメラアクターが存在していて、コリジョンで埋められています。また、敵キャラはスポーンさせた後に位置を変えようとしている(提示したコードの後に書かれている)ので、コリジョンがあると判断されてスポーンしないと推測できます。
また、SpawnCollisionHandlingOverrideAlwaysSpawn に以前したときに、敵とのエンカウント方法がシンボルエンカウント(接触したら画面遷移)で、ゲームを始めた時に毎回プレイヤーと敵のスポーン場所が同じでフィールド画面が表示されないという問題に遭遇してしまったため、Try to Adjust Location, Don't Spawn に設定しています。

ゲームシステムの話は余談になってしまいましたが、私もコリジョンの可能性を疑って、アクタをスポーンさせるときにLocationを指定してスポーンするように変えようと思ったのですが、上手く調べることができず断念してしまった記憶があります。よろしければ、そういった方法を教えていただけないでしょうか。(あるいはカメラの位置を変えたほうがいいのでしょうか?)

追記です

どうやらブループリントのキャラの設定(メッシュかカプセルコンポーネント)が悪いらしく、強制的にスポーンさせると体が地面に埋まっていました。
おそらくこっちが本当の原因かと思います。。。

ACharacterクラスにすると、自動的に追加されるカプセルコンポーネントが地面に埋まっていて動かせず、メッシュに合わせられないのですが、これはどのようにするのが正解なのでしょうか。参考までに画像を貼っておきます。

長文で申し訳ありません。

Try to Adjust Location, but Always Spawn であれば、Collisionの埋まりを回避しつつ、かつ必ずSpawnする、という状態になります

CharacterのSkeletalMeshは足元(≒root)をCapsuleの下端まで位置を下げるのが基本です
ThirdPersonTemplateの構成を参考にすると良いでしょう

シンボルエンカウントの場合、最初にシンボルがSpawnする位置は決まっている(Playerと同じ場所にSpawnすることはない)はずなので、まずはそちらから解決するほうが良いでしょう
いわゆるSpawnerのようなものを作るとよいかと思います
Spawnerを使わず一括で生成するにしても、PlayerStartのような、場所を指定するための専用のActorを用意し、そこから位置情報を取得するようにするほうが、レベルデザインをする上でも楽になるかと思います

CharacterのSkeletalMeshは足元(≒root)をCapsuleの下端まで位置を下げるのが基本です
ThirdPersonTemplateの構成を参考にすると良いでしょう

ありがとうございます、ThirdPesonと同じように設定して、Always Spawn にしたら無事スポーンしました!

シンボルエンカウントの場合、最初にシンボルがSpawnする位置は決まっている(Playerと同じ場所にSpawnすることはない)はずなので、まずはそちらから解決するほうが良いでしょう
いわゆるSpawnerのようなものを作るとよいかと思います
Spawnerを使わず一括で生成するにしても、PlayerStartのような、場所を指定するための専用のActorを用意し、そこから位置情報を取得するようにするほうが、レベルデザインをする上でも楽になるかと思います

なるほど。ご指摘ありがとうございます。Player Startをそのままレベルにおいているので、そこから位置情報を取得するようにします。
長々とお付き合いいただきありがとうございました。大変助かりました。