How do I set or change sprite textures based on rotation angle?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By jbskaggs

I have top down game, That I am changing to a 1/4 top down view. Created new sprite textures. Currently my object rotates and faces enemies. (I created the sprites as a 3d obj and exported the 8 pngs)

How do I instead of rotating the object change to one of the 8 direction textures that match the direction_to facing the enemy?

or would this just be easier in a 3d scene and rotate the 3d object?

Thanks.

:bust_in_silhouette: Reply From: Host32

You can create 8 animations using your sprites, and add some logic in your script to play the animation according with rotation.

So, to fix the 3D rotation of node, you can use the Billboard mode to the sprite3D. The billboard mode makes the sprite always faces the camera.

For a AnimatedSprite3D, you can open the menu “Flags” in the inspector and enable billboard.

:bust_in_silhouette: Reply From: xetaichohangpq

I’ve written a sprite shader that rotates a sprite to face the camera along the Y-axis. The rotation itself is perfectly functional, but something strange happens when the sprite is viewed from certain specific angles.

At angles where the camera’s Y rotation differs from that of the sprite’s GameObject, nothing strange happens:
BillboardShader1.png

…But when they have matching Y rotations, (in this case, both zero) the sprite vanishes at certain values of the camera’s X rotation:
BillboardShader2.png

Again, the vanishing only seems to happen (from what I can tell) when their Y rotations match, as you can see here:
BillboardShader3.png

The scale of the sprite’s Transform also plays a part in what camera angles make it vanish. I’ve gotten the sprite to disappear a few times by just fiddling with its Z scale.

I’m really puzzled as to what’s causing this. I can only assume it has something to do with how my shader does the rotating, but I can’t figure out what.

Shader Code:
Code (CSharp):
Shader “Sprites/Billboard Y Only”
{
Properties
{
[PerRendererData] _MainTex (“Sprite Texture”, 2D) = “white” {}
_Color (“Tint”, Color) = (1,1,1,1)
_ScaleX (“Scale X”, Float) = 1.0
_ScaleY (“Scale Y”, Float) = 1.0
[MaterialToggle] PixelSnap (“Pixel snap”, Float) = 0
}

SubShader
{
    Tags
    {
        "Queue"="Transparent"
        "IgnoreProjector"="True"
        "RenderType"="Transparent"
        "PreviewType"="Plane"
        "CanUseSpriteAtlas"="True"
        "DisableBatching"="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;
        };

         float4 RotateAroundYInDegrees (float4 vertex, float degrees)
             {
                 float alpha = degrees * UNITY_PI / 180.0;
                 float sina, cosa;
                 sincos(alpha, sina, cosa);
                 float2x2 m = float2x2(cosa, -sina, sina, cosa);
                 return float4(mul(m, vertex.xz), vertex.yw).xzyw;
             }

         float4 RotateAroundYInRadians (float4 vertex, float radians)
             {
                 float sina, cosa;
                 sincos(radians, sina, cosa);
                 float2x2 m = float2x2(cosa, -sina, sina, cosa);
                 return float4(mul(m, vertex.xz), vertex.yw).xzyw;
             }

        fixed4 _Color;
        float _ScaleX;
        float _ScaleY;

        v2f vert(appdata_t IN)
        {
            v2f OUT;

            IN.vertex *= float4(_ScaleX, _ScaleY, 1.0, 1.0); // Scale X and Y

            float3 camDir = mul((float3x3)unity_CameraToWorld, float3(0,0,-1));        // Camera direction
            camDir = mul((float3x3)unity_WorldToObject, camDir);                    // Put it in Object space (So object rotation won't affect it)
            camDir.y = 0.0;                                                            // Discard Y axis to make it horizontal

            float angle = acos(dot(normalize(camDir), normalize(float3(0.0, 0.0, -1.0))));    // Angle between horizontal camera direction and object forward
            if (sign(camDir.x) < 0.0) { angle *= -1; }        // Check if the angle should be negative

            OUT.vertex = UnityObjectToClipPos(RotateAroundYInRadians (IN.vertex, angle));    // Calculate rotated vertex position (And put it in Clip space)

            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;

        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

            return color;
        }

        sampler2D _CameraDepthNormalsTexture;

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

}

Source: xetaichohang