6
\$\begingroup\$

What is the most efficient way of making two sided sprites in Unity's new 2D tools? I'm looking to make playing cards with a backside and a front side.

enter image description here

\$\endgroup\$
4
  • 1
    \$\begingroup\$ All of the cards have the same backing? Why not just make one game object of the back of the card and then instantiate that object in place of the actual numbered card? Get what I'm saying? \$\endgroup\$
    – Savlon
    Feb 27 '14 at 5:43
  • 1
    \$\begingroup\$ Another way would be to add an animation state to the card object and switch sprite when a function is called... Example: have an animation that shows the 2hearts face and set that as the default sprite... Then create another animation which has the backface of the card as it's sprite... Then create a method to "flip" the card which changes the animation state from the face to the back... \$\endgroup\$
    – Savlon
    Feb 27 '14 at 7:33
  • \$\begingroup\$ @Savlon Yes, the animation flipping is one of the ideas I had. Since Y-axis at 90 degress makes the sprite invisible so then you can swap the sprite. \$\endgroup\$
    – Esa
    Feb 27 '14 at 7:41
  • 1
    \$\begingroup\$ I uploaded an example for you... check out youtu.be/uiVjzjQwJD4 \$\endgroup\$
    – Savlon
    Feb 27 '14 at 8:02
8
\$\begingroup\$

I did this successfully by rotating the sprite to 90 degrees on the Y-axis, then changing the sprite texture and finally rotating it back again.enter image description here

while(turningCard)
{
    transform.rotation = Quaternion.Slerp(startRotation, endRotation, rotateTime);

    if (CheckIfAngleBigEnough())
    {
        ChangeSprite();

        ChangeRotationDirection();
    }

    yield return null;

}
\$\endgroup\$
1
\$\begingroup\$

Either two sprites backing together, or a custom shader with no Backface culling could be the way to go, you could use a mod of the original sprite shader which is here : Unity Built-in Shaders (select the last version and you should find them in the same order as in the menu)

I did a shader once with a different texture on each side, with the same vertex count but i'm not close to my code right now.

EDIT : If you go for the custom shader dont forget to create a material and associate it with your sprites. I just realized by the way that there could be an issue with the fact that the Sprite renderer accepts only one texture, but you could trick it by making a texture with the front and back on the same texture, and then offsetting your UV's to match the correct positions.

\$\endgroup\$
1
\$\begingroup\$

I gave a quick try(infact took some time to get used to shader lab syntax ;) as i was trying after quite some time).

Let me know if this shader works for you.

Basically checking the frag color by sign value of dot product of view direction and normal of the vertex. Btw, I set the culling to off.

Thanks for letting me trying this out. Very happy with the output ^_^ . I'm aware of doing without shader but thought of giving this a try with shader.

Sorry for replying abit late to your post.

Link : http://pastebin.com/8dKBzsY6

Update: Here is the explanation of the code. This is infact how Back-face culling works. The Dot product between The camera view direction and the vertex normal will tell which way the vertex is oriented. Whether its away from camera or towards the camera.

Dot product value of those two vectors goes negative if the vectors are away from each other.

So , the same math is used to find out which texture we need to show.

In the code, I took two texture samples (_FirstTex,_SecondTex) as properties.

Vertex Shader

1) First we need to convert vertex co-ordinate which is in object space to Clip Space.

2)Next we use world View space direction(_WorldSpaceCameraPos) provided by unity cg includes(UnityCG.cginc,UnityShaderVariables.cginc) and normalize it. (Infact there is no real importance of normalising here as we just need sign of dot product.)

3)We then need to convert vertex normal to world space.(Please check the comment there for converting to same co-ordinate system). We can do the other way as well(converting view direction to object space).

4)Find the dot product and save the value in color.w to pass it to fragment shader.

Fragment Shader:

1)We find out the sign of the dot product value and based on that decide which texel to fetch.

2)Return the texel color.

Let me know if you need any further clarification.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ -1 for essentially a link-only answer. Consider editing your answer to include the relevant code (so the link can't rot) as well as some explanation of the technique and why it works so you aren't just providing a code dump. \$\endgroup\$
    – user1430
    Mar 5 '14 at 5:11
  • \$\begingroup\$ Indeed, the effort is appreciated, but the answer doesn't fit as it is. \$\endgroup\$
    – House
    Mar 5 '14 at 5:30
  • \$\begingroup\$ Sure Josh. will explain further. Thankyou. @Byte: You meant the answer is not answering the question :| ? \$\endgroup\$
    – Ayyappa
    Mar 5 '14 at 6:04
  • \$\begingroup\$ Nope, just agreeing with Josh. It's great that you've answered, but the format needs to be fit to this site. \$\endgroup\$
    – House
    Mar 5 '14 at 6:08
  • \$\begingroup\$ :) will edit it today for sure. Thanks for the feedback! \$\endgroup\$
    – Ayyappa
    Mar 5 '14 at 6:52
1
\$\begingroup\$

The answer by @Ayyappa helped me greatly. Here's an updated and working implementation of the suggested shader, which will enable you to set separate textures for each side of a quad-based card, and a Color to either tint or fade the card:

Shader "Card" 
{
    Properties
    {
        _Color ("Color", Color) = (0, 0, 0, 1)
        _FrontTex ("Front Texture", 2D) = "white" {}
        _BackTex ("Back Texture", 2D) = "white" {}
    }

    SubShader
    {
        Tags 
        { 
            "Queue" = "Transparent"
            "RenderType" = "Transparent"
        }

        Cull Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 3.0

            #include "UnityCG.cginc"

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

            float4 _Color;
            sampler2D _FrontTex;
            sampler2D _BackTex;
            float4 _FrontTex_ST;
            float4 _BackTex_ST;

            v2f vert(appdata_base v) 
            {
                v2f o;

                o.vertex = UnityObjectToClipPos(v.vertex);
                o.texcoord = v.texcoord;

                return o;
            }

            fixed4 frag(v2f i, fixed facing : VFACE) : SV_TARGET 
            {
                if (facing > 0)
                    return tex2D(_FrontTex, i.texcoord) * _Color;
                else
                    return tex2D(_BackTex, i.texcoord) * _Color;
            }

            ENDCG
        }
    }
}

GitHub Gist snippet

\$\endgroup\$
2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .