私は最近、一度に複数のゲーム オブジェクトのインスタンス化を高速化するために、Unity でのオブジェクト プーリングを試しています。
ただし、これらはかなり複雑なオブジェクトであるため、プールに戻ったときにリセットする必要があります。
簡単にリセットできるようにデフォルト値を保存するには、ScriptableObject を使用するのが良い方法かもしれないと読みました。しかし、そのためには、実行時に新しい ScriptableObject をロードして、オブジェクトの実際の値を格納する必要があります。
したがって、疑似コードでは、とのクラスがpublic MyScriptableData data
ありますpublic MyScriptableData defaults
1) デフォルトの ScriptableObject でプールされた新しいオブジェクトを作成しますdata = defaults;
。
2) オブジェクトの存続期間中にスクリプト可能なオブジェクトの値を変更することを行う
3) 非アクティブ化してから、プールされたオブジェクトをプールに戻し、scriptableObject をデフォルトにリセットします (data = defaults;
再度)。
主な質問が 3 つあります。
A) 実際にこれを実装する方法がわかりません。ステップ2で、デフォルト値が変更されるようです。したがって、デフォルトにリセットしても何も起こりません。を使用して、スクリプト可能なオブジェクトの新しいインスタンスを作成することを考えました
data = ScriptableObject.CreateInstance<MyScriptableData>();
defaults
しかし、デフォルト値を からコピーして、デフォルト値を決して変更しないようにするにはどうすればよいでしょうか? Unity エディターでデフォルトをアセットとして編集できるようにしたいと考えています。
B) CreateInstance を使用すると、パフォーマンスが低下しますか? このオブジェクト プーリングを行っている全体的な理由は、オブジェクトのインスタンス化のパフォーマンス コストを削減することです。スクリプト可能なオブジェクトをインスタンス化して、遅いコードを再導入するのは嫌いです。
C) このアプローチは大丈夫ですか? または、プールに戻る前にオブジェクトをリセットするより良い方法はありますか?
いくつかの回答に基づいて編集:私はすでにフィールドの長いリストを持ち、これらのフィールドのデフォルト値を辞書に保存するセットアップを持っています。しかし、フィールドを追加/変更/削除するたびに、いくつかの場所でコードを変更する必要があることがわかりました
試みられた解決策 (ただし、間違っています。以下を参照してください): ScriptableObject の拡張メソッドを作成しました。
using UnityEngine;
using System.Reflection;
public static class ScriptableObjectExtension {
public static T ShallowCopy<T> (this T orig) where T : ScriptableObject {
T copiedObject = ScriptableObject.CreateInstance<T> ();
FieldInfo[] myObjectFields = orig.GetType ().GetFields (
BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.Instance);
foreach (FieldInfo fi in myObjectFields) {
fi.SetValue (copiedObject, fi.GetValue (orig));
}
return copiedObject;
}
}
最終的解決:
上記のスクリプトは、スクリプト可能なオブジェクトを複製するために機能しましたが、そのソリューションでは間違った道をたどっていたようです。
以下の何人かの人々は、プーリングはほとんどのアプリケーションの単一性においてそれほど重要ではないことを指摘しています。プロファイラーによるフレームレートが約 30 ~ 15 fps だったので、最初はプーリングを入れようとしましたが、プーリングがそれを改善するのに役立つと思いました。
コメントに基づいて、もう少し深く掘り下げたところ、LogStringToConsole というプロセスがあることがわかりました。これは、私の Debug.Log ステートメントが速度を落とすのと同じくらい簡単なことではないでしょうか!? それらを削除したところ、大きなスパイクはなくなりました。どうやら Debug.Log は大きなパフォーマンスの問題を引き起こします。今は60fpsを大きく超えています。このため、これらのオブジェクトをプールしないことにしました (ただし、1 秒間に数回生成される別のシナリオでは、より単純なオブジェクトにプールを使用しています)。これは、ここではスクリプト可能なオブジェクトについてまったく心配する必要がないことを意味します。私は今、プレハブと Init メソッドをロードして物事をセットアップし、それらが使い果たされるとオブジェクトが破棄されるインスタンスを作成しました。
インスタンス化/破棄の使用に戻ったとき、パフォーマンスに大きな変化は見られませんでした。すべての応答に感謝します!