Nanite有効なStaticMeshのロード・アンロード時におけるSTAT_StaticMeshTotalMemoryの統計値不一致について

【概要】

Naniteが有効なStaticMeshにおいて、InitResourcesとReleaseResourcesで計算されるリソースサイズに乖離があるため、統計値(STAT_StaticMeshTotalMemory)が正しく減算されず、デバッグ表示上でメモリリークが発生しているように見える現象を確認しました。

調査の結果、Naniteリソースの一部が解放処理の過程で先に破棄またはサイズ変更されているために、GetResourceSizeBytes が返す値が確保時よりも小さくなっていることが原因と推測されます。

【再現環境】

UEバージョン: 5.7.3 (Source Build)

プラットフォーム: Windows Package (Developmentビルドで確認。EditorPIE実行、StandAlone実行では確認できませんでした。)

対象: Naniteサポートを有効化したStaticMeshが存在するレベルをロード・アンロード(調査環境ではOpenLevelでレベル遷移を行うだけで発生しました)

【調査内容】

StaticMesh.cpp の実装を確認したところ、以下の箇所で統計値の加減算が行われています。

確保時:UStaticMesh::InitResources()

GetResourceSizeBytes(EResourceSizeMode::Exclusive) で取得したサイズを INC_DWORD_STAT_BY で加算。

解放時:UStaticMesh::ReleaseResources()

同様に GetResourceSizeBytes(EResourceSizeMode::Exclusive) で取得したサイズを DEC_DWORD_STAT_BY で減算。

しかし、Nanite有効なメッシュで検証したところ、以下の通りサイズに差分が生じていました。(メッシュはどのメッシュでもNaniteサポートが有効になっている場合は同様に現象を確認できます。)

InitResources時:

TotalSize: 81,492 (Naniteリソース分: 33,488 / その他: 48,004)

ReleaseResources時:

TotalSize: 48,324 (Naniteリソース分: 320 / その他: 48,004)

非Nanite部分のサイズは一致していますが、Naniteリソース(RootData, PageStreamingStates等)のサイズが、ReleaseResources が呼ばれるタイミングでは既に大幅に減少あるいは一部破棄されています。

この結果、加算した値よりも少ない値が減算されるため、レベルのロード/アンロードを繰り返すたびに STAT_StaticMeshTotalMemory の値が累積し、統計上リークしているように見えてしまいます。

Naniteに関しては

NaniteResource.cpp

void FResources::SerializeInternal(FArchive& Ar, UObject* Owner, bool bCooked)

でStremablePagesにシリアライズされており、RenderThread側で処理されているのかと思われます。

​【検証ログ】

~初期化時
[2026.02.16-06.18.42:420][739]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[0]::UStaticMesh::Serialize
[2026.02.16-06.18.42:421][739]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[0]::UStaticMesh::SetRenderData
[2026.02.16-06.18.42:421][739]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[81492]::UStaticMesh::SetRenderData
[2026.02.16-06.18.42:421][739]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[81492]::UStaticMesh::UpdateStaticMaterialsInfoCache
~解放時
[2026.02.16-06.18.45:413][483]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[48324]::UStaticMesh::BeginDestroy
[2026.02.16-06.18.45:413][483]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[48324]::UStaticMesh::ReleaseResources
[2026.02.16-06.18.45:413][483]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[48324]::UStaticMesh::BeginDestroy
[2026.02.16-06.18.45:413][483]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[48324]::UStaticMesh::IsReadyForFinishDestroy

NaniteResourceSizeも表示したログは下記の通りでした。

[2026.02.16-08.28.03:942][714]LogStaticMesh: Warning: [Ptr:0000022855F35CE0]->NowSize[81492]->NaniteSize[33488]::UStaticMesh::InitResources
[2026.02.16-08.28.06:922][477]LogStaticMesh: Warning: [Ptr:0000022855F35CE0]->NowSize[48324]->NaniteSize[320]::UStaticMesh::ReleaseResources

Naniteのサイズ取得のログの出力は以下で行っております。

FResourceSizeEx ResSize = FResourceSizeEx(EResourceSizeMode::Exclusive);
GetResourceSizeEx(ResSize);
UE_LOG(LogTemp, Warning, TEXT("[Ptr:%p]->NaniteSize[%llu]::%s"), (const void*)this, ResSize.GetTotalMemoryBytes(), *FString(__FUNCTION__));

【質問】

・統計上の不一致か、メモリリークか

DEC_DWORD_STAT_BYに渡されるサイズが小さいため、Debug View上の StaticMeshTotalMemory は増加し続けます。これは単なる表示上のバグ(統計計算のタイミングの問題)でしょうか、それともNaniteリソースの実際の解放漏れが発生しているのでしょうか。

・Naniteのメモリ管理仕様:

Naniteリソースは StreamablePages 等を通じてGPU/レンダリスレッド側で管理されている認識でございますが、ReleaseResources時点でGetResourceSizeBytesが小さい値を返すのは意図された挙動でしょうか。

もし統計上の問題である場合、確保時のサイズを保持しておいて減算するような修正が適切でしょうか。あるいは、Naniteリソースのサイズ取得において推奨されるタイミングや手法があればご教授ください。

以上、よろしくお願いいたします。

[Attachment Removed]

お世話になっております。

本件詳細な調査を行っていただきありがとうございます。

こちらご提供いただいたパッケージにてStat Memoryを実行しメモリが増えてしまっている状況を確認し、またシンプルな類似のプロジェクトにおいても再現の方確認しております。

※追記

一度シンプルな環境で再現確認できていない報告をしておりましたが、こちらの検証環境にて対象MeshのNaniteが有効化されておりませんでした。大変失礼いたしました。

現状類似の報告は見つかっていない状況でして、引き続き調査に進展があり次第ご連絡させていただきます。

ご不便をおかけしますが、よろしくお願いいたします

[Attachment Removed]

お世話になっております。

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

> 現状類似の報告は見つかっていない状況でして、引き続き調査に進展があり次第ご連絡させていただきます。

承知いたしました。引き続きよろしくお願いいたします。

こちらでも継続して調査を行い、なにか進展がありましたら返信にて追記させていただきます。​

[Attachment Removed]

本件お時間を頂き申し訳ございません。

今回の問題についてですが、ご調査いただいていた通りNanite リソース側が適切にデクリメントできていない状態となっており、実際のメモリリークではなく統計上正しく計測ができていない見込みです。

※LLM 計測上では Nanite リソースに有意な増加は確認されておらず、その他 Nanite リソースに関するメモリリークの報告も現時点では確認できておりません。

本件は以下の不具合として報告させていただきました。

UE-367793 STAT_StaticMeshTotalMemory increases after repeated loading and unloading of a level containing Nanite static meshes

理想としては、リソースサイズの変更を検知し、そのタイミングで Stats を更新する実装が望ましいと考えておりますが、現状のワークアラウンドとしましては、取得時のサイズを保持し、解放処理時にその値を減算する対応となる見込みです。

ご不便をおかけしますが、よろしくお願いいたします。

[Attachment Removed]

調査報告とチケット報告ありがとうございます。

対処方法に関しましても、確保時のサイズをキャッシュしておいて解放時に減算対応の旨も承知いたしました。

本件に関してはチケット作成いただきましたのでクローズとさせていただきます。

ご対応ありがとうございます。

[Attachment Removed]

ご確認ありがとうございます。

本スレッドはクローズとさせていただきますが​、また何かございましたらお気軽にお問い合わせください。

よろしくお願いいたします。​

[Attachment Removed]