株式会社ヒストリアさん主催の第13回UE4ぷちコンの作業進捗。
昨夜ハマったネタの備忘録として。
ConstructionScript × GetSocketTransform
上は、コンストラクションスクリプト上で、ドラゴンの Head ボーンの World Transform を取得するノードグラフ。
Draw Debug Coordinate Cross は、ただ単に座標軸を書くためのもの。
UE4 標準の Draw Debug Coordinate System もよく使うが、マイナス軸の表示も欲しいときはこういうのを使っている。
この結果、エディタのビューポートに表示される絵はこうなる:
頭と全然違う位置に座標軸のデバッグ表示が出てしまっている。
ドラゴンの体を通るピンクのラインは、ビューポート内の Show メニューの Developer > Bones を ON にしたもの。
おおむね昨日一日、この問題で悶絶していた。
もともとは、頭(≒顎)に対する餌の位置を探していたので、逆行列の計算とかがアレコレ入っていて、掛け算の順番を間違ったか?とか、World Spaceじゃなくて、Component Spaceなのか?とか、そっちの方を必死に追いかけてしまっていた。
ふと、思い立って、Tickでもデバッグ表示してみたのがこちら:
あってんじゃん!
ボーン表示はコンソールコマンド
show Bones
ということで、今のところ、Construction Script で Get Socket Transform をすると、正しくない値が返ってくる可能性があるかもしれません。実行中の Get Socket Transform は正しい値を返します。(UE4.24.3)
例えば、グレイマンでは正しく出るのではないかとか、Get Socket Location ならどうなのか、など、他のシチュエーションでの追加調査をする余裕はないので、このまま放置します。すみません。(…ぷちコン締め切りまで1週間!)
ざっくり何をやったかだけ列挙すると:
- Construction Script での動作
- Skeletal Mesh Component (=ドラゴン) は、Yaw回転が-90度で、2倍のスケール
- Skeletal Mesh Component の Override Animation Data で、エディタ上で表示するアニメーションとフレーム番号を指定。
- 【追記】IsPlaying = True, PlayRate = 0.0 でも、IsPlaying = False, PlayRate = 1.0 でも、状況は変わらず。
- その後、Get Socket Transform で頭ボーンの Transform を取得
こういう流れでやっています。
AnimSequenceからフレームレートなどを取得する
Blueprintでは取得できない、アニメーションシーケンスの総フレーム数、フレームレートなどについて。
もう取れないものだとずっと諦めていたのだが、今更ながら、C++でサクっと取得できることに気づいた。
- UAnimSequence::GetNumberOfFrames(): 総フレーム数の取得
- UAnimSequenceBase::GetPlayLength(): 総再生時間(秒)の取得(Blueprint 版もある)
- UAnimSequence::GetFrameRate(): フレームレートの取得
C++ で Blueprint Function Library を作って、一気に便利に取得するようにした例:
void UMyBlueprintFunctionLibrary::GetAnimFrameInfo(UAnimSequence* InAnimSequence,
bool& OutSuccess, int& OutNumFrames, float& OutPlayLength, float& OutFrameRate)
{
if (!InAnimSequence)
{
UE_LOG(LogMyLibrary, Error, TEXT("GetAnimFrameInfo() InAnimSequence must not be a nullptr."));
OutSuccess = false;
return;
}
OutSuccess = true;
OutNumFrames = InAnimSequence->GetNumberOfFrames();
OutPlayLength = InAnimSequence->GetPlayLength();
OutFrameRate = InAnimSequence->GetFrameRate();
}
【注意】自作関数GetAnimFrameInfo()の第一引数の型がconst UAnimSequence*
ではなく、UAnimSequence*
なのは、GetPlayLength()
だけconst関数ではないため。(泣く泣く)
ついでに便利そうな関数も
後日談 (2020/05/01)
UAnimSequenceBase::GetTimeAtFrame() も UAnimSequence::GetFrameAtTime() も、WITH_EDITOR 関数だった。
パッケージビルドをするとビルドエラーが出る。
これらは、Editor 専用モジュールでしか使ってはいけない。
#if WITH_EDITOR
float UMyBlueprintFunctionLibrary::GetAnimTimeAtFrame(const UAnimSequence* InAnimSequence, int InFrame)
{
if (!InAnimSequence)
{
UE_LOG(LogMyLibrary, Error, TEXT("GetAnimTimeAtFrame() InAnimSequence must not be a nullptr."));
return 0.0f;
}
return InAnimSequence->GetTimeAtFrame(InFrame);
}
int UMyBlueprintFunctionLibrary::GetAnimFrameAtTime(const UAnimSequence* InAnimSequence, float InTime)
{
if (!InAnimSequence)
{
UE_LOG(LogMyLibrary, Error, TEXT("GetAnimFrameAtTime() InAnimSequence must not be a nullptr."));
return 0.0f;
}
return InAnimSequence->GetFrameAtTime(InTime);
}
#endif // WITH_EDITOR
こちらはconst UAnimSequence*
型で行ける。