Make 2D sprites glow?

I’ve tried a million things and can’t seem to get the simple effect of making my sprites glow. I followed a tutorial to make a a glowing shader but it turned out it would only work on 3D objects. I found a script to put on the camera that makes everything glow from unity’s built in assets, but can’t make it only effect a specific object. Does anyone know how to either make a shader meant for 3D work on sprites, make the camera glow effect script effect only specific objects, or have any other ideas on how I can achieve a glowing effect on a sprite?? I’m looking for an effect similar to that in games like geometry wars or Ori and the Blind Forest where objects glow.

If you’re curious, I need it so I can make certain body-parts of enemies glow to indicate to the player which parts are that enemy’s weak points. Actually, if anyone has a better idea than making them glow I’d be open to suggestions :slight_smile: Because this glow thing is starting to be more trouble than it’s worth. I tried particle effects but can’t figure out how to make them spawn based on the shape of an object (only in squares or spheres).

Thanks for any advice!!

Here is the shader we copied from Unity’s standart sprite shader and modified to shine certain location of sprite.

You can change ShineLocation and ShineWidth to make an shine animation through c# scripts.

It may help you…

//Kaan Yamanyar,Levent Seckin
Shader "Sprites/ShinyDefault"
{
	Properties
	{
		[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
		_Color("Tint", Color) = (1,1,1,1)
		_ShineLocation("ShineLocation", Range(0,1)) = 0
		_ShineWidth("ShineWidth", Range(0,1)) = 0
		[MaterialToggle] PixelSnap("Pixel snap", Float) = 0
	}

		SubShader
	{
		Tags
	{
		"Queue" = "Transparent"
		"IgnoreProjector" = "True"
		"RenderType" = "Transparent"
		"PreviewType" = "Plane"
		"CanUseSpriteAtlas" = "True"
	}

		Cull Off
		Lighting Off
		ZWrite Off
		Blend One OneMinusSrcAlpha

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ PIXELSNAP_ON
#include "UnityCG.cginc"

	struct appdata_t
	{
		float4 vertex   : POSITION;
		float4 color    : COLOR;
		float2 texcoord : TEXCOORD0;
	};

	struct v2f
	{
		float4 vertex   : SV_POSITION;
		fixed4 color : COLOR;
		float2 texcoord  : TEXCOORD0;
	};

	fixed4 _Color;

	v2f vert(appdata_t IN)
	{
		v2f OUT;
		OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
		OUT.texcoord = IN.texcoord;
		OUT.color = IN.color * _Color;
#ifdef PIXELSNAP_ON
		OUT.vertex = UnityPixelSnap(OUT.vertex);
#endif

		return OUT;
	}

	sampler2D _MainTex;
	sampler2D _AlphaTex;
	float _AlphaSplitEnabled;
	float _ShineLocation;
	float _ShineWidth;

	fixed4 SampleSpriteTexture(float2 uv)
	{
		fixed4 color = tex2D(_MainTex, uv);

#if UNITY_TEXTURE_ALPHASPLIT_ALLOWED
		if (_AlphaSplitEnabled)
			color.a = tex2D(_AlphaTex, uv).r;
#endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWED

		
	
		
		float lowLevel = _ShineLocation - _ShineWidth;
		float highLevel = _ShineLocation + _ShineWidth;
		float currentDistanceProjection = (uv.x + uv.y) / 2;
		if (currentDistanceProjection > lowLevel && currentDistanceProjection < highLevel) {
			float whitePower = 1- (abs(currentDistanceProjection - _ShineLocation ) / _ShineWidth);
			color.rgb +=  color.a * whitePower;
		}
		
		return color;
	}

	fixed4 frag(v2f IN) : SV_Target
	{
		fixed4 c = SampleSpriteTexture(IN.texcoord) * IN.color;
		c.rgb *= c.a;

	return c;
	}
		ENDCG
	}
	}
}

Based on Kaan Yy’s Answer. I have wrote a utils function to make it working more convenient.
Here it is:

public static void shineObject (GameObject obj, float width, float duration)
{
	var mono = obj.GetComponent<MonoBehaviour>();
	if( mono != null) {
		// change material
		Material mat = Resources.Load ("Materials/ShineMaterial", typeof(Material)) as Material;

		var render = obj.GetComponent<Renderer> ();
		if (render != null) {
			render.material = mat;
		} else {
			var img = obj.GetComponent<Image> ();
			if (img != null) {
				img.material = mat;
			} else {
				Debug.LogWarning ("cannot get the render or image compoent!");
			}
		}

		mat.SetFloat("_ShineWidth", width);

		// start a coroutine
		mono.StopAllCoroutines ();
		mono.StartCoroutine (shineRoutine (mat, duration));
	} else {
		Debug.LogWarning ("cannot find MonoBehaviour component!");
	}
}

static IEnumerator shineRoutine (Material mat, float duration)
{
	if( mat != null ) {
		float location = 0f;
		float interval = 0.04f;
		float offsetVal = interval / duration;
		while(true) {
			yield return new WaitForSeconds (interval);
			mat.SetFloat("_ShineLocation", location);
			location += offsetVal;
			if (location > 1f) {
				location = 0f;
			}
		}
	} else {
		Debug.LogWarning ("there is no material parameter!");
	}
}

It works both on a UI Image or a Sprite game object. But the game object must have a “MonoBehaviour” component to use the StartCoroutine function.

The result:
77301-result.png

You need to use an emissive shader, and supply a suitable emission map: Unity - Manual: Material parameters

I changed firestoke code into this and it’s working for me perfectly, and as an absolute amateur I have to say that I am very grateful for the main Shader code and of course firestoke script. I think if you try and work on the code a bit, you can personalize it to fit your needs. here is the code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ShineMaterialScript : MonoBehaviour 
{
    public float width;
    public float duration;
    public float m_Delay;
    //delay is the time between each shine;

    void Start () 
    {
        Material mat = Resources.Load("Materials/Environment/Shiny", typeof(Material)) as Material;
        // either you have to have this exact address in your resource folder or change it to where ever 
        // you saved your shiny material, remember that the "Shiny" last bit here is just an example I used for
        // the material name, you have to use the name which you have given your material with shiny shader on it.
        // Take note that you have to add a "Resourse" folder in your assets folder in order for the script to work.

        Renderer renderer = gameObject.GetComponent<Renderer>();
        if (renderer != null)
        {
            renderer.material = mat;
        }
        else
        {
            Image img = gameObject.GetComponent<Image>();
            if (img != null)
            {
                img.material = mat;
            }
            else
            {
                Debug.LogWarning("Cannot get the Renderer or Image component!");
            }
        }

        mat.SetFloat("_ShineWith", width);
        StopAllCoroutines();
        StartCoroutine(shineRoutine(mat, duration, m_Delay));
	}

    static IEnumerator shineRoutine(Material mat, float duration, float m_Delay)
    {
        if (mat != null)
        {
            float location = 0f;
            float interval = 0.04f;
            float offsetVal = interval / duration;
            while (true)
            {
                yield return new WaitForSeconds(interval);
                mat.SetFloat("_ShineLocation", location);
                location += offsetVal;
                if (location > 1f)
                {
                    yield return new WaitForSeconds(m_Delay);
                    location = 0f;
                }
            }
            
        }
        else
        {
            Debug.LogWarning("There is no Material parameter!");
        }
    }
}