概要
Unityのシェーダーを使ってタップ(またはクリック)した時に波紋のアニメーションを生成する方法
こんな感じで水面に広がる波紋のようにアニメーションさせるスクリプトを書いてみました。
https://github.com/katsuma99/TapRippleShader
以下にシェーダーのソースを載せていますが、今回は細かい解説はなしに波紋エフェクトが使えるように手順を説明していきます。また、波紋エフェクトはタップした時に発生させることを想定しているため、タップ時の当たり判定についても少し解説します。
Shader "Custom/Ripple" {
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
[HideInInspector]_StartTime("StartTime", Float) = 0
_AnimationTime("AnimationTime", Range(0.1, 10.0)) = 1.5
_Width("Width", Range(0.1, 3.0)) = 0.3
_StartWidth("StartWidth", Range(0, 1.0)) = 0.3
[Toggle] _isAlpha("isAlpha",Float) = 1
[Toggle] _isColorShift("isColorShift",Float) = 1
[MaterialToggle] PixelSnap("Pixel snap", Float) = 1
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"PreviewType" = "Plane"
}
Lighting Off
ZWrite Off
Fog{ Mode Off }
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile DUMMY PIXELSNAP_ON
#include "UnityCG.cginc"
struct v2f
{
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
v2f vert(appdata_base IN)
{
v2f OUT;
OUT.vertex = UnityObjectToClipPos(IN.vertex);
OUT.texcoord = IN.texcoord;
return OUT;
}
fixed3 shift_col(fixed3 RGB, half3 shift)
{
fixed3 RESULT = fixed3(RGB);
float VSU = shift.z*shift.y*cos(shift.x*3.14159265 / 180);
float VSW = shift.z*shift.y*sin(shift.x*3.14159265 / 180);
RESULT.x = (.299*shift.z + .701*VSU + .168*VSW)*RGB.x
+ (.587*shift.z - .587*VSU + .330*VSW)*RGB.y
+ (.114*shift.z - .114*VSU - .497*VSW)*RGB.z;
RESULT.y = (.299*shift.z - .299*VSU - .328*VSW)*RGB.x
+ (.587*shift.z + .413*VSU + .035*VSW)*RGB.y
+ (.114*shift.z - .114*VSU + .292*VSW)*RGB.z;
RESULT.z = (.299*shift.z - .3*VSU + 1.25*VSW)*RGB.x
+ (.587*shift.z - .588*VSU - 1.05*VSW)*RGB.y
+ (.114*shift.z + .886*VSU - .203*VSW)*RGB.z;
return RESULT;
}
sampler2D _MainTex;
float _StartTime,_Width,_StartWidth, _AnimationTime, _isAlpha,_isColorShift;
fixed4 frag(v2f IN) : SV_Target
{
fixed4 color = tex2D(_MainTex, IN.texcoord);
float2 pos = (IN.texcoord - float2(0.5,0.5)) * 2; //-1~1 幅2
float dis = (_Time.y - _StartTime) / _AnimationTime + _StartWidth - length(pos);
if (dis < 0 || dis > _Width)
return fixed4(0,0,0,0);
float alpha = 1;
if (_isAlpha == 1)
{
alpha = clamp((_Width - dis) * 3, 0.1, 1.5);
}
fixed3 shiftColor = color;
if (_isColorShift == 1)
{
half3 shift = half3(_Time.w * 10, 1, 1);
shiftColor = shift_col(color, shift);
}
return fixed4(shiftColor, color.a * alpha);
}
ENDCG
}
}
Fallback "Sprites/Default"
}
使用するための手順
1. マテリアルの作成
2. ゲームオブジェクトの作成
3. タッチパネルの作成
Step1.マテリアルの作成
まずは、波紋シェーダーをアタッチするために、ProjectタブでマテリアルTapRippleMat
を作成します。
マテリアルの作成:Project > Create > Material
次に、シェーダーRipple
を作成し、冒頭で紹介したコードをそのままコピペして上書きします。
シェーダーの作成:Project > Create > Shader > ImageEffectShader
最後に、作成したTapRippleMat
にRipple
をアタッチし、InspectorタブのShaderプルダウンでCustom/Rippleを指定します。これで、波紋シェーダーのマテリアルが完成しました。シェーダーのパラメータをいじることで様々な波紋エフェクトを作成できます。(後で説明)
Step2.ゲームオブジェクトの作成
タップした場所に波紋を生成するゲームオブジェクトTapEffect
を作成します。正確には波紋を描画するための平面をアタッチしたゲームオブジェクトを生成するため、Hierarchy上でSpriteを生成します。
スプライトの作成:Hierarchy > 2DObject > Sprite
次に、以下のテクスチャをProject上にドラック&ドロップでインポートします。そして、TapEffect
のSpriteRenderer > Spriteに割り当てます。
次に、C#スクリプトTapCircle
を作成し、以下のコードをコピペで上書きして、TapEffect
にアタッチします。
C#スクリプトの作成:Project > Create > C#Script
using UnityEngine;
[RequireComponent(typeof(SpriteRenderer))]
[RequireComponent(typeof(Collider2D))]
public class TapCircle : MonoBehaviour
{
SpriteRenderer mSpriteRenderer;
Collider2D mCircleCollider;
void Awake()
{
mSpriteRenderer = transform.GetComponent<SpriteRenderer>();
mCircleCollider = transform.GetComponent<Collider2D>();
}
void Start()
{
Invoke("unenabledTrigger", 0.05f);
mSpriteRenderer.material.SetFloat("_StartTime", Time.time);
float animationTime = mSpriteRenderer.material.GetFloat("_AnimationTime");
float destroyTime = animationTime;
destroyTime -= mSpriteRenderer.material.GetFloat("_StartWidth") * animationTime;
destroyTime += mSpriteRenderer.material.GetFloat("_Width") * animationTime;
Destroy(transform.gameObject, destroyTime);
}
public void unenabledTrigger()
{
mCircleCollider.enabled = false;
}
public void OnTriggerEnter2D(Collider2D collider)
{
//タップしたオブジェクト : collider
//-----------------処理-----------------//
}
}
すると自動的にTapEffect
にCircleCollider2Dがアタッチされるので、CircleCollider2D > Radiusに0.5を指定してください。
ちなみに、タップの当たり判定についてはTapCircle
のOnTriggerEnter2Dの関数内でタップしたオブジェクトcollider
に対して処理を行うことができます。
なお、タップするオブジェクトにはColliderと一緒にRigidbodyもアタッチしておいてください。当たり判定はColliderをアタッチしたどちらかのゲームオブジェクトにRigidbodyがないとできない仕様になっています。
当たり判定の注意:Colliderの他にRigidbodyが必要
以上で、ゲームオブジェクトの設定ができたので、TapEffect
をHierarchyからProjectへ移しておいてください。
Step3.タッチパネルの作成
まずは、C#スクリプトPlayTouchPanel
を作成し、以下のコードをコピペして上書きしてください。
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof(Image))]
public class PlayTouchPanel : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
public GameObject mTapEffect;
public void OnPointerDown(PointerEventData eventData)
{
//マウスクリック時
NewTapEffect(eventData.position);
}
public void OnPointerUp(PointerEventData eventData)
{
}
public void OnDrag(PointerEventData eventData)
{
}
void Update()
{
//タップ時
CheckTap();
}
void CheckTap()
{
foreach (Touch t in Input.touches)
{
if (t.phase == TouchPhase.Began)
{
NewTapEffect(t.position);
}
}
}
//タップエフェクトを出す
void NewTapEffect(Vector2 pos)
{
Vector2 worldPos = Camera.main.ScreenToWorldPoint(pos);
Object.Instantiate(mTapEffect, worldPos, Quaternion.identity, transform);
}
}
以上でProjectの編集は完了し、以下のように6ファイルを作成できていると思います。
次に、HierarchyにキャンバスTouchCanvas
を作成し、その下に空のゲームオブジェクトTouchPanel
を作ります。EventSystem
はキャンバスを作成すると自動的に作られるタッチイベントを可能にするゲームオブジェクトです。
キャンバスの作成:Hierarchy > UI > Canvas
空のオブジェクトの作成:Hierarchy > CreateEmpty
TouchPanel
にPlayTouchPanel
をアタッチし、Scene上でTouchPanel
の枠を操作して、RectTransformの領域をカメラ画面に合わせておきます。
またPlayTouchPanel
をアタッチすると、自動的にCanvasRendererとImageがアタッチされていることがわかります。この2種類のコンポーネントはタッチイベントを発生させるために必要です。タッチイベントは、キャンバス上のイメージにタッチすることがトリガーとなっていることに注意してください。
タッチイベントの注意:CanvasRendererとImageが必要
以上でタッチパネルの作成が完了しました。
アプリを実行して画面にタッチすることで波紋が出ることを確認してい下さい。
パラメーターをいじる
項目 | 意味 |
---|---|
AnimationTime | 波紋エフェクトが発生して消えるまでの時間 |
Width | 広がる波紋の幅(全長 : 2) |
StartWidth | エフェクト発生時の波紋の広がり度合(中心からの距離) |
isAlpha | 波紋にアルファをかけて柔らかくする |
isColorShift | 波紋の色を変えてカラフルにする |
お気に入りの波紋アニメーションを作成してみよう。
使用例
落ちてくる物をタップして、得点を稼ぐゲームです。
特にタップゲーはタップした時になにか反応がないと、タッチしたかわからず、操作性が微妙ってことになってしまうと思います。
タップした部分に波紋を広げることで、爽快感とタップした触感を視覚的に与えることができるのではないでしょうか。
と、ただのゲームの宣伝なのですが。。。よければ応援お願いしますm・・m