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

Unity Shader无_MainTex属性 访问mainTexture偶发报错排查

问题说明

运行时抛出错误:Shader doesn't have a texture property '_MainTex'
异常表现如下:

  • 代码首次运行时完全正常,后续运行在如下代码行触发报错:
exampleTexture = (Texture2D)rend.material.mainTexture;
  • 当前使用的自定义Shader未定义Unity标准主纹理属性_MainTex,其Properties块定义如下:
Properties
    {
        _Example ("Example (R16)", 2D) = "black" {}
        _Color ("Color", Color) = (1, 1, 1, 1)
    }
  • 核心疑问:首次执行代码无任何异常,后续运行才触发报错。
产生原因

这个现象是Unity材质系统的懒加载机制+内置API的固定绑定逻辑共同导致的:

  1. Renderer.material是实例化材质属性,第一次访问这个属性时,Unity才会为当前渲染器克隆一份独立的材质实例(和共享材质sharedMaterial分离)。这个克隆过程是懒执行的,初始阶段材质和Shader的属性绑定校验还没完成,此时访问mainTexture,引擎找不到对应的_MainTex属性时只会静默返回null/默认占位纹理,不会抛出异常,所以第一次运行能正常走通流程。
  2. 等后续帧引擎完成材质实例与Shader的绑定校验后,会严格按照Shader中声明的Properties列表做属性合法性检查。而material.mainTexture是Unity为标准Shader预留的快捷访问API,它固定读写Shader中名为_MainTex的纹理属性,不会自动匹配你自定义的其他2D属性,此时检测到当前Shader没有声明_MainTex,就会直接抛出异常。

*补充:如果首次运行时你给mainTexture做过赋值,引擎会临时给材质实例挂载一个_MainTex的动态属性,等Shader重编译、场景重载、材质实例重置后这个临时属性被清除,再次访问时也会触发同样的报错。

解决方案

二选一即可,根据项目需求选择:

  • 方案1:保留现有C#代码逻辑,修改Shader对齐Unity标准属性规范
    直接在Shader的Properties块中补上_MainTex的声明即可,不需要改动原有_Example相关的渲染逻辑;如果不需要额外保留_Example属性,也可以直接把_Example重命名为_MainTex。补全声明的示例代码:
    Properties
        {
            _MainTex ("Base Texture", 2D) = "white" {} // 新增这一行即可
            _Example ("Example (R16)", 2D) = "black" {}
            _Color ("Color", Color) = (1, 1, 1, 1)
        }
    
  • 方案2:保留现有Shader结构,修改C#代码通过自定义属性名访问纹理
    弃用mainTexture这个固定绑定_MainTex的快捷API,改用通用的材质属性读写接口,直接操作你自定义的_Example纹理属性,修改后的代码示例:
    // 替换原有的rend.material.mainTexture读取逻辑
    exampleTexture = (Texture2D)rend.material.GetTexture("_Example");
    // 如果需要给纹理赋值,调用对应Set接口即可
    // rend.material.SetTexture("_Example", targetTexture);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:27:23