ご要望ありがとうございます。
NodeGraph生成時における負荷についてですね。
ObjectPoolによる事前生成
まず、ゲーム途中に生成が頻発し高負荷になってしまうのが問題の場合、ObjectPoolingを使用して必要な数を予め生成しておきオブジェクトを使いまわす方法があります。
主に以下の流れでObjectPoolingを使用します。
- AdvancedPoolingでGameObjectを必要数プールする。
生成には若干時間がかかるため、生成完了まで待つReadyリンクより遷移する。
- InstantiateGameObjectのUse Poolにチェックを入れて生成する。
- 不要になったらDestroyGameObjectで破棄する(この時プール可能であればプールへ戻される)
注意点としては、再利用された場合にコンポーネントの各フィールドやプロパティは以前のままとなっています。
もし残ってしまうと困る場合は、削除前に初期値に戻すなどの処理も行ってください。
※自動的に初期値に戻す対応を行うとなるとこちらもReflectionを使用せざるを得なくなりObjectPoolingによる負荷軽減の意味がなくなってしまうため、各自対応をお願いいたします。
自作するスクリプトでもArbor内のObjectPooling機能を使用する場合は、
ObjectPooling名前空間に各種クラスがありますので参考にしてみてください。
RegisterNodesを各グラフでReflectionを使用せずに行う
ArborFSMInternal、
BehaviourTreeInternalにNodeGraph.RegisterNodes()を移植し、各ノードリストを直接登録することでReflection使用を回避する方法です。
例えば以下のような移植の流れとなります。
- NodeGraphクラスにOnRegisterNodes()を追加(中身は不要)。
Code: Select all
protected virtual void OnRegisterNodes()
{
}
- NodeGraph.RegisterNodes()を以下のように変更。
Code: Select all
void RegisterNodes()
{
ClearNodes();
foreach (var node in _Calculators)
{
RegisterNode(node);
}
foreach (var node in _Comments)
{
RegisterNode(node);
}
foreach (var node in _Groups)
{
RegisterNode(node);
}
for (int i = 0; i < _DataBranchRerouteNodes.count; i++)
{
RegisterNode(_DataBranchRerouteNodes[i]);
}
OnRegisterNodes();
}
- ArborFSMInternalクラスにOnRegisterNodes()追加。
Code: Select all
protected override void OnRegisterNodes()
{
foreach (var node in _States)
{
RegisterNode(node);
}
for (int i = 0; i < _StateLinkRerouteNodes.count; i++)
{
RegisterNode(_StateLinkRerouteNodes[i]);
}
}
- BehaviourTreeInternalクラスにOnRegisterNodes()追加。
Code: Select all
protected override void OnRegisterNodes()
{
RegisterNode(_RootNode);
for (int i = 0; i < _CompositeNodes.count; i++)
{
RegisterNode(_CompositeNodes[i]);
}
for (int i = 0; i < _ActionNodes.count; i++)
{
RegisterNode(_ActionNodes[i]);
}
}
※もしforeachの使用も削減する方針でしたら、forへの置き換えはご自由に行ってください。
変更箇所が多岐にわたる点および対象ファイルがシステムの根幹の部分になるため、変更後のファイルの暫定的な配布は行っておりません。
上記移植の流れを参考に変更していただくようお願いいたします。
この変更は、今後の更新で対応する方向で検討いたします。
その他、Reflectionの使用について
今から全体的にReflectionの使用をほぼ禁止とすると、ユーザー様の作成するスクリプトにも変更が必要になってしまうような大幅な仕様変更となってしまうため、現状でReflectionの使用を削減するのは難しいです。
よって現状では全体的なReflection使用削減を行う予定はございません。
ご理解のほどよろしくお願いいたします。
Instantiate時の負荷について
そもそものUnityの仕様としてInstantiate自体も高負荷であるため、頻繁に呼び出すようなことがある場合は、ObjectPoolingを使用するようにお願いいたします。
とはいえ、Arbor内部の処理負荷も高くなっているのも事実であるため、可能な限り負荷軽減できないかも今後の課題として検討いたします。
取り急ぎ、まず全体としてObjectPoolingに対応できそうかやRegisterNodesの変更でどうなるかご検証ください。
以上となります。
ご不便おかけして申し訳ございませんがよろしくお願いいたします。