我试图根据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
}
我做错了什么?
1条答案
按热度按时间jv4diomz1#
您试图通过变量t来固定transform,只是为了稍后在delayCall回调中使用它。考虑到Unity中的许多类型包含非托管资源,这是很危险的,因此会出现错误。如果您在WinForms中创建了一个字体,释放它,然后尝试使用该字体,效果是相同的。
操作:
那有没有更好的方法来处理这件事呢?
据我所知,
Transform
总是连接到GameObject
,而被破坏的是GameObject
,同时也破坏了Transform
。我所知道的防止游戏对象破坏的唯一方法是通过
DontDestroyOnLoad
,但我不确定它是否适用于这里,因为后者是真正为保护而设计的,同时过渡到一个 * 新的场景 *,但你永远不知道也许它可以防止东西在其他场景中被破坏。尝试在
ValidateComponent
的顶部调用DontDestroyOnLoad
,如下所示:否则,就会出现Unity Answer,它建议简单地禁用并重新启用对象,而不是首先破坏对象。按照这种方法,您不需要对上面的代码进行任何更改。
仅编辑器时间脚本
顺便说一句,关于
#if UNITY_EDITOR
位,如果你想避免在代码中到处使用#if
来修饰代码(作为一个前c/c++程序员,我当然不会错过必须一直这样做的机会),考虑简单地将您的脚本移动到名为Editor的子文件夹中。Unity会自动将放置在此类文件夹中的任何内容视为仅限编辑时间,并且不会“不要被纳入你的最终游戏构建。更好的是,不需要#if
的东西。最好的原因是,当Unity制作你的最终游戏时,由于忘记使用
#if
或Editor文件夹而导致的构建错误。我通常会在Unity商店中的第三方脚本中遇到这种情况。我不必修复代码,只需将其移动到一个子Editor文件夹中。另请参阅