【UE5】ボーンインデックスってどこで見れるの?【C++】

スケルタルメッシュやスケルトンの編集画面を開くと、ボーンの名前と階層構造は確認できるのですが、ボーンインデックスは確認できません。
見つからないので Editor Utility Widget(以下、EUW) でボーンインデックスビュワーを作りました。

動作環境
Unreal Engine 5.5 Preview, 5.5
Visual Studio 2022
Windows 11 Home

もくじ

EUW の見た目

スケルタルメッシュを選択すると、そのスケルタルメッシュが参照しているスケルトンのボーンインデックスとボーンの名前を表示するだけの EUW です。

ウィジェットの構成は以下の画像のようになっています。
※画像をタップまたはクリックすると拡大表示します。

赤枠内のウィジェット

スケルタルメッシュを選択する部分(上記画像の赤枠部分)は、過去の記事に掲載した Asset Selector Widget を使います。
詳しい内容は以下の記事をご確認ください。

青枠内のウィジェット

上記画像の青枠部分には Editor Utility Button を設置していますが、押しても何もしません。
複数のボタンを並べて、タブのように切り替えるつもりでボタンにしたのですが、結局使いませんでした。
なので、テキストでも問題ないです。

緑枠内のウィジェット

緑枠部分にボーンインデックスとボーン名を表示します。
ScrollBox の中に VerticalBox を配置して、リストビューのように使います。
リストビューは対応がめんどくさいので使ってません。

ボーンインデックスは3種類ある

ボーンインデックスと呼ばれるものは、以下の3種類あるようです。

  1. スケルトン用
  2. メッシュ用
  3. コンパクトポーズ用

ここではスケルトン用のボーンインデックスだけ必要なので、残りの2つには対応しません(取り方も不明)。

ボーン インデックスの解説 – UE 技術ブログ

スケルトン用ボーンインデックスを取得して返すコード
// Copyright dokuro.moe Rights Reserved.

// BoneIndexFunctions.h

#pragma once

#include "CoreMinimal.h"
#include "Runtime/Engine/Classes/Kismet/BlueprintFunctionLibrary.h"

#include "BoneIndexFunctions.generated.h"

USTRUCT(BlueprintType)
struct モジュール名_API FBoneIndexParams
{
	GENERATED_BODY()

	UPROPERTY(BlueprintReadWrite)
	int32 Index{-1};

	UPROPERTY(BlueprintReadWrite)
	FName Name;
};

UCLASS(BlueprintType)
class モジュール名_API UBoneIndexViewerFunctionLibrary
	: public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
public:
	UFUNCTION(BlueprintCallable)
	static TArray<FBoneIndexParams> GetSkeletonBoneIndices(USkeletalMesh* InSkeletalMesh);
};
// Copyright dokuro.moe Rights Reserved.

#include "BoneIndexFunctions.h"

//static
TArray<FBoneIndexParams> UBoneIndexViewerFunctionLibrary::GetSkeletonBoneIndices(USkeletalMesh* InSkeletalMesh)
{
	TArray<FBoneIndexParams> ParamsArray;

	if (!IsValid(InSkeletalMesh)) { return ParamsArray; }

	const FReferenceSkeleton& Skeleton = InSkeletalMesh->GetRefSkeleton();
	const int32 BoneNum = Skeleton.GetNum();
	ParamsArray.Reserve(BoneNum);

	for (int32 BoneIndex = 0; BoneIndex < BoneNum; BoneIndex++)
	{
		const FName BoneName = Skeleton.GetBoneName(BoneIndex);
		FBoneIndexParams Params;
		Params.Index = BoneIndex;
		Params.Name  = BoneName;
		ParamsArray.Add(Params);
	}

	return ParamsArray;
}
コードの説明

ブループリントでアクセスできるよう、親が UBlueprintFunctionLibrary のクラスに static な UFUNCTION を追加しています。
この関数は、スケルタルメッシュのポインタを渡すと、スケルトン用のボーンインデックスと、ボーンインデックスに対応するボーン名を構造体の配列(TArray)に格納して返してくれます。
スケルタルメッシュからスケルトンのボーン情報にアクセスするには、USkeletalMesh::GetRefSkeleton() を使います。

追加したコードをブループリントで使う


上図の赤枠で囲ったノード(Get Skeleton Bone Indices)が、前項のコードで追加した UFUNCTION です。
スケルタルメッシュのポインタを渡してあげるだけですが、スケルタルメッシュのポインタを取得するために、いくつかのプロセスが必要になります。

ブループリントの説明

こちらの記事で作成した AssetSelectorWidget を使って、プロジェクト内にあるスケルタルメッシュを選択すると、そのパスが Asset Path に入ります。

プラグインを使うのが面倒な場合は、スケルタルメッシュのパスを Load Asset に渡せばロードできます。
パスは、コンテンツブラウザでスケルタルメッシュのサムネイルを右クリックして「パッケージパスをコピー」で取得できます。

Asset Path を使って、Load Asset でスケルタルメッシュをメモリに読み込み、読み込んだデータのポインタを Cast To SkeletalMesh でキャストします。
SkeletalMesh にキャストしないと、Get Skeleton Bone Indices ノードに渡せません。
Get Skeleton Bone Indices ノードからボーン情報の配列を受け取ります。

その配列に対して For Each Loop で配列要素をひとつずつ処理して、ボーンインデックスとボーン名のリストを作成しています。

リストの作り方

ボーンインデックスとボーン名の一覧を表示する部分にリストビューは使っていません。
VerticalBox にリスト項目を追加するだけで済ませたかったので、Scroll Box の子に VerticalBox を設定しているだけです。

リストに表示する項目は別の EUW で作っています。

リスト項目のデザイン

リスト項目は別の EUW で作ります。
ウィジェットはこんな感じ。
※画像をタップまたはクリックすると拡大表示します。

リスト項目のブループリント


外部からウィジェットのテキストを変更したり、表示サイズを変更するブループリント関数をいくつか追加しています。
大したことはやっていないので、関数の中身は割愛します。

リスト項目の生成

元の EUW に戻ります。

※画像をタップまたはクリックすると拡大表示します。

上記は「追加したコードをブループリントで使う」で示した図です。
これには For Each Loop から先の処理が入っていませんが、その処理を以下に示します。

※画像をタップまたはクリックすると拡大表示します。

リスト項目の EUW を Create EUW … Widget ノードで生成したら(赤枠部分)、その EUW が持っているブループリント関数を使って、リスト項目に表示するテキストや表示サイズを設定し(緑枠部分)(「リスト項目のブループリント」で図示した関数群です)、最後に VerticalBox に AddChild (青枠部分)しています。

リストビューを使う場合は、親クラスは UObject にすればいいのか、UUserWidget にすればいいのかで迷ってネット検索して調べたり、インターフェースを登録しなきゃならなかったり、リストビューのエントリー周りの作り方や設定が面倒なので、ScrollBox と VerticalBox で対応しました。

興味がある方のみ以下のスポイラーをクリックして内容をご確認ください。

リストビューは不要?
Editor Utility Widget はエディタでしか使わないので、メモリ消費量を気にする必要がなく、このような大雑把な作り方ができますが、ゲーム中に表示するウィジェットの場合も同じような方法で実装するべきかどうかは色々と検証しないと分からないです。
仮に、ゲーム中ではリストビューの仕組みで作った方が軽いのであれば、リストビューを使うべきです。

「軽い」かどうかの判断は、処理が速いことを優先するのか、処理が遅くてもメモリに優しいことを優先するのか、どっちも優先せずバランスを取りたいのか、どっちをどれくらい優先したいか…というようにどのような実装を求められているかで変わります。
フレームレート優先、クオリティ優先を設定できたり、ウルトラスペック設定、ハイスペック設定など、いくつかの段階に分けて設定できるゲームがあるように、ゲーム設定によって切り替える場合もあります。

EUW と比べて、ゲームで使うウィジェットは色々と気にする所が多いです。

リストビューの作り方の参考になる記事

プラグインにしました。
MIT ライセンスです。

ダウンロードしたら BoneIndexViewer フォルダをプロジェクトの Plugins フォルダに放り込めば使えると思います。
README.md と LICENSE は動作確認には不要ですので、削除して構いません。
UE 5.5 Preview か UE 5.5 でないとビルドが通らないので気を付けてください。

Asset Selector Widget プラグイン の EUW とソースコードを流用しています。
AssetSelectorWidget プラグインを使っている場合は無効にしてから、このプラグインを導入してください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です