気ままなUnityエンジニアブログ

新米Unityエンジニアが送る解説アウトプットブログです。Twitter : @UjinUnity

MENU

Unityでもじぴったんのスタンバイアニメーションを再現する!

スポンサーリンク

先週は「Unity1Week」開催中なこともあって、お題の「探す」をテーマにしたゲームを作ろうとしていたのですが、どういう訳か19年ほど前の名作ゲーム「もじぴったん」のゲーム開始前の演出を作成していました。

もう19年も前なのか

 

1. もじぴったんを再現したソースコード

using System;

using System.Collections;

using System.Collections.Generic;

using DG.Tweening;

using UniRx;

using UnityEngine;

using UnityEngine.UI;

public class ImgFade : MonoBehaviour {

 

    public RectTransform imageRt;

 

    public RectTransform LimitTextRt;

 

    public Image image;

 

    public CanvasGroup canvasGroup;

 

    public CanvasGroup canvasGroupText;

 

    private Vector3 saveSize;

 

    public Text FadeText;

 

    public RectTransform LimitTitleText;

    public RectTransform LimitText;

 

    public RectTransform ReadyText;

 

    public Text mReadyText;

    private int colorType = 0;

 

    void Awake () {

 

        this.canvasGroup.alpha = 0f;

        this.canvasGroupText.alpha = 0f;

        this.mSetYellowText ();

    }

 

    private void mSetYellowText () {

        string red = "<size=84><color=#ffea00>4</color></size>";

        string yellow = "<color=#ff0000>文字</color>";

        string white = "<color=#ffffff>のことばを あと</color>";

        string yellow2 = "<size=84><color=#ff0000>3</color></size>";

        string red2 = "<color=#ffea00>こ</color>";

        string white2 = "<color=#ffffff>作れ</color>";

 

        this.FadeText.text = red + yellow + white + yellow2 + red2 + white2;

    }

 

    private void mSetRedText () {

        string red = "<size=84><color=#fad000>4</color></size>";

        string yellow = "<color=#fad000>文字</color>";

        string white = "<color=#fad000>のことばを あと</color>";

        string yellow2 = "<size=84><color=#fad000>3</color></size>";

        string red2 = "<color=#fad000>こ</color>";

        string white2 = "<color=#fad000>作れ</color>";

 

        this.FadeText.text = red + yellow + white + yellow2 + red2 + white2;

    }

 

    void Start () {

 

        Observable.Timer (TimeSpan.FromSeconds (2))

            .Subscribe (_ => {

                Sequence sequence = DOTween.Sequence ()

                    .OnStart (() => {

 

                    })

                    .Append (this.imageRt.DOScale (Vector3.one, 1f)).SetEase (Ease.OutCubic)

                    .Join (this.canvasGroup.DOFade (1f, 0.8f)).SetEase (Ease.Linear)

                    .OnComplete (() => {

                        Debug.Log ("Comp");

                        this.setColor ();

                        // 回数表示

                        this.mSetLimitText ();

                    });

                sequence.Play ();

            }).AddTo (this);

 

    }

 

    private void setColor () {

        Observable.Interval (TimeSpan.FromSeconds (1))

            .Subscribe (_ => {

 

                if (this.colorType == 0) {

                    this.colorType = 1;

                    this.image.color = Color.red;

                    this.mSetRedText ();

                } else {

                    this.image.color = new Color (1, 0.4f, 0);

                    this.mSetYellowText ();

                    this.colorType = 0;

                }

            }).AddTo (this);

 

    }

 

    private void mSetLimitText () {

        Observable.Timer (TimeSpan.FromSeconds (2))

            .Subscribe (_ => {

                this.mLimitTextAnimation ();

            }).AddTo (this);

    }

 

    private void mLimitTextAnimation () {

        Sequence sequence = DOTween.Sequence ()

            .Append (this.LimitTitleText.DOScale (Vector3.one, 1f)).SetEase (Ease.OutCubic)

            .Join (this.LimitText.DOScale (Vector3.one, 1.5f)).SetEase (Ease.OutCubic)

            .Join (this.canvasGroupText.DOFade (1f, 0.8f)).SetEase (Ease.Linear)

            .OnComplete (() => {

                Debug.Log ("Comp mLimitTextAnimation");

                this.mLimitTextCoolTime ();

            });

    }

 

    private void mLimitTextCoolTime () {

        Observable.Timer (TimeSpan.FromSeconds (2))

            .Subscribe (_ => {

                this.mLimitTextUpper ();

            }).AddTo (this);

 

    }

 

    private void mLimitTextUpper () {

        Sequence sequence = DOTween.Sequence ()

            .Append (this.LimitTitleText.DOAnchorPosY (400f, 1f)).SetEase (Ease.Linear)

            .OnComplete (() => {

                Debug.Log ("Comp mLimitTextUpper");

            });

 

        Sequence sequence2 = DOTween.Sequence ()

            .Append (this.LimitText.DOAnchorPosY (280f, 1f)).SetEase (Ease.Linear).SetDelay (0.5f)

            .OnComplete (() => {

                Debug.Log ("Comp mLimitTextUpper");

            });

        Sequence sequence3 = DOTween.Sequence ()

            .Append (this.imageRt.DOAnchorPosY (-450, 1f)).SetEase (Ease.Linear).SetDelay (0.8f)

            .OnComplete (() => {

                Debug.Log ("Comp mLimitTextUpper");

                this.mSetReadyText ();

            });

 

    }

 

    private void mSetReadyText () {

        Sequence sequence = DOTween.Sequence ()

            .Append (this.ReadyText.DOAnchorPosX (50f, 1f)).SetEase (Ease.Linear)

            .AppendInterval (1f)

            .OnComplete (() => {

                this.mReadyText.text = "ごー!";

                this.mSetGoText ();

            });

 

    }

 

    private void mSetGoText () {

        Sequence sequence = DOTween.Sequence ()

            .AppendInterval (0.5f)

            .Append (this.ReadyText.DOAnchorPosX (1300f, 1f)).SetEase (Ease.Linear)

            .OnComplete (() => {

                Debug.Log ("mSetGoText");

            });

    }

}

テスト用に作成したのでスクリプトや関数名はすごい適当です。

アニメーションの再現方法は

1 . Dotweenを使ってテキストやイメージのアニメーションを行う
2 . TextのRichTextを適応して動的にテキストの色を変更する

の2つを使用しています。

次にUnity側の実装を見ていきましょう。


f:id:Wojtek:20191021152047p:plain

思わずなんだこれは!?と思ってしまう散らかりっぷりですね・・・(反省)

最初のimage ですが、ここでは最初のオレンジの帯とテキストの部分を担当しています。


f:id:Wojtek:20191021153705g:plain


上記動画の部分ですね。最初に表示され、ゲームのルールを知らせます。


次は残り時間などを表示する部分です。
今回は残り回数という表記で表しています (当初作成する予定のゲームルールに合わせて)

f:id:Wojtek:20191021154103g:plain


ここもUnityのTextをDotweenで動かしています。

あと、ゲームルールを知らせるTextですがタイマー制御で1秒ごとに背景とTextの色とサイズを変更しています。

ソースコードでいうとこの部分に該当

    private void mSetYellowText () {

        string red = "<size=84><color=#ffea00>4</color></size>";

        string yellow = "<color=#ff0000>文字</color>";

        string white = "<color=#ffffff>のことばを あと</color>";

        string yellow2 = "<size=84><color=#ff0000>3</color></size>";

        string red2 = "<color=#ffea00>こ</color>";

        string white2 = "<color=#ffffff>作れ</color>";

 

        this.FadeText.text = red + yellow + white + yellow2 + red2 + white2;

    }

 

    private void mSetRedText () {

        string red = "<size=84><color=#fad000>4</color></size>";

        string yellow = "<color=#fad000>文字</color>";

        string white = "<color=#fad000>のことばを あと</color>";

        string yellow2 = "<size=84><color=#fad000>3</color></size>";

        string red2 = "<color=#fad000>こ</color>";

        string white2 = "<color=#fad000>作れ</color>";

 

        this.FadeText.text = red + yellow + white + yellow2 + red2 + white2;

    }

RichTextが有効の場合、html形式が有効になるのでソースコード上で動的に変更することが可能です。
細かいアニメーションをやりたい場合はオススメの方法ですね。


最後に左側から出現する「レディー?」部分を見てみましょう。

f:id:Wojtek:20191021154742g:plain


こちらは左側からTextを中央に移動させ、タイマー管理で文字を変更し右側に移動させています。

色々とゴチャゴチャしていますが1つ1つの処理はとても単純で作りやすいですね
流石もじぴったん

UIアニメーションを入れるだけでゲームの面白さがガツンと上がると思っています。
これからも積極的に導入していきたいですね。