Unity开发:如何为可复用Shader设置默认纹理?
解决Unity中Sprite使用自定义Shader闪白时显示全白的问题
问题原因分析
Sprite显示全白,大概率是以下两个原因:
- 自定义Shader未正确处理纹理采样(比如缺少UV变换、未声明必要的纹理属性)
- 代码创建Material时,只设置了纹理,未同步原材质的UV平铺/偏移、颜色等关键属性
修复步骤
1. 确保自定义Shader正确处理纹理
检查你的Shader代码,必须包含完整的纹理属性声明和UV处理逻辑,示例如下:
Properties { _MainTex ("Sprite Texture", 2D) = "white" {} _FlashAmount ("Flash Intensity", Range(0, 1)) = 0.0 } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent" "IgnoreProjector"="True" "RenderPipeline"="UniversalPipeline" // 若使用URP,添加此标签 } Blend SrcAlpha OneMinusSrcAlpha Cull Off ZWrite Off Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float4 color : COLOR; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 color : COLOR; }; sampler2D _MainTex; float4 _MainTex_ST; // 必须声明,用于UV平铺/偏移变换 float _FlashAmount; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); // 处理UV的平铺和偏移 o.color = v.color; return o; } fixed4 frag (v2f i) : SV_Target { fixed4 baseColor = tex2D(_MainTex, i.uv) * i.color; // 闪白混合逻辑:原颜色与白色按_FlashAmount插值 baseColor.rgb = lerp(baseColor.rgb, fixed3(1,1,1), _FlashAmount); return baseColor; } ENDCG } }
2. 修改C#代码,正确创建Material
不要直接用Shader创建空Material,而是基于原SpriteRenderer的材质实例化,自动继承所有纹理和UV属性:
public class Health : MonoBehaviour { [SerializeField] private int _maxHealth; [SerializeField] private Shader _flashShader; [SerializeField] private SpriteRenderer _spriteRenderer; private int _health; private Material _flashMaterial; private void Awake() { _health = _maxHealth; // 基于原材质创建实例,再替换为闪白Shader _flashMaterial = new Material(_spriteRenderer.material); _flashMaterial.shader = _flashShader; _spriteRenderer.material = _flashMaterial; } public void OnDamage(int damage) { FlashDamage(); _health -= damage; if(_health <= 0) { Destroy(gameObject); } } public void OnHeal(int heal) { _health = Mathf.Min(_health + heal, _maxHealth); } private void FlashDamage() { StopAllCoroutines(); StartCoroutine(FlashDamageRoutine()); } private IEnumerator FlashDamageRoutine() { _flashMaterial.SetFloat("_FlashAmount", 1f); yield return new WaitForSeconds(0.15f); _flashMaterial.SetFloat("_FlashAmount", 0f); } }
3. 额外检查点
- 确认Sprite的纹理导入设置正确(比如Sprite模式、Alpha通道开启)
- 如果使用URP/HDRP,Shader要对应适配渲染管线的标签
内容的提问来源于stack exchange,提问作者Nombre de Usuario Genérico




