LoginSignup
2
0

More than 1 year has passed since last update.

Unity Sheet Animation Shader

Last updated at Posted at 2021-10-17

概要

Unity上でSheet Animationを使ったシェーダーの例です。
Sheet Animationを使うことで板ポリ1枚とテクスチャ1枚でアニメーションを表現することができます。
連番アニメーションはAnimatorを用いることで実装することもできますが、Shaderを使った方が使用するコンポーネントも少なく軽量です。
また、アニメーションの際にMaterialを変化させないので、MaterialのInstance化を防ぎバッチを効かせることができます。

fire.gif

Unity Sheet Animation Shader Graph版

ソースコード

Shader "Unlit/SheetAnimation"
{
    Properties
    {
        [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
        _MainColor("Main Color",Color) = (1,1,1,1)
        _Row("Row",int) = 4
        _Column("Column",int) = 4
        _Speed("Speed",float) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _MainColor;

            uint _Row;
            uint _Column;
            float _Speed;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //全てのコマ数を計算
                uint cells = _Row * _Column;
                //時間にSpeedを掛けて小数点以下だけを返すことで0~1を生成
                fixed process = frac(_Time.y * _Speed);
                //index=どのコマを指しているか
                uint index = process * cells;

                //1コマ当たりのUVサイズを計算
                float invRow = 1.0 / (float)_Row;
                float invColumn = 1.0 / (float)_Column;

                float2 tiling = float2(invRow,invColumn);

                //indexからどのコマに当たるかを計算する
                half x = (index % _Row) * invRow;
                //画像の左上からコマが始まるのでひっくり返している
                half y = 1 - (((index / _Row) +1) * invColumn);

                float2 offset = float2(x,y);

                //テクスチャのオフセットを適用する
                fixed4 col = tex2D(_MainTex, (i.uv * tiling) + offset);
                //色を変えられるようにする
                col *= _MainColor;

                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

解説

  • Unlit Shaderから作成を開始しています
    • 今はOpaqueになってますが、Blend Modeを変えることで半透明シェーダーとして使うこともできます
  • _Time.yの時間で変化する変数を用いて、テクスチャの表示する位置を変化させています
  • メインのテクスチャでTilingやOffsetを設定できないよう[NoScaleOffset]の属性を付与しています

    • Sheet Animationの場合はTexture全体を使うのが一般的なので、TilingやOffsetを設定する必要は無いはず
  • Sheet Animationのコマ割りの順番は、下の画像のように左上から右下に進むことを想定しています

texturetest001.jpg

  • もし順番が違う場合はoffsetを計算する部分のコードを書き換える必要が出てきます
    • 例えば左下からスタートする場合は下記のようになります
half y = ((index / _Row) +1) * invColumn;
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0