【Unity】カスタムパスで画面を水が流れるエフェクトを作る

投稿者: | 2024-02-13

プレイヤーが水をかぶったときのような、画面を水が流れるエフェクトを作ってみました。

テクスチャを使ってスクリーン位置をずらし画面を歪ませます。テクスチャは時間の値を使って縦にスクロールさせます。

プレイヤーが水流のオブジェクトを通ったときにエフェクトを表示します。コライダーとスクリプトを使います。

Custom Pass Volume

Custom Pass Volumeコンポーネントには、フルスクリーンシェーダーグラフが設定されたマテリアルがアタッチされています。

シェーダーグラフ

Graph InspectorのMaterialでは「Fullscreen」が選択されています。

シェーダーグラフでは、まずScreen PositionのY座標にTimeノードの値を足してスクロールさせます。

この値でNormalマップをサンプリングします。

強度などをかけたあとに、Screen Positionに足します。

このスクリーン位置を使ってシーンカラーを取得し、マスタースタックに入力します。

テクスチャをアタッチ

素材サイトで波のタイリングテクスチャをダウンロードして、法線マップを作ります。GIMPのフィルターでも作成できます。

画像をUnityにインポートします。Unityのインポート設定でTexture Typeを「Normal map」に設定します。

テクスチャはマテリアルにアタッチします。

これで画面を水が流れるエフェクトができました。

エフェクトを再生/停止する

プレイヤーが流れる水のオブジェクトにあたっているときにエフェクトを表示します。水から出るとエフェクトをフェードアウトさせます。

流れる水と水しぶきは前の記事で作成したものを使いました。参考:VFXとシェーダーグラフで簡単に水しぶきと流れる水を作る

流れる水の近くに空のゲームオブジェクトを置きます。Boxコライダーとタグを設定します。Boxコライダーは「Is Trigger」のチェックを入れます。また、プレイヤーと衝突できるレイヤーを設定します。

エフェクトの強度を操作

カスタムパスのゲームオブジェクトにスクリプトをつけます。カスタムパスにアタッチされたマテリアルを取得して、エフェクトの強度を操作しています。

using System.Collections;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;

public class StreamingWaterDistortion : MonoBehaviour
{
    Material material;

    // Start is called before the first frame update
    void Start()
    {
       var  volume = GetComponent<CustomPassVolume>();

        // カスタムパスのマテリアルを取得
        FullScreenCustomPass cp = (FullScreenCustomPass)volume.customPasses[0]; 
        material = cp.fullscreenPassMaterial;
    }

    public void StartWaterEffect()
    {
        // エフェクトを最大にする
        material.SetFloat("_Intensity", 1f);
    }

    public void FadeOutWaterEffect()
    {
        // コルーチンを開始
        StartCoroutine("FadeOutEffect");
    }

    IEnumerator FadeOutEffect()
    {
        // Intensityを徐々に下げる
        while (material.GetFloat("_Intensity") > 0f)
        {        
            material.SetFloat("_Intensity", material.GetFloat("_Intensity") - Time.deltaTime * 0.5f);
            
            yield return null;
        }

        material.SetFloat("_Intensity", 0f);
    }
}

まず、Startメソッドでフルスクリーンカスタムパスからマテリアルを取得します。

    Material material;

    // Start is called before the first frame update
    void Start()
    {
       var  volume = GetComponent<CustomPassVolume>();

        // カスタムパスのマテリアルを取得
        FullScreenCustomPass cp = (FullScreenCustomPass)volume.customPasses[0]; 
        material = cp.fullscreenPassMaterial;
    }

エフェクトを開始するメソッドと、フェードアウトするメソッドを作りました。

    public void StartWaterEffect()
    {
        // エフェクトを最大にする
        material.SetFloat("_Intensity", 1f);
    }

    public void FadeOutWaterEffect()
    {
        // コルーチンを開始
        StartCoroutine("FadeOutEffect");
    }

フェードアウトするときは、コルーチンで強度を少しずつ減少させます。

    IEnumerator FadeOutEffect()
    {
        // Intensityを徐々に下げる
        while (material.GetFloat("_Intensity") > 0f)
        {        
            material.SetFloat("_Intensity", material.GetFloat("_Intensity") - Time.deltaTime * 0.5f);
            
            yield return null;
        }

        material.SetFloat("_Intensity", 0f);
    }

プレイヤーのスクリプト

最後に、プレイヤーにスクリプトをつけます。OnTriggerEnter/Exitでエフェクトを再生/停止します。

using UnityEngine;

public class WaterInteractionHandler : MonoBehaviour
{ 
    [SerializeField] StreamingWaterDistortion effect;

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag != "WaterStream") return;

        // エフェクトを開始
        effect.StartWaterEffect();
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.tag != "WaterStream") return;

        // エフェクトをフェードアウト
        effect.FadeOutWaterEffect();
    }
}

これで、水流の出入りによってエフェクトが表示されるようになりました。

コメントを残す

メールアドレスが公開されることはありません。