Pink Custom Shaders in a Windows PC when building for target Android

Addressables Version: 1.16.15 / 1.17.15
Shader code:

Shader "UI/Overlayed Color1"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
       
        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255

        _ColorMask ("Color Mask", Float) = 15

        [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
       
        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }

        Cull Off
        Lighting Off
        ZWrite Off
        ZTest [unity_GUIZTestMode]
        Blend One OneMinusSrcAlpha
        ColorMask [_ColorMask]

        Pass
        {
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "UnityUI.cginc"

            #pragma multi_compile __ UNITY_UI_ALPHACLIP
           
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                half2 texcoord  : TEXCOORD0;
                float4 worldPosition : TEXCOORD1;
            };
           
            fixed4 _Color;
            fixed4 _TextureSampleAdd;
            float4 _ClipRect;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.worldPosition = IN.vertex;
                OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);

                OUT.texcoord = IN.texcoord;
               
                #ifdef UNITY_HALF_TEXEL_OFFSET
                OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
                #endif
               
                OUT.color = IN.color * _Color;
                return OUT;
            }

            sampler2D _MainTex;

            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 c = tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd;
                float lum = (c.r + c.g + c.b) * 0.6666666;

                fixed3 c1 = IN.color.rgb * lum;
                fixed3 c2 = lerp(IN.color.rgb, fixed3(1,1,1), lum - 1);
                float r = step(1, lum);
                c.a *= IN.color.a * UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                c.rgb = (c1 * (1 - r) + c2 * r) * c.a;

                #ifdef UNITY_UI_ALPHACLIP
                clip (c.a - 0.001);
                #endif

                return c;
            }
        ENDCG
        }
    }
}

Steps to reproduce in empty-new project:

  1. Create a Prefab with an UI Image attached, reference a random sprite
  2. Reference a material that uses this custom shader
  3. Add the Prefab as addressable
  4. Switch Platform to Android
  5. Make Addressables build and make sure the Play Mode is set to Use Existing Groups
  6. Load the Prefab from an addressable bundle and instantiate it
  7. Watch how the Prefab is instantiated correctly, the sprite and materials are set correctly in the SpriteRenderer window.
  8. Watch how the Custom Shader is loaded correctly (its not a missing shader), however, all the settings are defaulted, is not fetching the Properties correctly from the custom shader, so it shows as pink.

This seems just to be an Editor issue, because apparently when building an apk it works fine.

Any ideas how to work around this issue in Editor or if theres any fix in sight for this ?

Hey, just wanted to chime in. I imagine that warning in your console is something similar to

There’s a bit of documentation about it here Getting started | Addressables | 1.17.17 but, admittedly, it could be better documented.

The tl;dr version is that we can’t support shaders built for non-Standalone platforms in the Editor because of how the shaders are compiled. Even if we implemented a solution so that playmode didn’t have pink (missing) shaders it would be because we force the Editor to look at standalone AssetBundles.

Sorry that it’s disappointing news. I hope this helps though

@davidla_unity Can you or someone else at Unity explain, what is the difference between a built-in shader such as UI/Default and a custom shader? Somehow this isn’t the issue with “UI/Default” but if someone makes their own copy of it, when loaded from a bundle it turns pink like any other custom shader.

Also worth mentioning, one could temporarily “fix” the issue by opening a material in playmode and simply re-assigning the shader, but it only works within one playmode session and isn’t really convenient.

It would be extremely useful to be able to get asset-bundled mobile shaders properly work in editor without a ton of hacks.

The issue is that the bundle you download contains a compiled version of the shader for Android, but you’re running on Windows which can’t use that compiled shader. When you run the project in editor, all local shaders are using the Windows compatible compiled shaders as they’re available in the asset database.

Even if it’s the same shader, Unity does not know that, because you can basically load any bundle with any shader content. There might be shaders you don’t have in your project. It’s the same with textures. Even you put the very same texture in a bundle that you have in the asset database, once loaded as asset bundle in editor, it will be a (compressed) copy of the texture and not the one in your asset database.

I think you can disable shader stripping to include all versions in the bundles, but to me this a bit defeats the purpose of bundles. I recommend making local Android builds to test the Addressables download flow.