Unity:需要在返回池时重置池化对象.也许使用ScriptableObject?

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时,我没有注意到性能的重大变化.感谢所有的回复!

Dis*_*Neo 5

如果您只需要在停用时重置对象的值,则不能简单地使用:

OnEnable()
{
    default = data;
}

OnDisable()
{
    data = default;
}
Run Code Online (Sandbox Code Playgroud)

这将允许您在激活时存储/分配默认数据,并在停用时将其数据重置为默认值.