【Unity】スプライト画像を白くする処理をShaderGraphで行う方法

スプライトを白くさせる方法 Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「スプライト画像を白っぽくさせたい!」

「ダメージを受けたときにスプライトを一瞬だけ白くさせたい!」

というお悩みの方に向けた内容となっています。

Unityでは、スプライト画像の色を変更したい場合、SpriteRendererColorプロパティで変更することができます。

しかし、Colorプロパティのデフォルト色がすでに白に設定している場合は、それ以上白くすることができないため、通常はシェーダーというプログラムを書くことで実現できます。

ただ、僕自身シェーダーをほとんど扱ったことが無いため、難しそうと思っていたのですが、UnityのShaderGraphというツールを使うことで、簡単にスプライトを白くするシェーダーを作ることができました。

そこでこのページでは、UnityのShaderGraphを使って、スプライト画像を白くする方法についてまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

スプライト画像を白くする処理をShaderGraphで実装する方法

まず、今回実装したい内容として、以下のキャラクターとなるオブジェクトがダメージを受けた時に、一瞬だけ白くなってすぐに戻るという処理を作っていきます。

現状では、SpriteRendererのColorプロパティが、以下のように白色になっているため、これ以上白くさせるということができません。

そこで、冒頭でも記述していたShaderGraphが登場してきます。

このShaderGraphとは、シェーダーを視覚的に制作できるツールとなっていて、初心者でも簡単にシェーダーを作ることができます。

そもそもシェーダーというのは、オブジェクトの見た目を決めているプログラムのことで、今回はオブジェクトに白色を上書きして、オブジェクトを白くさせるというプログラムをShaderGraphで作っていきます。

なお、全体の大きな流れとして、

  • ShaderGraphでシェーダーを作成する
  • 新しいマテリアルにシェーダーをセットする
  • オブジェクトにマテリアルを紐づける
  • スクリプトからマテリアルのパラメーターを変更する

で解説していきますが、ほとんどは①のシェーダーの作成部分の説明となります。

ShaderGraphでシェーダーを作成する

まずは、今回のメインともなるShaderGraphを使ってシェーダーを作成していきます。

ここでは、ShaderGraphを使うのが初めての方でも分かるように、一からゆっくりと説明していきます。

なお、作業としては、

  1. ShaderGraphのアセットを作成する
  2. ShaderGraphのウィンドウを開く
  3. プロパティを定義していく
  4. SampleTexture 2Dのノードを作成する
  5. Colorのノードを作成する
  6. Blendのノードを作成する
  7. ブレンドした色をFragmentへ入力する

上記の7つの作業を行っていきます。

ShaderGraphのアセットを作成する

最初に、ShaderGraphのアセットを作成していきます。

プロジェクトウィンドウの+ボタンから、「ShaderGraph」の中の「URP」を選択します。

URPとはユニバーサルレンダーパイプラインの略で、画面にオブジェクトを描画するための一連の処理を行っているものです。
プロジェクトの作成時に「Universal 2D」もしくは「Universal 3D」を選択した場合は、このURPがレンダリングパイプラインに設定されます。

この中で、2Dのスプライト画像用のシェーダーを作成できるものとして、以下の3つがあります。

  • Sprite Unlit Shader Graph:ライトの影響を受けないシェーダーを作れる
  • Sprite Lit Shader Graph:ライトの影響を受けるシェーダーを作れる
  • Sprite Custom Lit Shader Graph:ライトの影響を受けるカスタムシェーダーを作れる

名称の中にある「Unlit」「Lit」ライトによる影響を受けるかどうかを決めていて、例えばオブジェクトに影や光の反射などを表示させるかどうかを決めています。

また、カスタムシェーダーというのは、通常のシェーダーでは表現できない独自の描画表現を加えるような場合に使います。

今回は、ライトの影響を受けなくていいので、「Sprite Unlit Shader Graph」を選択しています。

すると、以下のようなShaderGraphのアセットが作成されるので、分かりやすい名前に変更しておきます。

ここでは、「MyShaderGraph」という名前にしてみました。

ShaderGraphのウィンドウを開く

先ほど作成したShaderGraphのアセットをダブルクリックすると、以下のようなShaderGraphのウィンドウが表示されます。

この画面を使って、シェーダーを作成していくことになります。

ちなみに、ShaderGraphの編集画面はそのままだと使いにくいので、以下のようにタブの部分をダブルクリックして最大化しておくと良いです。

プロパティを定義していく

ShaderGraphの編集画面で、まずはプロパティを定義していきます。

ここで定義するプロパティは、後ほど紐づけるマテリアルのインスペクターウィンドウ上から値を設定したり編集したりすることができます。

今回は、スプライト画像に白色を上書きするという処理を作りたいので、スプライトの画像データとなるTexture2D型と、上書きする色の不透明度を決めるFloat型の2つのプロパティを定義していきます。

プロパティを定義する際は、画面の左上の+ボタンを押して、

表示された項目の中から、今回定義するTexture2DFloatを選択していきます。

ただ、プロパティを定義する際にいくつか注意点があります。

Texture2D型のプロパティ

まず、Texture2D型のプロパティは、名前を必ず「MainTex」にしておきます。

これは、作成したMainTexを選択してみると、右側のGraph Inspectorの中のReferenceという項目に自動的に「_MainTex」と入っているのが分かると思います。

この「_MainTex」というのが、マテリアルのメインテクスチャを参照することができるプロパティ名となっていて、Unity側で決められている名称です。

つまり、この名前でプロパティを定義しておくことで、インスペクターウィンドウからテクスチャをわざわざ指定しなくても、そのマテリアルを設定したオブジェクト(スプライト画像)のテクスチャを自動で取得することができます。

そのため、Texture2D型のプロパティ名はMainTexにしておきます。

Float型のプロパティ

次に、Float型のプロパティですが、こちらは名前の指定は特に無く、ここでは「WhiteValue」としています。

このWhiteValueは、0~1までの間で値を設定できるようにしたいので、Graph InspectorからModeを「Slider」に選択して、Minを「0」、Maxを「1」にしておきます。

ちなみに、WhiteValueは上書きする白色の不透明度を決めることになるので、最小の0にしたら透明な白色が上書きされるので何も変更されず、この数値を引き上げることで白色の不透明度が上がりより白く表示されることになります。

そのため、通常時は白くさせる処理を行いたくないので、Default Valueは「0」のままにしておきます。

SampleTexture 2Dのノードを作成する

プロパティが定義できたら、「SampleTexture 2D」のノードを作成していきます。

このSampleTexture 2Dノードは、先ほど取得したTexture2Dを入力して、Vector4の色(RGBA)を出力することができます。

もう少し簡単に言えば、スプライト画像の標準の色合いを取得するために使います。

ちなみに、ノードとは個々の要素を表すもので、ShaderGraphではこのノードを繋いでシェーダーのプログラムを作成していきます。

ノードを作成する場合は、画面の何も無いところで、右クリックして「Create Node」を選択、

「SampleTexture 2D」を検索で探して、

ダブルクリックしてあげることで以下のように追加できます。

ノードが作成できたら、まず入力するTexture2Dを以下の部分に繋いでいく処理を作ります。

このTexture2Dには、プロパティで定義したMainTexを設定したいので、左のMainTexをドラッグ&ドロップで以下のように持ってきてあげます。

そして、MainTexの右の赤丸部分から、SampleTexture 2DのTextureの部分までをマウスでドラッグすることで、繋ぐことができます。

これで、スプライトの画像データ(テクスチャ)から標準となる色を出力することができるようになりました。

Colorのノードを作成する

次に、スプライトに上書きするための色を指定するColorのノードを作成していきます。

このColorのノードで、白色をセットしてあげることになります。

先ほどと同様に、画面の何もないところで右クリックして「Create Node」を選択、「Color」をダブルクリックしてあげます。

すると、以下のようにカラーピッカーで色を指定することができるので、白色に設定しておきます。

今回は、スプライトを白色にしたいので上記の設定を行っていますが、別の色を指定しても問題ありません。
また、ここでは行っていませんが、Color型のプロパティを定義しておくことで、インスペクターウィンドウから色を指定できるようになるので便利です。

Blendのノードを作成する

次に、Texture 2Dの色にColorで指定した白色を上書きしたいので、Blendのノードを作成していきます。

Blendのノードは、簡単に言えば2つの色を混ぜることができるもので、基準となる「Base」とブレンドさせたい「Brend」の色を入力して、それを混ぜたものを出力することができます。

これまでと同様に、右クリックして「Create Node」を選択し、「Blend」を検索してダブルクリックします。

まず、Modeという項目で、どのように色をブレンドさせるかを指定することができるので、上書きとなる「Overwrite」を指定します。

次に基準の色となるBaseは、スプライトのテクスチャの標準色を指定するので、SampleTexture 2Dノードから出力されるRGBAの色を繋いで入力します。

また、ブレンドの色となるBrendは、Colorノードで作成した白色を繋いで入力します。

あとは、Opacityブレンドする色に対しての不透明度を表しているので、WhiteValueのプロパティをドラッグ&ドロップで持ってきて、このOpacityに繋げてあげます。

ここまでで、以下のようなShaderGraphの編集画面になりました。

ブレンドした色をFragmentへ入力する

色をブレンドできたら、そのブレンドされた色をFragment(フラグメント)シェーダーへ入力してあげます。

このFragmentシェーダーとは、簡単に言えば画像描画における色を決める(塗る)作業を行う部分になっていて、このFragmentにブレンドされた色を渡してあげることで、オブジェクトに塗る色を変更させることができます。

先ほどのBlendノードから出力された色を、Fragmentの「BaseColor」という部分に繋げて入力します。

そして、SampleTexture2Dで出力される透過度を表す「A」を、同じくFragmentで透過度を決める「Alpha」に繋げて入力してます。

これで、スプライトのテクスチャに白色で上書きした色を、Fragmentに渡すことができたので、ShaderGraphでの作業は完了となります。

なお、以下が最終的な完成形の画面となります。

最後に、忘れずに左上の部分から保存しておきます。

新しいマテリアルにシェーダーをセットする

ShaderGraphでシェーダーを作成できたら、今度はマテリアルに作成したシェーダーをセットしていきます。

シェーダー見た目を決めるプログラムであるのに対して、マテリアルはシェーダーにパラメーターを渡して、オブジェクトの見た目を変更できるという役割を持っています。

もう少し簡単に言えば、シェーダーというのは直接オブジェクトに紐づけることはできず、マテリアルを介してそのオブジェクトの見た目を決めていく必要があります。

マテリアルの作成は、プロジェクトウィンドウの+ボタンから「Material」を選択します。

ここでは、「WhiteColorMat」という名前にしてみました。

マテリアルにシェーダーをセットするのは簡単で、先ほど作成したShaderGraphのアセットをマテリアルにドラッグ&ドロップしてあげれば紐づけすることができます。

マテリアルの「Shader」の項目に、以下のように作成したShaderGraphが紐づいていれば問題ありません。

オブジェクトにマテリアルを紐づける

マテリアルが作成出来たら、対象となるオブジェクトに紐づけていきます。

オブジェクトにマテリアルを紐づけるのも、ドラッグ&ドロップで行うことができます。

紐づけができたらオブジェクトを選択して、インスペクターウィンドウの下の方のマテリアルの中に、ShaderGraphで作成したWhiteValueのプロパティを探してみます。

そして、値をスライドで変更してみます。

上記のように、スライドするとオブジェクトに少しずつ白色が足されていき、値が1になると完全に真っ白になれば問題ありません。

一旦、WhiteValueの値を0に戻しておきます。

スクリプトからマテリアルのパラメーターを変更する

あとは、WhiteValueのプロパティの値をスクリプトから変更してあげれば完成です。

オブジェクトに対して、以下のスクリプトを紐づけておきます。

using UnityEngine;
using System.Collections;   // コルーチンを使用するため明記

public class EnemyController : MonoBehaviour
{
    Material material;  // オブジェクトのマテリアルを取得する変数を宣言

    void Start()
    {
        material = GetComponent<Renderer>().material;   // Rendererコンポーネントからマテリアルを取得する処理
    }

    // 当たり判定を検知
    void OnTriggerEnter2D()
    {
        StartCoroutine(WhiteChange());  // コルーチンを開始する
    }

    IEnumerator WhiteChange()
    {
        material.SetFloat("_WhiteValue", 0.5f); // WhiteValueの値を0.5に変更する
        yield return new WaitForSeconds(0.05f); // 0.05秒処理をストップする
        material.SetFloat("_WhiteValue", 0f);   // WhiteValueの値を0に戻す
    }
}

まず、マテリアルからプロパティの値を変更する必要があるので、10行目でGetComponentメソッドを使って、Rendererコンポーネントからmaterialを取得しています。

次に、14行目で他のオブジェクトとの当たり判定をOnTriggerEnter2Dメソッドで作り、その中の16行目でWhiteChangeというコルーチンを開始する処理を行っています。

なお、ここでは当たり判定を簡単に作ってしまっていますが、実際には相手のコライダー情報で当たり判定を行うかどうかを記述していきます。

WhiteChangeのコルーチンを定義した中の21行目と23行目で、materialSetFloatメソッドを使ってfloat型であるWhiteValueのプロパティの値を変更しています。

注意点として、プロパティ名はWhiteValueですが、スクリプトから処理を記述する際はShaderGraphのReferenceの項目に記載してある「_WhiteValue」の方になります。

これでゲームを実行してこのオブジェクトに別のオブジェクトを当ててみると、

当たった瞬間だけ、白色に変化するという処理を作ることができました。

まとめ

このページでは、Unityでスプライト画像を白くする方法について、ShaderGraphで実装するやり方をまとめていきましたが、いかがでしたでしょうか?

Unityでスプライト画像を白くする処理を作る場合、ShaderGraphを使うことで簡単に白色に変更することができます。

具体的には、ShaderGraphを使って白色を上書きさせたシェーダーを作成し、それをマテリアルにセットして使用することで実装できます。

シェーダーを自作するのは大変ですが、ShaderGraphは視覚的に使えて簡単に作成することができるので便利です。

最後までお読みいただきまして、ありがとうございました!

コメント