Page 1 of 2

BehaviourTreeコンポーネントを破棄した後も意図せずメモリに残り続けているコンポーネントがある

Posted: 2024/12/19 09:53
by urkw
お世話になっております。
BehaviourTreeによる制御を行った後のメモリ使用について質問です。

BehaviourTreeコンポーネントを含むGameObjectが破棄された後にMemoryProfilerでキャプチャをしたところ、破棄されたはずのコンポーネントがメモリに残り続ける現象を確認しています。
このコンポーネントがどこから参照されているかMemoryProfilerで確認したところ、最終的にArborのNodeで参照されているようです。
Calculator等ノードの入出力となったコンポーネントがstatic変数のようなもので参照され続けており、GCで破棄されない可能性を検討しています。

この現象はArborの仕様もしくは不具合でしょうか。
こちらの実装の問題かどうか切り分けを行いたく質問させていただきました。

仕様の場合は回避策があればご教授いただけますと幸いです。
ご確認よろしくお願いします。

Re: BehaviourTreeコンポーネントを破棄した後も意図せずメモリに残り続けているコンポーネントがある

Posted: 2024/12/19 10:38
by caitsithware
まずコンポーネントがNodeBehaviour関連の場合についてです。
最初に考えられるのは、エディタ上でノードなどをコピーした場合です。
この場合はクリップボードのような内部データにコンポーネントそのものがコピーされていますのでコピー元が破棄されても残ります。
またNodeBehaviourのフィールドから参照しているコンポーネントもGCの対象から外れます。
こちらについては仕様であり、ランタイムへの影響もありませんのでそのままでも問題ないかと思います。

エディタ操作に関係なくビルドしたランタイムでも残る場合はArbor3の何らかのキャッシュの不具合の可能性が高いです。
ざっと調べてみたところ問題がありそうな箇所がありますので今後の更新で対応いたします。

暫定対処方法
  • Assets/Plugins/Arbor/Internal/Scripts/EachField.csを開く
  • 686行目(メソッド内の一番最後の行)に以下のコードを追加

    Code: Select all

    s_FindReceiver.receiver = null;
この他にもあるかもしれないため、正式な修正は更新までお待ちください。

NodeBehaviour関連以外の場合は特にキャッシュは行っていないと思いますが、すべてを調査する必要がありますので現時点では分かりません。
Arborが原因でキャッシュされていると思われる箇所の情報などが他にありましたらご報告いただけると助かります。

Re: BehaviourTreeコンポーネントを破棄した後も意図せずメモリに残り続けているコンポーネントがある

Posted: 2024/12/20 01:51
by urkw
ご連絡ありがとうございます。

報告した現象はランタイムで確認しております。
こちらで確認した限りではCalculatorやDecoratorの入出力となったコンポーネントが残っており、NodeBehaviour関連である可能性が高いと推測します。
こちらでもEachField.csやCalculator.csのstatic変数にあたりを付け調査を行っていますが、特定には至っておりません。
いただいた暫定対処方法で改善するか確認いたします。

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

Re: BehaviourTreeコンポーネントを破棄した後も意図せずメモリに残り続けているコンポーネントがある

Posted: 2024/12/20 03:15
by urkw
暫定対処を試しましたが、NullExceptionが発生&EachField.cs L435にnullチェックを追加しましたが今度はうまくビヘイビアツリーが動作しなくなってしまいました。
メソッドの一番最後に追加とのことでしたが、EachField<T>.Find(object rootObj, System.Type type, IFindReceiver receiver, bool ignoreRoot)の一番最後ということであっていますでしょうか。

Code: Select all

s_FindReceiver.receiver = null;
引き続き調査しますが、情報ありましたらよろしくお願いいたします。

Re: BehaviourTreeコンポーネントを破棄した後も意図せずメモリに残り続けているコンポーネントがある

Posted: 2024/12/20 03:44
by caitsithware
再帰的に呼び出される可能性を失念しており内容が不十分でした。
正確には以下のようなコードにしてください。

Code: Select all

public static void Find(object rootObj, System.Type type, IFindReceiver receiver, bool ignoreRoot)
{
	var oldReceiver = s_FindReceiver.receiver;
	s_FindReceiver.receiver = receiver;
	s_FindReceiver.Find(rootObj, type, ignoreRoot);
	s_FindReceiver.receiver = oldReceiver;
}

Re: BehaviourTreeコンポーネントを破棄した後も意図せずメモリに残り続けているコンポーネントがある

Posted: 2024/12/20 03:51
by caitsithware
もともとのコードもあまり良い作りとは言えない点に加え、別件で報告がありましたInstantiateAsyncで動かない不具合も同じ箇所が関連していますのでここは次回更新であわせて修正いたします。

Re: BehaviourTreeコンポーネントを破棄した後も意図せずメモリに残り続けているコンポーネントがある

Posted: 2024/12/20 07:20
by urkw
ご対応ありがとうございます。
新しくいただいた対応を入れて検証してみましたが、症状は改善しませんでした。
引き続き情報がありましたらよろしくお願いいたします。

アップデートでの対応もお待ちしております。

Re: BehaviourTreeコンポーネントを破棄した後も意図せずメモリに残り続けているコンポーネントがある

Posted: 2024/12/20 07:54
by caitsithware
ご確認ありがとうございます。

EachFieldの各種Findメソッドでのキャッシュは他にもありますので、そちらも同様の対策が必要なようです。
ひとまずこちらの開発環境(InstantiateAsyncへの対策も行った環境)にて、一通りEachFieldへの対策を行い関連オブジェクトDestroy後にMemoryProfilerを確認したところAll Of MemoryタブのManaged/Managed ObjectsにArbor3関連のコンポーネントのインスタンスが残っていないことを確認いたしました。
次回の更新でこの対応を適用いたします。

Re: BehaviourTreeコンポーネントを破棄した後も意図せずメモリに残り続けているコンポーネントがある

Posted: 2024/12/20 08:14
by urkw
ご対応ありがとうございます。
それでは、次回アップデートの反映を検討させていただきます。
引き続きよろしくお願いいたします。

Re: BehaviourTreeコンポーネントを破棄した後も意図せずメモリに残り続けているコンポーネントがある

Posted: 2024/12/21 09:52
by caitsithware
Arbor関連でGCの対象にならずにメモリーに残るかどうかの仕様についてもまとめましたので記載いたします。

残るのが仕様
  • ArborEditorを開いた場合など、エディタ関連で参照されているデータ全般
  • 型情報や属性などのキャッシュデータ
  • 破棄されていないArbor関連コンポーネントから参照(Parameterやデータフローでの受け渡し含む)されているインスタンス
残らないのが仕様
  • 破棄されたArbor関連コンポーネントからのみ参照(Parameterやデータフローでの受け渡し含む)されていたインスタンス
※「インスタンス」はコンポーネントなどUnityオブジェクト以外の参照型のインスタンスもすべて含まれます

とくに「破棄されていないArbor関連コンポーネントから参照されているインスタンス」についてはインスタンスが破棄されたかどうかの検出が難しいため、破棄されても残っているのは仕様であり現時点で改善予定はないものとしてご理解ご了承のほどよろしくお願いいたします。