まずは作成したものからどうぞ。
はじめに
よく、RPGなどでモンスターが死亡したときに砂のように消滅するかっこいい演出をみかけますが、その演出をシェーダーで作成してみました。
開発環境
- Unity2018.3.0f2
- Windows10
- 実機動作確認
- Android Galaxy s6 edgeにて確認。
- ※iOSを持ってないためiOS未検証です。ご了承ください。
VanishingShader
こちらが今回作成したシェーダーのコードです。
消滅させるシェーダーなのでそのままVanishingShader
と名付けました。
Shader "Custom/VanishingShader"
{
Properties
{
_MainTex ("Source", 2D) = "white" {}
_StrengthX("StrengthX",Float) = 0
_StrengthY("StrengthY",Float) = 0
_Alpha("Alpha",Range(0,1)) = 1
}
SubShader
{
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Fog { Mode Off }
Tags { "Queue" = "Transparent" }
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float _StrengthX;
float _StrengthY;
float _Alpha;
float rand(float2 co)
{
return frac(sin(dot(co.xy, float2(12.9898, 78.233))) * 43758.5453);
}
fixed4 frag (v2f_img i) : SV_Target
{
float r = rand(i.uv);
float2 uv = i.uv + r * float2(_StrengthX, -_StrengthY);
fixed4 c = tex2D(_MainTex, uv );
c.a *= _Alpha;
return c;
}
ENDCG
}
}
}
解説
シェーダーコードについて解説していきます。
まずはProperties
からですが、これらプロパティたちをのちほど出てくる
コンポーネントからいじることになります。
Properties
{
_MainTex ("Source", 2D) = "white" {}
_StrengthX("StrengthX",Float) = 0
_StrengthY("StrengthY",Float) = 0
_Alpha("Alpha",Range(0,1)) = 1
}
_Source
:テクスチャを指定します。
_StrengthX
:0なら何も効果なし。 値が大きくなるほど横方向に砂化します。
_StrengthY
:0なら何も効果なし。値が大きくなるほど縦方向に砂化します。
_Alpha
:0なら透明。値が1で不透明です。
頂点シェーダー・フラグメントシェーダーの指定
#pragma vertex vert_img
#pragma fragment frag
この部分で、頂点シェーダーにvert_img
を、フラグメントシェーダーにfrag
を指定しています。
vert_img
はビルドインの頂点シェーダーです。
UnityCG.cginc
というビルドインの変数やヘルパー関数が定義されたファイル内に定義されています。
#include "UnityCG.cginc"
のように定義することで使用できるようになります。
今回はすでに定義された頂点シェーダーを使用したので、書いたシェーダーのコード量も減りましたが、
実際の定義を引用すると、このようになっています。
struct appdata_img
{
float4 vertex : POSITION;
half2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
v2f_img vert_img( appdata_img v )
{
v2f_img o;
UNITY_INITIALIZE_OUTPUT(v2f_img, o);
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.pos = UnityObjectToClipPos (v.vertex);
o.uv = v.texcoord;
return o;
}
そしてスプライトを砂と化すメイン部分がこちらです。
float r = rand(i.uv);
float2 uv = i.uv + r * float2(_StrengthX, -_StrengthY);
fixed4 c = tex2D(_MainTex, uv );
UVをランダムに(Strengthが強いほどどんどん)ズラして、
砂みたいになるのを表現しています。
randについてはこちらランダムな値を返す関数 on GLSLを参考にしました。
テクスチャ設定について
Textureの設定のWrapMode
はClamp
にしておきます。
Repeat
だと、上方に移動した砂がまた下方から表示されてきてしまうので、
見た目としておかしくなります。
マテリアルを作成する
マテリアルを作成し、シェーダーはCustom/VanishingShader
を選択します。
コントローラー
アニメーションからマテリアルのシェーダーのパラメータを操作できるようにします。
シェーダーのパラメータをアニメーションで制御できるようにするために、
コントローラーとなるコンポーネントを作成します。
using UnityEngine;
[ExecuteInEditMode]
public class VanishingShaderController : MonoBehaviour
{
[SerializeField] float strengthX = 0f;
[SerializeField] float strengthY = 0f;
[SerializeField] float alpha = 1f;
[SerializeField] Material material;
void Update()
{
UpdateMaterial();
}
void UpdateMaterial()
{
if (material == null) { return; }
material.SetFloat("_StrengthX", strengthX);
material.SetFloat("_StrengthY", strengthY);
material.SetFloat("_Alpha", alpha);
}
}
マテリアルをアタッチ
uGUIのImage
とVanishingShaderController
のMaterial
にマテリアルをアタッチします。
コンポーネントのインスペクターで露出している値をアニメーションのほうで制御してみましょう。
こんな感じでStrengthY
(もしくはX)やAlpha
を制御してやれば、調整可能です。
プロジェクトデータ
今回作成したプロジェクトをGithubに載せました。
どうぞご自由にご利用ください。
https://github.com/gingerbread4/VanishingShader
まとめ
いかがでしたでしょうか。作成したシェーダーは初歩的でシンプルながら、
スプライトが砂のように消滅する感じが出ていて、
RPGなど、モンスターが死亡する演出などに使えるのではないでしょうか。
課題
よく見ると、ちょっとImage
の上のほうで砂になったピクセルがImageの境界で見切れているのがわかると思います。透明になっていくことで少しごまかしがきいていると思いますが、見た目としてはあまりよろしくないです。
参考サイト様
- シェーダーリファレンス
- ランダムな値を返す関数 on GLSL
- ゴブリンの画像