えんじにあ雑記!

開発していて学んだことをまとめていきます!

DOTweenでPostProcessingの値を調整しようとしてAmbiguous invocationに悩んだ話

f:id:flat-M_M:20200407231710j:plain

DOTweenを使ってPostProcessingの値をスクリプトからアニメーションさせる時に遭遇したエラー。

Ambiguous invocation」の原因と、解決策まで!

本題

下記のようなコードでPostProcessingのColorGradingエフェクトのパラメータをスクリプトから調整しようとしてました。

var seq = DOTween.Sequence();
seq.Append(DOTween.To(() => _colorGrading.saturation, sat => _colorGrading.saturation = sat, 1f, 1f));
return seq;

すると、

f:id:flat-M_M:20200304214149p:plain
エラーメッセージ

なんかエラーが起きました。原因はDOTween.Toメソッドは引数がfloatとdoubleの場合でオーバーロードされているため、今回どっちを呼び出したら良いかコンパイラが判断できません。ということでした。

解決策

まずは、解決策から記載しておきます。

var seq = DOTween.Sequence();
seq.Append(DOTween.To(() => _colorGrading.saturation.value, sat => _colorGrading.saturation.value = sat, 1f, 1f));
return seq;

このように、saturationのvalueプロパティにアクセスすることでfloatだと判断できてコンパイルエラーを解決することができます。

原因

原因を説明していきます。

まず、saturaioinの実装を見にいきます。

        /// <summary>
        /// Pushes the intensity of all colors.
        /// </summary>
        [DisplayName("Saturation"), Range(-100f, 100f), Tooltip("Pushes the intensity of all colors.")]
        public FloatParameter saturation = new FloatParameter { value = 0f };

floatじゃなくて、FloatParameterというクラスの型になっています。さらに探ってみます。

    /// <summary>
    /// A <see cref="ParameterOverride{T}"/> that holds a <c>float</c> value.
    /// </summary>
    /// <remarks>
    /// The interpolation method for this parameter is the same as <see cref="Mathf.LerpUnclamped"/>.
    /// </remarks>
    [Serializable]
    public sealed class FloatParameter : ParameterOverride<float>
    {
        /// <inheritdoc />
        public override void Interp(float from, float to, float t)
        {
            value = from + (to - from) * t;
        }
    }

徐々に原因が見えてきました。コメント部分を翻訳しますと下記の通りになります。

A <see cref="ParameterOverride{T}"/> that holds a <c>float</c> value.
【訳】ParameterOVerrideはfloatの値を保持します

もう少しだけ掘り下げてみます。

    [Serializable]
    public class ParameterOverride<T> : ParameterOverride
    {
        /// <summary>
        /// The value stored in this parameter.
        /// </summary>
        public T value;

出てきましたね、value

先ほどの解決方法のコードをもう一度示します。

var seq = DOTween.Sequence();
seq.Append(DOTween.To(() => _colorGrading.saturation.value, sat => _colorGrading.saturation.value = sat, 1f, 1f));
return seq;

ここでアクセスしているvalueとは、

FloatParameterクラスが継承している

ParameterOverrideクラス

フィールド変数valueを参照してました。

そして、そのvalueとはジェネリクス

FloatParameterの場合継承しているのはParameterOverride<float>

なのでfloat型となるわけです。

最後に

初見では「は?」ってなったエラーですが、少し掘り下げてみると原因がさくっとわかったのでよかったです。

同じことで悩んでいる方の参考になれば幸いです。