You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何批量切换多个MeshRenderer的材质并恢复原材质?

解决Unity中MeshRenderer批量切换并恢复材质的问题

嘿,我来帮你搞定这个材质切换的问题~你的现有代码有两个核心问题:一是错误地用了renderer[i].materials[i]来替换材质(这会把第i个Renderer的第i个材质换掉,但每个Renderer的材质数量不一定和数组索引匹配),二是没有保存每个Renderer的原始材质数据,所以根本没法恢复。下面是完整的可行方案:

核心思路

我们需要先把每个MeshRenderer的完整原始材质数组保存下来,之后切换时把该Renderer的所有材质都替换成目标材质,恢复时再把保存的原始数组赋值回去。

完整代码实现

using UnityEngine;
// 如果用后面的Linq优化,需要加这个:using System.Linq;

public class MaterialSwitcher : MonoBehaviour
{
    public MeshRenderer[] renderers; // 把变量名改成复数,避免和内置的renderer属性冲突
    public Material switchMat;
    private Material[][] originalMaterials; // 二维数组:每个元素对应一个MeshRenderer的原始材质集合

    private void Start()
    {
        // 初始化并保存所有原始材质,同时切换到目标材质
        SwitchToTargetMaterial();
    }

    // 封装成单独方法,方便随时调用切换
    public void SwitchToTargetMaterial()
    {
        if (renderers == null || switchMat == null) return;
        
        originalMaterials = new Material[renderers.Length][];
        for (int i = 0; i < renderers.Length; i++)
        {
            if (renderers[i] == null) continue;
            
            // 保存当前Renderer的所有原始材质(用.materials获取实例化副本,不影响全局材质)
            originalMaterials[i] = renderers[i].materials;
            
            // 创建一个和原始材质数量相同的数组,全部填充目标材质
            Material[] newMatArray = new Material[originalMaterials[i].Length];
            for (int j = 0; j < newMatArray.Length; j++)
            {
                newMatArray[j] = switchMat;
            }
            
            // 赋值给Renderer完成切换
            renderers[i].materials = newMatArray;
        }
    }

    // 恢复所有Renderer的原始材质
    public void SwitchBack()
    {
        if (originalMaterials == null || renderers == null) return;
        
        for (int i = 0; i < renderers.Length; i++)
        {
            if (renderers[i] == null || originalMaterials[i] == null) continue;
            
            // 直接把保存的原始材质数组赋值回去
            renderers[i].materials = originalMaterials[i];
        }
    }
}

关键细节要注意

  • 变量名规范:把renderer改成renderers,避免和Unity组件自带的renderer属性重名,减少代码混淆。
  • .materials vs .sharedMaterials:一定要用.materials!它会返回当前Renderer专属的材质副本,修改它只会影响这个对象;而.sharedMaterials是直接引用全局材质资源,改了会影响所有用这个材质的物体,绝对不适合这个场景。
  • 空值检查:代码里加了多处null判断,避免因为某个MeshRenderer引用为空或者目标材质没赋值导致运行时报错。
  • 简化写法(可选):如果觉得创建新材质数组的循环麻烦,可以用Linq的Enumerable.Repeat简化,把那段循环换成:
    Material[] newMatArray = Enumerable.Repeat(switchMat, originalMaterials[i].Length).ToArray();
    
    记得顶部要加using System.Linq;哦。

使用方法

  1. 把这个脚本挂到任意GameObject上。
  2. 在Inspector面板中,把需要切换材质的所有MeshRenderer拖进renderers数组。
  3. 拖入你要切换的目标材质到switchMat
  4. 可以通过调用SwitchToTargetMaterial()SwitchBack()方法来控制切换和恢复(比如用UI按钮的点击事件绑定)。

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

火山引擎 最新活动