You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity重置水管预制体后MeshRenderer引用丢失问题求助

问题根源

当你销毁旧的PipeGrid预制体后,仍然有代码在调用已销毁Pipe实例的材质修改方法,这些旧实例中的_renderer缓存指向已经被销毁的MeshRenderer组件,因此触发MissingReferenceException。新实例化的Pipe虽然会在Start中重新缓存Renderer,但如果你的逻辑还持有旧Pipe的引用,就会访问到失效的组件。

解决方案

1. 彻底清理旧Pipe的引用

如果你的游戏中有管理所有Pipe实例的集合(比如List<Pipe> _allPipes),在销毁Grid前必须清空这个集合,避免后续逻辑调用旧实例:

private List<Pipe> _allPipes;

private void DestroyGrid()
{
    // 清空旧Pipe引用
    if (_allPipes != null)
    {
        _allPipes.Clear();
    }
    Destroy(_currentPipeGrid);
}

2. 实例化新Grid后更新Pipe引用

在新Grid创建完成后,重新获取所有Pipe组件并更新引用集合,确保后续操作都针对新实例:

private void InstantiateGrid()
{
    _currentPipeGrid = Instantiate(pipeGridPrefab);
    // 获取新Grid下所有Pipe组件
    _allPipes = new List<Pipe>(_currentPipeGrid.GetComponentsInChildren<Pipe>());
}

3. 在Pipe脚本中增加安全检查(可选但推荐)

在每个修改材质的方法中,先检查_renderer是否有效,避免意外访问已销毁对象:

private MeshRenderer _renderer;

private void Start()
{
    _renderer = GetComponent<MeshRenderer>();
}

// 新增检查方法
private bool IsRendererValid()
{
    if (_renderer == null)
    {
        _renderer = GetComponent<MeshRenderer>();
        // 如果还是null,说明对象已销毁或没有该组件
        return _renderer != null;
    }
    // 检查组件是否已被销毁
    return !_renderer.Equals(null);
}

public void ChangeColor()
{
    if (!IsRendererValid()) return;
    _renderer.material = _wateredPipe;
}

public void RevertToOriginalMaterial()
{
    if (!IsRendererValid()) return;
    _renderer.material = _originalMaterial;
}

public void MakePipeRed()
{
    if (!IsRendererValid()) return;
    _renderer.material.color = Color.red;
}

public void MakePipeGreen()
{
    if (!IsRendererValid()) return;
    _renderer.material.color = Color.green;
}

4. 优化初始Grid的获取方式

Start中用GameObject.FindGameObjectWithTag不够可靠,建议直接在Inspector中将初始的PipeGrid赋值给_currentPipeGrid,避免查找错误:

[SerializeField] private GameObject pipeGridPrefab;
[SerializeField] private GameObject _currentPipeGrid; // 直接在编辑器中拖入初始Grid

private void Start()
{
    // 移除原来的Find代码,直接用赋值好的引用
    _allPipes = new List<Pipe>(_currentPipeGrid.GetComponentsInChildren<Pipe>());
}
关键注意点
  • 永远不要持有已销毁对象的引用,重置关卡时必须同步清理所有相关引用集合。
  • 所有对Pipe的操作,都要通过更新后的_allPipes集合来进行,不要保留零散的旧Pipe引用。

内容的提问来源于stack exchange,提问作者williepaprika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 23:15:35