【Unity】3DTextをホワンと半透明アニメーションさせる

【Unity】3DTextをホワンと半透明アニメーションさせる
スポンサーリンク

こんにちは!ゆとり(@yutori_techblog)です!最近Unityにハマっています。

この記事では、次のような3DTextがホワンと浮かび上がるようなアニメーションを作成してみます。

普通にできそうな気がしますが、実は3DTextを半透明にするアニメーションは一筋縄ではいきません。

TextMeshのColorプロパティはアニメーションできない

3DTextの透明度を変化させるには、TextMeshコンポーネントのColorプロパティをいじれば実現できます。

なので、アニメーションプロパティでColorをいじれば簡単に実現できると考えてしまうのですが、何故かUnityのアニメーションシステムではTextMeshのColorプロパティをいじることができません。。

しかしながら、上に書いたように3DTextを半透明にする方法は実際に存在するわけで。
TextMeshのColorプロパティを直接いじるスクリプトを書けば実現できるかな?と思って作ってみました。

3DTextの透明度をアニメーションさせるコンポーネント

次のようなコンポーネントを作成しました。

public class Text3DOpacityControl : MonoBehaviour
{
    TextMesh textMesh;

    [SerializeField, Range(0,1)]
    float m_opacity;

    //Inspectorで値が編集されたときに呼ばれる
    private void OnValidate()
    {
        if (textMesh == null) textMesh = GetComponent<TextMesh>();
        textMesh.color = new Color(textMesh.color.r, textMesh.color.g, textMesh.color.b, m_opacity);
    }

    private void Update()
    {
        OnValidate();
    }
}

SerializeFiledのfloat値を持ち、その値が変わったらTextMeshのColorプロパティ(r,g,b,a)のaの成分に直接適用させるコンポーネントですね。

ちなみに、OnValidate()というメソッドの中に書いた処理は、Inspectorの値が変化する度に自動的に呼ばれるようになります。そのため、Inspectorから処理結果をリアルタイムにプレビューすることができます。

OnValidateメソッド

OnValidateメソッドの中に書いた処理は、ゲームの実行中でなくても、Inspectorの値が編集されると自動的に呼ばれるようになる。

このコンポーネントを対象の3DTextにアタッチします。

するとInspectorにこのようなスライダーが現れるので、これを操作すると…

TextMeshのColorプロパティに値が連動して、3DTextの透明度を直接操作することができました!

作成したコンポーネントをアニメーションに適用する

というわけで、3D Textの不透明度を直接いじることができるプロパティができたので、Unityのアニメーションシステムに紐付けましょう。

AddPropertyを押下し、作成した「Text3DOpacityControl」の中のOpacityプロパティを追加します。

これでアニメーションシステムの中で3DTextの透明度の制御ができるようになりました!
あとは煮るなり焼くなり好きにすることができます。

ちなみに、記事の最初にお見せしたようなアニメーションは、positionのy座標も操作して次のようなアニメーションになっています。

UniRxを利用したスクリプトの改善

ちなみに、先ほどの自作コンポーネントは一部非効率な部分があることに気づきましたか?

public class Text3DOpacityControl : MonoBehaviour
{
    TextMesh textMesh;

    [SerializeField, Range(0,1)]
    float m_opacity;

    //Inspectorで値が編集されたときに呼ばれる
    private void OnValidate()
    {
        if (textMesh == null) textMesh = GetComponent<TextMesh>();
        textMesh.color = new Color(textMesh.color.r, textMesh.color.g, textMesh.color.b, m_opacity);
    }

    private void Update()
    {
        OnValidate();
    }
}

Updateメソッド内で毎回Color書き換えが起こっているのが気になるような…

そうなんです!
これでは、アニメーションしていないときも毎フレームTextMeshのColorを書き換える処理が入ってしまいます。

m_opacityの値が変化した時だけColorを書き換えて欲しい…

「値が変化したとき」といえば…?

UniRxのDistinctUntilChanged!!

というわけで、UniRxを使って書き換えたコードも載せておきますので、よろしければ参考にしてください。
この改善版コードを利用すると、必要なときだけColorプロパティの書き換えが行われるようになります。

public class Text3DOpacityControl : MonoBehaviour
{
    TextMesh textMesh;

    [SerializeField, Range(0,1)]
    float m_opacity;

    private void Start() {
        textMesh = this.GetComponent<TextMesh>();
        Observable.EveryUpdate()
                  .Select(_ => m_opacity)
                  .DistinctUntilChanged()
                  .Subscribe(opacity => textMesh.color = new Color(textMesh.color.r, textMesh.color.g, textMesh.color.b, opacity));
    }

    private void OnValidate()
    {
        if (textMesh == null) textMesh = GetComponent<TextMesh>();
        textMesh.color = new Color(textMesh.color.r, textMesh.color.g, textMesh.color.b, m_opacity);
    }
}
注意

このコードの利用にはUniRxをAsset Storeからダウンロードしてインポートする必要がありますのでご注意ください。

UniRx…?DistinctUntilChanged…??

この記事では説明しきれないのでググってみてね!

最後までありがとうございました!
ご意見、ご質問等ございましたら、コメントもしくはTwitterへお気軽にお寄せください!