UE4/C++: USoundWave と USoundCue または何れにせよ USoundBase でいいやのメモ
UE4 プロジェクト内のアセット化された「なにか」を C++ コードの ctor で拾いたい場合には以下のようにする、するのだが…:
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
// どこかの UObject 系の ctor でプロジェクト内のアセットを引っ張り出す(間違い探しアリ😋) static ConstructorHelpers::FObjectFinder< USoundCue > my_sound ( TEXT( "SoundWave'/Game/BGMs/game_maoudamashii_3_theme01.game_maoudamashii_3_theme01'" ) );
この実装はコンパイル可能で my_sound
に対して特に何も実装を加えていなければうっかり見過ごしてしまうかもしれない。しかし、 UE4 のビルドシステムのログにはしっかりとエラーが報告されている。(少なくとも UE4Editor では reload に失敗するのでほぼ確実に気付くと思う。)
Error: CDO Constructor (MyExperimentalActor): Failed to find SoundWave'/Game/BGMs/game_maoudamashii_3_theme01.game_maoudamashii_3_theme01'
game_maoudamashii_3_theme01 はゲーム系フリー音楽素材の配信元としておなじみの 魔王魂 で入手できる。今回はこの .wav
が /Game/BGMs
に入っていなかった落ちではない。
今回の「間違い」は USoundCue
として .wav
アセットを探すコードになっている事。 .wav
アセットは UE4 的には USoundWave
なので:
// .wav を放り込んだだけの USoundWave アセットに対する正しい実装例 static ConstructorHelpers::FObjectFinder< USoundWave > my_sound ( TEXT( "SoundWave'/Game/BGMs/game_maoudamashii_3_theme01.game_maoudamashii_3_theme01'" ) );
と、しなければ期待動作しない。これが UE4Editor で放り込んだ .wav
のコンテキストメニューから Create Cue
するなどして USoundCue
化されたアセットを作ってあるのなら:
// USoundCue に対する正しい実装例 static ConstructorHelpers::FObjectFinder< USoundCue> my_sound ( TEXT( "SoundCue'/Game/BGMs/game_maoudamashii_3_theme01_Cue.game_maoudamashii_3_theme01_Cue'" ) );
となる。
なるのだが、実際問題この段階で USoundCue
か USoundWave
か何れであるかが問題になる事はたぶん無い。面倒だ・w・
そこで、とりあえず区別する必要の無い段階では USoundBase
を使っておけばよい。 USoundBase
は USoundCue
と USoundWave
の何れの基底型でもある:
// USoundCue でも USoundWave でも USoundBase にしておけばどっちでもいいのです static ConstructorHelpers::FObjectFinder< USoundBase > my_sound_a ( TEXT( "SoundWave'/Game/BGMs/game_maoudamashii_3_theme01.game_maoudamashii_3_theme01'" ) ); static ConstructorHelpers::FObjectFinder< USoundBase > my_sound_b ( TEXT( "SoundCue'/Game/BGMs/game_maoudamashii_3_theme01_Cue.game_maoudamashii_3_theme01_Cue'" ) );
こうして作った USoundBase
は「どちらでもいいや」のまま UAudioComponent::SetSound
のパラメーターとして与えられる。(そもそも SetSound
の第1引数は USoundBase
型。)
// どこかに適当な UAudioComponent が居るとして auto c = NewObject< UAudioComponent >( this ); c->SetSound( my_sound_a.Object );
USoundCue
と USoundWave
、こやつらの違いは必要な事があれば Cast
すればいいし、トリアエズナラスダケ!くらいな程度では USoundBase
で取り回していても不便ないしね☺