unity3d 尝试撷取Lambda中的变数时发生MissingReferenceException

bd1hkmkf  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(143)

我试图根据this post访问lambda内部的一个局部变量的值,但是我遇到了这个异常:
缺少引用异常:“Transform”类型的对象已被破坏,但您仍在尝试访问它。
下面是我的代码:

private static void ValidateComponent<T>(Transform transform, Delegate validationMethod, object[] args) where T : Component
{
#if UNITY_EDITOR // EditorApplication is only available when running in the editor
    if (EditorApplication.isPlaying) return;

    if (transform == null) return; // in case inspector field is not assigned

    var t = transform;

    EditorApplication.delayCall += () =>
    {
        var component = t.GetComponent<T>();

        if (component == null)
        {
            LogAddingComponent<T>(t);
            var addedComponent = t.gameObject.AddComponent<T>();
            validationMethod.DynamicInvoke(args.Prepend(addedComponent));
        }
        else
        {
            validationMethod.DynamicInvoke(args.Prepend(component));
        }
    };
#endif
}

我做错了什么?

jv4diomz

jv4diomz1#

您试图通过变量t来固定transform,只是为了稍后在delayCall回调中使用它。考虑到Unity中的许多类型包含非托管资源,这是很危险的,因此会出现错误。如果您在WinForms中创建了一个字体,释放它,然后尝试使用该字体,效果是相同的。
操作:
那有没有更好的方法来处理这件事呢?
据我所知,Transform总是连接到GameObject,而被破坏的是GameObject,同时也破坏了Transform
我所知道的防止游戏对象破坏的唯一方法是通过DontDestroyOnLoad,但我不确定它是否适用于这里,因为后者是真正为保护而设计的,同时过渡到一个 * 新的场景 *,但你永远不知道也许它可以防止东西在其他场景中被破坏。
尝试在ValidateComponent的顶部调用DontDestroyOnLoad,如下所示:

private static void ValidateComponent<T>(Transform transform, 
                                         Delegate validationMethod,
                                         object[] args) 
    where T : Component
{
#if UNITY_EDITOR // EditorApplication is only available when running in the editor
    if (EditorApplication.isPlaying) return;

    if (transform == null) return; // in case inspector field is not assigned

    DontDestroyOnLoad (transform.gameObject); // <---- new
    var t = transform;
.
.
.

否则,就会出现Unity Answer,它建议简单地禁用并重新启用对象,而不是首先破坏对象。按照这种方法,您不需要对上面的代码进行任何更改。

仅编辑器时间脚本

顺便说一句,关于#if UNITY_EDITOR位,如果你想避免在代码中到处使用#if来修饰代码(作为一个前c/c++程序员,我当然不会错过必须一直这样做的机会),考虑简单地将您的脚本移动到名为Editor的子文件夹中。Unity会自动将放置在此类文件夹中的任何内容视为仅限编辑时间,并且不会“不要被纳入你的最终游戏构建。更好的是,不需要#if的东西。
最好的原因是,当Unity制作你的最终游戏时,由于忘记使用#ifEditor文件夹而导致的构建错误。我通常会在Unity商店中的第三方脚本中遇到这种情况。我不必修复代码,只需将其移动到一个子Editor文件夹中。

另请参阅

相关问题