Shader HLSL | Teleport Effect Shader


Ah yes, now for another fun shader that reduced the size of all of our assets.

As we were playing around with the game we hated the idea that the character would have to walk like in Final Fantasy Tactics Advanced or Fire Emblem. This would cause our asset list to grow quite large, every unit would have a walk animation and have to be facing 4-5 different directions, yuck!

Instead, we decided to go with having each character “teleport” to each location. Here was the first iteration.


Nice! The character teleported to where he was supposed to. Seems decent right? Well I and Raul felt something was a bit off, it was too sudden and the effect seemed very dull. How do we make it more fun?

We tried some ideas with some custom art but felt that it would take too many resources to have every unit have their own teleport animation, we wanted to achieve the below effect for every unit no matter which way that unit was facing.


The shader was easy enough to make, I just returned no color for every odd x pixel to make the image look like it was in strips. The effect wasn’t quite complete, though. In the effect above the image looks like it’s getting stretched on the y-axis to simulate a teleport animation.

In code, I decided to stretch the y-axis myself. But now I couldn’t apply this shader and the shader I had originally used for the sprite, so I added a “ghost” object sprite that is set active when the AI or Player is trying to move, the ghost sprite is just an object with a sprite renderer that takes the current sprite from the moving object.

The effect turned out like this.


Here’s the final shader:

Shader "Sprite/Teleport" 
	  	_MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _PixelsPerUnit("Pixels Per Unit", Float)= 16

        	"RenderType" = "Transparent" 

        Cull Off
        Lighting Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0
            #include "UnityCG.cginc"

             sampler2D _MainTex;
             float4 _MainTex_ST;
             float4 _MainTex_TexelSize;
             float4 _Color;
             float _PixelsPerUnit;

            float4 AlignToPixelGrid(float4 vertex)
				float4 worldPos = mul(unity_ObjectToWorld, vertex);

				worldPos.x = floor(worldPos.x * _PixelsPerUnit + 0.5) / _PixelsPerUnit;
				worldPos.y = floor(worldPos.y * _PixelsPerUnit + 0.5) / _PixelsPerUnit;

				return mul(unity_WorldToObject, worldPos);

			struct v2f 
                float4  pos : SV_POSITION;
                float2  uv : TEXCOORD0;

            v2f vert (appdata_base IN)
                v2f OUT;

                float4 alignedPos = AlignToPixelGrid(IN.vertex);

                OUT.pos = mul (UNITY_MATRIX_MVP, alignedPos);
                OUT.uv = TRANSFORM_TEX(IN.texcoord, _MainTex);

                return OUT;

            fixed4 frag(v2f IN) : SV_Target
           		float2 texSize =;
            	fixed4 col = fixed4(0,0,0,0);

            	float2 vpos = texSize  * IN.uv;

            	if ( vpos.x % 2.0 >= 1.0 )
            		col = tex2D(_MainTex, IN.uv) * _Color;

            	return col;

	FallBack "Diffuse"

It has an extra pixel per unit code for displaying pixel perfect sprites that you may or may not want to take out 🙂

Hope you enjoy your day! 🙂

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s