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

Unity技术问询:未在层级面板的预制体如何通过按钮修改材质

解决AR预制体不在Hierarchy时的材质切换问题

我明白你的痛点——把模型留在Hierarchy里会一直显示在AR场景中,但移除后又没法通过Inspector绑定按钮的OnClick事件。用AddListener动态绑定事件确实是正确的思路,我们可以通过一个全局管理器来搞定这个问题,具体方案如下:

步骤1:整理模型预制体

先把你的模型做成预制体(拖到Project面板里,然后从Hierarchy中移除),保留原来的ChangeColor脚本挂载在预制体上,原有逻辑不用修改。

步骤2:创建全局管理器脚本

新建一个名为ARMaterialController的脚本,挂载到场景中全程存在的对象上(比如AR Session Origin,它会在AR场景运行期间一直存在)。这个管理器会负责:

  • 引用你的UI按钮
  • 保存实例化后的模型引用
  • 动态给按钮绑定点击监听

管理器脚本代码:

using UnityEngine;
using UnityEngine.UI;

public class ARMaterialController : MonoBehaviour
{
    // 引用你的三个颜色切换按钮
    public Button greyBtn;
    public Button yellowBtn;
    public Button redBtn;

    // 你的模型预制体
    public GameObject modelPrefab;

    // 保存实例化后模型上的ChangeColor组件引用
    private ChangeColor modelColorHandler;

    void Start()
    {
        // 给按钮动态添加点击监听
        greyBtn.onClick.AddListener(TriggerGreyMaterial);
        yellowBtn.onClick.AddListener(TriggerYellowMaterial);
        redBtn.onClick.AddListener(TriggerRedMaterial);
    }

    // 这个方法要在AR识别到目标后调用(比如AR Tracked Image的回调里)
    public void SpawnARModel(Vector3 spawnPos, Quaternion spawnRot)
    {
        GameObject spawnedModel = Instantiate(modelPrefab, spawnPos, spawnRot);
        // 获取模型上的ChangeColor组件
        modelColorHandler = spawnedModel.GetComponent<ChangeColor>();
    }

    // 按钮点击后的实际执行逻辑
    private void TriggerGreyMaterial()
    {
        modelColorHandler?.GreyMaterial();
    }

    private void TriggerYellowMaterial()
    {
        modelColorHandler?.YellowMaterial();
    }

    private void TriggerRedMaterial()
    {
        modelColorHandler?.RedMaterial();
    }
}

步骤3:配置与使用

  1. 在Inspector面板给ARMaterialController赋值:
    • 把三个颜色按钮分别拖入对应的Button字段
    • 把你的模型预制体拖入modelPrefab字段
  2. 在你的AR识别逻辑里(比如AR Tracked Image Manager的OnTrackedImagesChanged回调),调用SpawnARModel方法实例化模型——这样模型只会在识别到目标后才出现,不会一直显示在场景里。
  3. 此时按钮的点击事件已经通过AddListener动态绑定,完全不需要再通过Inspector设置OnClick,只要模型被实例化出来,就能正常触发材质切换。

可选优化:简化逻辑(去掉原ChangeColor脚本)

如果你觉得模型上挂额外脚本麻烦,也可以把材质切换逻辑直接整合到管理器里,这样模型上不需要任何额外脚本:

using UnityEngine;
using UnityEngine.UI;

public class ARMaterialController : MonoBehaviour
{
    public Button greyBtn;
    public Button yellowBtn;
    public Button redBtn;
    public GameObject modelPrefab;
    // 直接在这里配置需要切换的材质数组
    public Material[] materials;

    private Renderer modelRenderer;

    void Start()
    {
        greyBtn.onClick.AddListener(() => SwitchMaterial(0));
        yellowBtn.onClick.AddListener(() => SwitchMaterial(1));
        redBtn.onClick.AddListener(() => SwitchMaterial(2));
    }

    public void SpawnARModel(Vector3 spawnPos, Quaternion spawnRot)
    {
        GameObject spawnedModel = Instantiate(modelPrefab, spawnPos, spawnRot);
        modelRenderer = spawnedModel.GetComponent<Renderer>();
        modelRenderer.enabled = true;
    }

    private void SwitchMaterial(int materialIndex)
    {
        if (modelRenderer != null && materialIndex < materials.Length)
        {
            modelRenderer.sharedMaterial = materials[materialIndex];
        }
    }
}

这种方式把所有逻辑集中在管理器里,更简洁,适合简单的材质切换场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 18:42:40