Ada*_*m B 2 c# unity-game-engine object-pooling unity5
我最近一直在尝试统一对象池,以便一次加速几个游戏对象的实例化.
但是,由于这些是相当复杂的对象,我需要在它们返回池中时重置它们.
我读到使用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)这种方法好吗?或者是否有更好的方法在返回池之前重置对象?
编辑基于一些答案:我已经有一个具有很长字段列表的设置,然后将这些字段的默认值存储在字典中.但我发现每次我想添加/更改/删除字段时,我都必须在几个位置更改代码
ATTEMPTED SOLUTION(但错误,见下文):我为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;
}
}
Run Code Online (Sandbox Code Playgroud)
最终解决方案:
上面的脚本用于克隆可编写脚本的对象,但是,看起来我正在使用该解决方案走错路.
下面的几个人指出,对于大多数应用来说,池化并不是那么重要.我最初试图将游泳池放入,因为我根据剖面仪的帧速率大约是30-15 fps,我认为合并可以帮助改善这一点.
根据评论我挖得更深一点,发现有一个名为LogStringToConsole的进程.我对自己说,这可能就像我的Debug.Log语句一样简单!我删除了它们,巨大的尖峰消失了.显然Debug.Log会导致巨大的性能问题.现在我已经超过了60fps.因此我决定不对这些对象进行池化(但是我仍然在另一个场景中使用更简单的对象进行池化,这些场景每秒会产生几次).这意味着我根本不需要担心脚本化对象.我现在已经并实例化了加载预制件和Init方法进行设置,并且对象在用完后会被销毁.
当我回到使用instantiate/destroy时,我没有注意到性能的重大变化.感谢所有的回复!
如果您只需要在停用时重置对象的值,则不能简单地使用:
OnEnable()
{
default = data;
}
OnDisable()
{
data = default;
}
Run Code Online (Sandbox Code Playgroud)
这将允许您在激活时存储/分配默认数据,并在停用时将其数据重置为默认值.