如何破坏静态类中创建的统一对象?

时间:2017-01-14 10:51:45

标签: unity3d

请考虑以下代码。它从特定路径创建材质和着色器。它是在编辑器扩展中使用的实用程序。

public static class GpuImageProcessing
{
    private static readonly string matPath = Application.dataPath + "/Uplus/Zcommon/Material/ImageProcessing/";

    private static Shader Gaussian2D5Shader;
    private static Material Gaussian2D5Mat;
    static GpuImageProcessing()
    {
        Gaussian2D5Shader = (Shader) AssetDatabase.LoadAssetAtPath(matPath 
           + "Gaussian2D5.shader", typeof(Shader));
        Gaussian2D5Mat = new Material(Gaussian2D5Shader);
    }
}

现在问题是如何在每次更改某些脚本时编辑器重新编译之前销毁此材料?我的意思是在更改了一些代码之后,编辑器需要重新编译脚本并创建一个新的执行上下文,并且将创建此GpuImageProcessing的新版本。我想破坏之前运行时创建的材料。

PS:这包含在DLL文件中,因此我无法将其设为ScriptableObject并监听事件回调,也因为它是实用程序类我真的很喜欢它是静态的。

1 个答案:

答案 0 :(得分:0)

感谢@Programmer找出解决方法以确保材料的销毁。为了使其工作,该类应该成为单身并继承自ScriptableObject。然后我们可以实现OnDisable(),并在编辑器重新编译时调用它。以下是工作示例:

public class GpuImageProcessing:ScriptableObject
{
    private static readonly string matPath = "Assets/Uplus/Zcommon/Material/ImageProcessing/";

    private Material Gaussian2D5Mat;
    private Material Gaussian1DVariableMat;

    private static GpuImageProcessing _instance;
    private bool destroyedAlready;

    public static GpuImageProcessing Instance
    {
        get
        {
            if (_instance != null) return _instance;
            _instance= CreateInstance<GpuImageProcessing>();
            _instance.Init();
            return _instance;
        }
    }

    private void Init()
    {
        var Gaussian2D5Shader = (Shader)AssetDatabase.LoadAssetAtPath(matPath + "Gaussian2D5.shader", typeof(Shader));
        Gaussian2D5Mat = new Material(Gaussian2D5Shader);

        var gaus1dVarShader = (Shader)AssetDatabase.LoadAssetAtPath(matPath + "Gaussian1DVariable.shader", typeof(Shader));
        Gaussian1DVariableMat = new Material(gaus1dVarShader);
    }

    private void OnDisable()
    {
        Debug.Log("On disable GpuImgProc");
        if(destroyedAlready) return;
        DestroyImmediate(Gaussian2D5Mat);
        DestroyImmediate(Gaussian1DVariableMat);
        destroyedAlready = true;
        DestroyImmediate(this);
    }
}

重要提示:请注意destroyedAlready字段。它确保材料只被销毁一次,因为OnDisable被调用两次(一次是统一编辑器调用它时,一次是我们DestroyImmediate(this)时)。请在致电destroyedAlready之前设置DestroyImmediate(this)

虽然不是原始问题的确切解决方案而不是一个很好的解决方案,但它确实有效,可以防止内存泄漏,同时保留类的静态特性。