【发布时间】:2020-02-06 19:33:49
【问题描述】:
我有一个问题,我找到了解决方法,但不明白为什么 Unity 没有按我预期的方式工作,或者我做错了什么。基本上,我在脚本中引用了一个被破坏对象的渲染器组件(在它被破坏很久之后),空检查和类型检查都没有让我知道它被破坏了。
我有一个临时修改某些对象的着色器的脚本,以便我可以对它们应用效果;效果完成后,它会将材质/着色器恢复原状。
碰巧我在开始其中一个效果的同一帧中更换了角色的武器,因此脚本结束时引用了被破坏对象(旧武器)的渲染器。许多帧之后,当效果要完成时,它自然会出错。
我首先尝试了类型检查以查看引用是否仍然指向渲染器 - 不走运。 Unity 的文档说空检查应该有效,但仍然无效。
if (pair.Key != null && pair.Key is Renderer renderer) { renderer.materials = pair.Value; }
我明白了:
MissingReferenceException: The object of type 'SkinnedMeshRenderer' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
activeInHierarchy 同样不起作用。
在我销毁对象的代码中添加 DestroyImmediate 可以正常工作;效果开始时对象不存在,因此永远不会进行引用。但是,这只解决了这个问题,而不是其他此类情况。
谁能告诉我如何正确检查对已损坏对象或组件的引用,或者我在检查时是否做错了什么?我应该引用 gameObject 而不是渲染器组件或类似的东西吗?
编辑: 由于评论者要求它,这里是效果的完整代码的要点。破坏发生在此之外,因为它完全不相关。 https://gist.github.com/jackphelps/f507d949a84c53457f570c5009bcb6d4
解决了——有点? 我更改了字典以存储渲染器的游戏对象而不是渲染器,并且正如预期的那样,简单的空检查用于检测被破坏的对象。我喜欢知道为什么它在渲染器上不起作用,以及是否有适当的方法来检查!
【问题讨论】:
-
销毁对象时是否要从字典中删除键?
-
如果您注意到屏幕截图不在列表中,但我的代码显示字典:我的参考存储在字典中;因为 unity 不会序列化它们,所以我添加了跟踪与字典键/值对相同的引用的列表,所以我可以看到发生了什么。
-
为什么要使用字典来更改 renderer.materials?您可以直接从密钥中引用它。无需将其临时存储为值。
-
@ErikOverflow 我不是——物品破坏与效果完全无关,效果只是捡起物品,因为破坏发生在同一帧的早些时候。所以我需要一种方法来确保在效果的最后一位运行时字典仍然有效。
-
我正在更改材料,存储的参考是原始材料。我需要不同的临时效果。