Chapter 34無料公開

🍍 SVG素材を使った線のアニメーション【Adobe Illustrator】

このチャプターでは、SVG素材から作成したテクスチャ素材を利用して、以下のような線のアニメーションを作る方法を紹介します。

サンプルデータ

線のアニメーションのサンプルデータはGitHubにて公開中です

https://github.com/rngtm/ShaderGraphCookBookSample

使用するツール

Adobe Illustrator 2020

素材の準備

まず最初に、SVGファイルから以下のようなグラデーション付きの素材を作成し、Unityへインポートします。

1. SVG素材のインポート (Illustrator)

SVGファイルをAdobe Illustratorにインポートします。

OKマークのSVGファイルは https://ikonate.com/ からお借りしました。

2. グラデーションをつける (Illustrator)

グラデーションパネルにて「パスに沿ってグラデーションを適用」を選択し、
パスに沿ったグラデーションを設定します。

Unity上では、黒い部分から白い部分へ向かって白塗りが流れていくようなアニメーションになります。

3. 素材のエクスポート (Illustrator)

アートボードの名前は 「ok-ring」としておきましょう。

ファイル -> 書き出し -> スクリーン用に書き出し から素材を書き出して、Unityへ持っていきます。

4. 素材のインポート (Unity)

ok-ringのテクスチャ設定にて、sRGBのチェックを外します。

sRGBが有効だと、テクスチャをサンプリングした際に逆ガンマ補正がかかってしまい、アニメーションに不自然な緩急が入るようになってしまいます。

テクスチャを表示してみる (Unity)

先ほど作成した、ok-ring.png をShaderGraphで出力してみます。
以下のようなShaderGraphを組んでみてください。

結果

OKマークが表示されます。

アニメーション用ShaderGraphの作成

次にアニメーションを行うためののShaderGraphを作成します。

プロパティの作成

アニメーションの進行度を表すFloatプロパティ Progress を作成します。
Progress = 0 はアニメーションの最初、Progress = 1 はアニメーションの最後 といった意味の実数値です。

ShaderGraphの作成

StepやMultiplyノードを使って、以下のようなShaderGraphを組みます。

結果

マテリアル上でProgressの値を変化させると、以下のように線が削れていきます。

線が削れる表現としては良さそうなのですが、アルファの削り部分がところどころ汚くなってしまいます。

Smoothstepノードを利用したアニメーション

Stepの代わりにSmoothstepノードを利用することで、アルファを0から1へゆるやかに削ることができます。

結果

マテリアル上でProgressの値を変化させると、ゆるやかに線が削れます。
削り部分の汚さは目立ちにくくなりました。

調整 : Progress = 1 でアルファを完全に削りきる

Smoothstepを利用した削り表現ですが、Progress = 1にした場合にアルファが削りきれずに残ってしまっています。

Progress = 1 をアニメーションの終わりとして、アルファは完全に削れてくれた方が都合が良いです。

Progressの範囲変換

Progress =0, 1 でのアルファ値はグラフは以下のようになります。
アルファ値は黄色い線で表しています。

Progress = 0 の時はアルファは常に1ですが、Progress = 1 の時はアルファが削り切れずに残ってしまっています。

Remapを利用した範囲変換

ProgressにRemapノードを接続することで、Progressがとる数値の範囲を変換することができます。

結果

Progress = 1 の時にアルファが完全に削り切れています。

ShaderGraph全体

今回作ったShaderGraphは以下のようになっています。

おまけ : AnimationClipを使ってアニメーションさせる

UIマテリアルのパラメータは、AnimationClipを使ってアニメーションさせることができません。

C#スクリプトを利用したアニメーション

以下の方法を取ることで、AnimationClipから削りアニメーションをコントロールすることができます。

  1. C#スクリプト(コンポーネント)を利用して、マテリアルの _Progress プロパティを毎フレーム更新する
  2. Animation Clipでコンポーネントのパラメータを変化させる

Materialのプロパティ_Progressを更新するC#スクリプト

以下のコンポーネントは、Image(RawImage)にアタッチされているマテリアルのプロパティ_Progressを更新するスクリプトです。

UIMaterialProgress.cs
namespace ShaderGraphCookBook
{
    using UnityEngine;
    using UnityEngine.UI;

    [ExecuteAlways]
    [RequireComponent(typeof(MaskableGraphic))]
    public class UIMaterialProgress : MonoBehaviour
    {
        [SerializeField, Range(0f, 1f)] private float progress = 0f; // マテリアルに渡す_Progressの値
        private Image _image = null;
        private RawImage _rawImage = null;
        private readonly int _progressId = Shader.PropertyToID("_Progress"); // シェーダープロパティのReference名

        private void Start()
        {
            Initialize();
        }

        /// <summary>
        /// 描画フレームで呼ばれる
        /// </summary>
        void Update()
        {
            var material = GetMaterial();
            if (material != null)
            {
                // マテリアルのプロパティ _Progress を更新
                material.SetFloat(_progressId, progress);
            }
        }

        /// <summary>
        /// 初期化処理
        /// </summary>
        void Initialize()
        {
            var component = GetComponent<MaskableGraphic>();
            _image = component as Image;
            _rawImage = component as RawImage;
        }

        /// <summary>
        /// Imageにアタッチされているマテリアルの取得
        /// </summary>
        Material GetMaterial()
        {
            if (_image != null) return _image.material;
            if (_rawImage != null) return _rawImage.material;
            return null;
        }
    }
}

結果

Imageにアタッチして、コンポーネントのProgressというスライダーを動かすとマテリアルの_Progressも変化します。

AnimationClipを使ったアニメーション

AnimationClipからコンポーネントのProgressを変化させると、UIがアニメーションします。

同じマテリアルを複数のUIにアタッチしている場合、すべてのUIが同時に動いてしまいます。
今回のスクリプトは、あくまで参考程度に利用ください。