Skip to content

Instantly share code, notes, and snippets.

@LordNed
Last active November 23, 2020 14:08
Show Gist options
  • Save LordNed/ffd97796bf2cc98555eb to your computer and use it in GitHub Desktop.
Save LordNed/ffd97796bf2cc98555eb to your computer and use it in GitHub Desktop.
2D Sprite Blinking
Shader "Sprites/Diffuse Flash"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_SelfIllum ("Self Illumination",Range(0.0,1.0)) = 0.0
_FlashAmount ("Flash Amount",Range(0.0,1.0)) = 0.0
_Color ("Tint", Color) = (1,1,1,1)
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Cull Off
Lighting Off
ZWrite Off
Fog { Mode Off }
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma surface surf Lambert alpha vertex:vert
#pragma multi_compile DUMMY PIXELSNAP_ON
sampler2D _MainTex;
fixed4 _Color;
float _FlashAmount,_SelfIllum;
struct Input
{
float2 uv_MainTex;
fixed4 color;
};
void vert (inout appdata_full v, out Input o)
{
#if defined(PIXELSNAP_ON) && !defined(SHADER_API_FLASH)
v.vertex = UnityPixelSnap (v.vertex);
#endif
v.normal = float3(0,0,-1);
UNITY_INITIALIZE_OUTPUT(Input, o);
o.color = _Color;
}
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * IN.color;
o.Albedo = lerp(c.rgb,float3(1.0,1.0,1.0),_FlashAmount);
o.Emission = lerp(c.rgb,float3(1.0,1.0,1.0),_FlashAmount) * _SelfIllum;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Transparent/VertexLit"
}
using UnityEngine;
using System.Collections;
public class SpriteFlash : MonoBehaviour
{
/// <summary> Renderer who's material we want to cause to flash. Material must have a "_FlashAmount" float property ([0-1]) to tween. </summary>
[SerializeField] private Renderer m_sprite;
/// <summary> Rate at which the sprite will flash - specifies duration of one half of the interval, ie: "0.1" will spend 0.1 seconds on, then 0.1s off. </summary>
public float FlashRate = 0.1f;
/// <summary> Cache of the materials we're modifying. Cache is kept so they can be freed at the end of the component's lifespan. </summary>
private Material[] m_spriteMaterialsCached;
/// <summary> We also store the shared materials, so we can re-assign them for use on death. This keeps a reference to the non-instanced copy everyone else is using. </summary>
private Material[] m_spriteSharedMaterialsCache;
private IEnumerator m_flashDurationEnumerator;
private bool m_isHighlighted;
private void Awake()
{
// Get a copy of the SpriteRenderer's material and cache it so that when we flash,
// we don't cause all things using that material to flash. We will clean this up
// in OnDestroy.
m_spriteSharedMaterialsCache = m_sprite.sharedMaterials;
m_spriteMaterialsCached = m_sprite.materials;
}
public void Flash(int numTimes = 1, float delay = 0f)
{
if (m_flashDurationEnumerator != null)
StopCoroutine(m_flashDurationEnumerator);
m_flashDurationEnumerator = FlashInternal(numTimes, delay);
StartCoroutine(m_flashDurationEnumerator);
}
public void StopFlashing()
{
StopCoroutine(m_flashDurationEnumerator);
m_flashDurationEnumerator = null;
// Ensure we're off, no matter the previous state of the flash.
SetFlash(false);
}
private IEnumerator FlashInternal(int numTimes, float delay)
{
// Make sure we turn the flash off incase we're interrupting an old flash.
SetFlash(false);
yield return new WaitForSeconds(delay);
// Iterate twice the length of times - that way numTimes is "how many times is it turned on", not "how many times does it flip".
for (int i = 0; i < numTimes * 2; i++)
{
SetFlash(!m_isHighlighted);
yield return new WaitForSeconds(FlashRate);
}
// Ensure we end on off state
SetFlash(false);
}
private void SetFlash(bool makeSpriteWhite)
{
// Early out if we're asked to achieve the state we're already at
// so we skip on setting the material property.
if (m_isHighlighted == makeSpriteWhite || m_spriteMaterialsCached == null)
return;
for (int i = 0; i < m_spriteMaterialsCached.Length; i++)
m_spriteMaterialsCached[i].SetFloat("_FlashAmount", makeSpriteWhite ? 1f : 0f);
m_isHighlighted = makeSpriteWhite;
}
private void OnDestroy()
{
if (m_spriteMaterialsCached != null)
{
for (int i = 0; i < m_spriteMaterialsCached.Length; i++)
Destroy(m_spriteMaterialsCached[i]);
m_spriteMaterialsCached = null;
// Tell the renderer to use the shared materials again so it doesn't disappear.
m_sprite.sharedMaterials = m_spriteSharedMaterialsCache;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment