【Unity】 VisualEffectGraph のプロパティに属性を付与する

はじめに

本記事ではVisualEffectGraphのプロパティに「擬似的に」属性を付与する方法について解説します。
付随してProperty Bindingを自前で実装する方法とその使い方についても記載します。

VisualEffectGraphのプロパティについて

VisualEffectGraphではプロパティと呼ばれるBlackboardで定義する変数を扱うことができます。
これは外部(他のコンポーネント等)からVisualEffectGraphに対して情報を与える変数として使用されます。

例えば、下記のようにVisualEffectGraph内で定義してやると

このようにVisualEffectのインスペクタにPropertiesとして変数設定が表示されるようになります。

やりたいこと

今回やりたいことはこのA、Bに属性を付与するということです。

通常のComponentであれば[Serializable]などのように普通にコードを書けばよいですが、VisualEffectGraphのプロパティの場合にコードで定義することはできないため、別の手段が必要になります。

どういうときに必要なの?

基本的にはあまり使わない内容だと思うので、結構ニッチなニーズかなと思います。

AssetStoreではエディタ拡張を用いた機能が提供されている物が多くあります。
例えばインスペクタの拡張で有名なOdinでは[ShowInInspector]という属性や[ReadOnly]といった属性などがあります。

エディタ拡張によるものでなくても[Range(min, max)]でスライダーで値を調整できるようにするなど、属性を使用したい場面は地味に存在します。

そういったことをVisualEffectGraphのプロパティに対してやろうとしたときに、デフォルトだとできないので、どうやって実現するかという話になります。

サンプルの前提

今回CurveMasterというアセットを購入しVisualEffectGraphで使用するカーブの編集を楽にしようと思ったのですが、AnimationCurveの場合AnimationCurveのフィールドに[EditWithCurveMaster]を付与する必要がありました。

Curve Master | Animation Tools | Unity Asset Store
Use the Curve Master tool from Yan-K Media Works on your next project. Find this & more animation tools on the Unity Ass...

せっかく買ったのに使えないのももったいないので、方法を調べたところProperty Binderという外部と接続するための機能があったのでこれを使用します。

上記アセット用に作成したものなので、今回はAnimationCurveの例になることをご承知おきください。

また、作成にあたってこちらの記事も参考にさせていただきました。
https://qiita.com/sh00t/items/fabcb0d06e578f21e815

実装例

今回はAnimationCurveに対して使用したかったので、AnimationCurveの例になります。

using UnityEngine;
using UnityEngine.VFX;
using UnityEngine.VFX.Utility;

/// <summary>
/// VFXBinderBase派生クラスで、Visual EffectのプロパティにAnimationCurveをバインドします。
/// CurveMasterと連携して動作します。
/// </summary>
[VFXBinder("CurveMaster/AnimationCurve")]
public class AnimationCurveBinder : VFXBinderBase
{
    /// <summary>
    /// Visual Effect Graph内でのAnimationCurveプロパティの名前を指定します。
    /// </summary>
    [VFXPropertyBinding("UnityEngine.AnimationCurve"), SerializeField]
    ExposedProperty AnimationCurvePropertyName;

    /// <summary>
    /// バインドするAnimationCurveを指定します。
    /// </summary>
    [SerializeField, EditWithCurveMaster] //←このEditWithCurveMaster属性が使いたかった
    private AnimationCurve animationCurve;

    /// <summary>
    /// バインディングが有効かどうかを確認します。
    /// </summary>
    /// <param name="component">検証対象のVisualEffectコンポーネント</param>
    /// <returns>
    /// バインディングが有効な場合はtrue、
    /// AnimationCurveまたはコンポーネントがnull、
    /// もしくはプロパティが存在しない場合はfalseを返します。
    /// </returns>
    public override bool IsValid(VisualEffect component)
    {
        if (animationCurve == null || component == null)
        {
            return false;
        }
        return component.HasAnimationCurve(AnimationCurvePropertyName.ToString());
    }

    /// <summary>
    /// Visual Effectのプロパティに指定されたAnimationCurveを設定します。
    /// </summary>
    /// <param name="component">更新対象のVisualEffectコンポーネント</param>
    public override void UpdateBinding(VisualEffect component)
    {
        component.SetAnimationCurve(AnimationCurvePropertyName, animationCurve);
    }
}

これを適当なフォルダに配置するとVisualEffectGraph用のプロパティでも、属性が付与されたもとのして変数を擬似的に扱えるようになります。
(触るのは実際にVisualEffectGraphで定義したものではないので擬似的にとしています)

■ざっくり解説
このクラスはVFXBinderBaseを継承しています。これを継承することでVisualEffectGraph内のプロパティにここの変数をBindすることができます。

今回はフィールドに属性を定義したいので、自前で書いていますが、Transformなどはあらかじめ用意されています。

IsValidメソッドはBindが有効かどうかを判定します。
今回はVisualEffectコンポーネントがnullでないこととAnimationCurveがnullでないこと。
そして、VisualEffectGraphがSizeCurveという名称のプロパティを持っているかで判定しています。

UpdateBindingメソッドはBindされた変数をVisualEffectGraphへ渡しています。
このメソッドはIsValidがtrueを返さないと呼ばれません。
今回はそのままカーブを渡していますが、この中で値を操作してから渡すということも可能です。

使用方法

まずVisualEffectGraph側でプロパティを用意しておきます。

次にインスペクタの方へ行き、VFX Property BinderというコンポーネントをVisualEffectがアタッチされたオブジェクトにアタッチします。

Property Bindings の「+」をクリックするとCurveMaster > AnimationCurveという項目があるのでそれをクリックします。
これがリストアップされるのは先程のコードで下記の属性を定義していたからです。
[VFXBinder(“CurveMaster/AnimationCurve”)]

Listに追加するとAnimationCurveBinderという項目が追加されます。
また、同時にAnimationCurveBinderコンポーネントが勝手にアタッチされます。(このコンポーネントは基本的に見ないでよいです)

List二追加されたAnimationCurveBinderをクリックするとAnimationCurveBinderクラスで定義したフィールドが展開されます。

PropertyNameの右端にある「v」をクリックするとVisualEffectGraph内に定義されているもののうち、指定された型(AnimationCurve)のものがリスト表示されるのでこれを選択します。今回はSizeCurveしか定義していないのでこれしか表示されません。

[VFXPropertyBinding(“UnityEngine.AnimationCurve”)]この属性で、VisualEffectGraph内のどの型(今回はUnityEngine.AnimationCurve)のプロパティをリストアップするかを指定しています。

SizeCurveを選択するとPropertyNameに記入されます。
そして問題なくBindされると先程までオレンジだった四角が緑に変わります。

これでBind完了でここのインスペクタのAnimationCurveを操作するとVisualEffectGraph内のカーブに反映されるようになります。

さいごに

上記を行うことで擬似的にVisualEffectGraphのプロパティを属性が付与された状態で扱うことができます。
ニッチなニーズだとは思いますが、どなたかのお役に立てば幸いです。

コメント

タイトルとURLをコピーしました