已销毁GameObject的Renderer状态?获取子对象Renderer遇缺失问题求助
Unity Renderer相关问题解答
问题1:已被销毁的GameObject其Renderer会处于何种状态?
当一个GameObject被销毁后,挂载在它上面的Renderer组件会变成无效的引用(也就是我们常说的"missing reference"),具体状态表现为:
- 用
renderer == null判断会返回true(Unity重载了==运算符,专门用来检测这类无效的对象引用) - 调用
Object.ReferenceEquals(renderer, null)同样会返回true - 该Renderer的
gameObject属性会变为null - 尝试访问它的任何属性(比如
enabled、material)都会触发空引用异常
问题2:过滤GetComponentsInChildren返回的缺失Renderer引用
你遇到的情况是因为Unity的对象销毁是延迟执行的:调用Destroy()后,对象会被标记为待销毁,直到下一帧才会从场景中真正移除,所以当前帧调用GetComponentsInChildren<Renderer>()还是能拿到这些无效的引用。
这里给你两种可靠的过滤方案:
方案一:利用Unity重载的==运算符直接判断
这种方式兼容所有Unity版本,代码简洁直观:
// 先获取所有子对象的Renderer List<Renderer> allRenderers = new List<Renderer>(); parent.GetComponentsInChildren(allRenderers); // 过滤无效引用 List<Renderer> validRenderers = new List<Renderer>(); foreach (var renderer in allRenderers) { if (renderer != null) // Unity会自动识别无效引用并返回true { validRenderers.Add(renderer); } } // 或者用LINQ简化写法(需要引入using System.Linq;) var validRenderers = parent.GetComponentsInChildren<Renderer>() .Where(r => r != null) .ToList();
方案二:使用Object.IsValid()(Unity 2020.1+可用)
这个方法是Unity官方提供的专门检测对象有效性的API,语义更清晰:
List<Renderer> allRenderers = new List<Renderer>(); parent.GetComponentsInChildren(allRenderers); var validRenderers = allRenderers .Where(r => UnityEngine.Object.IsValid(r)) .ToList();
另外补充一点:如果你的子对象只是被禁用(而非销毁),可以在调用GetComponentsInChildren时传入false作为第二个参数(默认值就是false),这样会自动跳过非激活状态的对象;但对于已销毁的对象,必须通过上述方式手动过滤。
内容的提问来源于stack exchange,提问作者CodeJock
相关产品推荐
相关产品推荐

