VRM4U icon indicating copy to clipboard operation
VRM4U copied to clipboard

VRM4U_runtimeload マップでVRM読み込み後にエラーが出て動かせない

Open Udon-Tobira opened this issue 1 year ago • 10 comments

Describe the bug VRM4U_runtimeload マップを開き、エディターでゲームを開始。 開いたダイアログでvrmを選択して、開く。 すると、VRMは問題なく読み込めるが、T字のままでWASDで動かせない状態となり、ログを見ると、次のエラーが発生していました。

LogActorComponent: Error: May not destroy component ChildActorComponent /VRM4U/Maps/UEDPIE_0_VRM4U_runtimeload.VRM4U_runtimeload:PersistentLevel.VRMSamplePawn_C_0.ChildActor owned by VRMSamplePawn_C /VRM4U/Maps/UEDPIE_0_VRM4U_runtimeload.VRM4U_runtimeload:PersistentLevel.VRMSamplePawn_C_0.

Screenshots, log image

UnrealEngine Version: UE5.4.4

Additional context プロジェクトは、Blank テンプレートで作成し、VRM4Uプラグインのみを入れたクリーンなプロジェクトです。

Udon-Tobira avatar Sep 24 '24 08:09 Udon-Tobira

その状態で正しいです。ややこしいサンプルですみません。。そのうちに修正しておきます。

WASDで動かすためには iniファイルでのインプット設定が必要です。この設定はベースとなるプロジェクトファイルによって異なります。 またアニメーションを同梱していないため モデルはTポーズのままです。 アニメーションについては同レベルのリターゲットActorを参考にしてください。

ruyo avatar Oct 01 '24 00:10 ruyo

なるほど! 入力の設定入れたら動くようになりました。 ありがとうございます。

また別の問題があるのですが… この VRM4U_runtimelaod をゲーム起動時に開くように設定して、Development でパッケージングしたゲームを開き、VRMファイルを読み込むと、一部の VRM ファイルで以下のようなエラーが出てゲーム落ちます。(ちなみに Shipping でも同様にエラーになりますが、「Fatal Error!!」の表示に変わります)

Assertion failed: VertexBufferLocation == nullptr || VertexBufferLocation->GetResource() [File:D:\build\++UE5\Sync\Engine\Source\Runtime\D3D12RHI\Private\D3D12StateCache.cpp] [Line: 1479] 

Crash in runnable thread RHIThread

image

そのVRMファイルは、エディターでは問題なく開けてパッケージングしたゲームではエラー になります。 どの辺りに問題がありそうでしょうか?

Udon-Tobira avatar Oct 01 '24 10:10 Udon-Tobira

謎ですね… 手元では そのようなエラーを見たことはありません。 参考くらいにですが… BP_dropActor の中でランタイムロードのインポートオプションを指定している箇所があります。 MorphTarget, Material, Bone などを変更して ある程度要因を絞ることはできるかもしれません。 もしモデルを共有可能でしたら、こちらで調べることも可能です。

image

ruyo avatar Oct 01 '24 11:10 ruyo

実際にエラーが出て困っているモデルは送れないのですが、こちらでエラーが発生するテスト用のVRMファイルを作成しました。 TestVRM.zip これで検証していただけるとありがたいです。こちらのモデルは自由に使っていただいて構いません。

この検証用のVRMですが、100%エラーではなく、私の方では次の6パターンの状況が発生しました。

  1. 普通に読み込める image
  2. D3D12StateCache.cpp でのエラー image
    Assertion failed: VertexBufferLocation == nullptr || VertexBufferLocation->GetResource() [File:D:\build\++UE5\Sync\Engine\Source\Runtime\D3D12RHI\Private\D3D12StateCache.cpp] [Line: 1479] 
    
    Crash in runnable thread RHIThread
    
  3. アウトラインがつく image
  4. RHIResources.h でのエラー image
    Assertion failed: NumRefs >= 0 [File:D:\build\++UE5\Sync\Engine\Source\Runtime\RHI\Public\RHIResources.h] [Line: 143] 
    Reference count has underflowed.
    
  5. 「Fatal error!」 image
  6. 頭や右腕が無くなる image

これらの発生頻度ですが、1≒2 > 3 >> 4 > 5≒6 くらいの感じです。 VRM4U_runtimeload をデフォルトマップにして development でパッケージングし、Open VRM を押して読み込んでテストしています。

Udon-Tobira avatar Oct 06 '24 05:10 Udon-Tobira

詳細ありがとうございます! 頂いたモデルで、手元でも再現できました。 ひとまず インポートを同期モードにすれば読み込めるようです。DropActorに切り替えオプションを追加しました。 初期値は非同期モードなので、切り替えて試してみてください。

将来的には 非同期モードで正しく読めるよう修正します。

image

ruyo avatar Oct 06 '24 22:10 ruyo

素早いお返事、ありがとうございます! 確かに、同期読み込みでエラーなく読めるようになりましたので、ひとまずは解決しました。 ただ同期読み込みでも発生する事象(エラーではなく、見た目がおかしくなる系)が2つほどまた見つかりまして… そちらは今回の件とは別件っぽそうなので、別の Issue で送らせていただきますね。

Udon-Tobira avatar Oct 07 '24 00:10 Udon-Tobira

本件、(D3D12StateCache.cpp でのエラー)私の方でも発生しております。 VRMConverter::ConvertModel()内の処理が起因していると思われます。 この事象が発生する際に、Editor時は発生しませんが、パッケージ化した際に一部のモデルにおいて以下のlessの警告が複数回確認されております。 (VrmConvertModel.cpp内の1794行目)

if (f < VRM4U_MaxBoneWeight) {
	if (f <= (VRM4U_MaxBoneWeight - MAX_TOTAL_INFLUENCES)) {
		if (warnCount < 50) {
			UE_LOG(LogVRM4ULoader, Warning, TEXT("less"));
			warnCount++;
		}
	}
	w.InfluenceWeights[maxIndex] += (VRM4U_BONE_INFLUENCE_TYPE)(VRM4U_MaxBoneWeight - f);
}

根本的な原因としては以下のRendering Threadにおける処理の中で SkinWeightVertexBufferがNULLになるケースがあるのではないかと思われます。 (VrmConvertModel.cpp内の1863行目)

if (VRMConverter::IsImportMode() == false) {
	ENQUEUE_RENDER_COMMAND(UpdateCommand)(
		[sk, Triangles, Weight](FRHICommandListImmediate& RHICmdList)
	{
		... Rendering Threadにおける処理

恐らくこの箇所が原因だろうというところまでは調べることが出来たのですが 具体的な解決方法まではまだ掴めていないという状況です。

また、非Editor時のみWeidgetの値を書き換えている箇所がありました。 この処理も何かしら本件に関りがある可能性があるためメモとして残しておきます。 (VrmConvertModel.cpp内の1772行目)

#if WITH_EDITOR
#else
for (int i = 0; i < Options::Get().GetBoneWeightInfluenceNum(); ++i) {
	w.InfluenceWeights[i] = (VRM4U_BONE_INFLUENCE_TYPE)(((int)(w.InfluenceWeights[i] / 256)) * 256);
}
#endif

mameoPix avatar Nov 10 '24 07:11 mameoPix

原因判明しました。 SkinWeidgetのVertexBufferの更新漏れが原因と思われます。

以下の更新処理を追加することで修正が可能です。 (VrmConvertModel.cpp内の1924行目)

d.SkinWeightVertexBuffer = InWeights;
// 以下のSkinWeidgetVertexBufferの更新処理を追加
if (d.SkinWeightVertexBuffer.GetDataVertexBuffer() != nullptr)
{
	d.SkinWeightVertexBuffer.GetDataVertexBuffer()->UpdateRHI(RHICmdList);
}

mameoPix avatar Nov 10 '24 08:11 mameoPix

情報ありがとうございます!

手元で d.SkinWeightVertexBuffer.GetDataVertexBuffer()->UpdateRHI(RHICmdList); を追加して試してみました。 なんとなくクラッシュの頻度は下がった… ように感じますが、根本的には直ってなさそうな気配がします。 UE5.4にて、Developパッケージで モデルを何度かロードして試しています。 こちらでも 追って調査してみます。

ruyo avatar Nov 10 '24 13:11 ruyo

確認いただきありがとうございます!

あとはImmediateFlushを実行することで強制的にレンダリングコマンドをフラッシュする等でしょうか・・・ ただし、この処理は重くパフォーマンスに影響が出るのがネックですね。 (VrmConvertModel.cpp内の1945行目に追加)

#if	UE_VERSION_OLDER_THAN(4,25,0)
		d.SkinWeightVertexBuffer.UpdateRHI();
#else
#endif
		// 以下を追加してリソースの初期化/更新を即時反映
		RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread);
	});
}

こちらの環境の記載がなく申し訳ございません。 UE5.3 / VRM4U_5_3_20241007を使用して確認を行っておりました。

UE5.4以降はレンダリングの並列化とバインドレスレンダリングが導入された影響で、また挙動が異なる可能性が高いです。 https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-5.4-release-notes#rhi-renderparallelization https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-5.4-release-notes#rhi-bindlessrendering(experimental)

mameoPix avatar Nov 11 '24 09:11 mameoPix