【Unity】カードをクルクル回転させるエフェクトを作ってみた

Unity

Unity初心者です。

現在カードゲームを作成しているのですが、初心者のため、なかなか苦戦をしており、備忘も兼ねて技術ブログを作成しています。

今回はカードゲームにおいてカードをクルクルと回転させるエフェクトをスクリプトで書いてみたので、その紹介になります。

カードをクルクル回転させるエフェクトとは

「カードをクルクル回転」という言葉でうまく説明できてるかわからないのですが、作成したエフェクトはこんな感じのものです。

まだちょっと荒いところもありますが、要はカードゲームの先攻と後攻を決める時に、「カードが止まった面で決まる」という演出をしたかったです。

要件としては

  • 裏と表が交互に見える
  • 指定したスピードや回転数で止まる
  • 徐々にスピードダウンする

といったところです。

(本当は双六みたいな感じで先攻と後攻を決めたかったですが、2Dだと面倒すぎてやめた)

あまり汎用的に使える演出じゃないので需要はないかもしれませんが、ソースなどを公開してみたいと思います。

カードを回転させてみたソースコード

早速ですがスクリプトは以下になります。

カード用のゲームオブジェクトは「teban」という名前でImageを作っており、それを回転させています。

最終的に、引数のisFirstがtrueであれば先行、falseであれば後攻が出ます。

    private async Task decisionTeban(bool isFirst)
    {
        const int MAXCNT = 10;  //回転させる数
        float speed = 200f; // 回転させるスピード
        float angle = -180f;

        Sprite ura = Resources.Load<Sprite>("Sprites/kouko"); //後攻の画像
        Sprite omote = Resources.Load<Sprite>("Sprites/senko"); //先行の画像

        float deltatime = Time.deltaTime;
        int i = 0;
        angle = 0f;

        //回転させる
        while (i < MAXCNT)
        {
            if (angle > 90f)
            {
                teban.sprite = isFirst ? ura : omote;
                deltatime = - deltatime;
                i++;
                speed -= (speed/MAXCNT);
                angle = 90f;
            }
            else if(angle < 0f)
            {
                teban.sprite = isFirst ? omote : ura;
                deltatime = - deltatime;
                i++;
                speed -= (speed/MAXCNT);
                angle = 0f;
            }
            angle += speed * deltatime;
            teban.transform.eulerAngles = new Vector3(0, angle, 0);
            await Task.Delay(TimeSpan.FromSeconds(0.01f));
        }
        teban.transform.eulerAngles = new Vector3(0, 0, 0);
        await Task.Delay(TimeSpan.FromSeconds(0.5f));
        Destroy(teban); // 終わったら画像を破棄する
        await Task.Delay(TimeSpan.FromSeconds(0.3f));
    }

呼び出し元

async void test(){
    int r = UnityEngine.Random.Range(0, 2); // 先攻と後攻をランダムで決定
    await decisionTeban(r == 0); // 処理を止めたいのでawaitで呼び出す
}

ソースコードの解説など

まず、基本的な部分は下記記事に記載したカードをめくるという処理とほぼ同じになります。

while文でawaitを使いながらカードを回転させていき、「カードのGameObjectが90度回転した時点で表面を差し替える」ことでカードが裏返ったように見せられます。

(transform.eulerAnglesのY軸を徐々に増やしていく)

もちろんメイン処理を止めたくなければ、async/awaitでなくコルーチンでも問題なく出来るかと思います。

しかし、ここで問題があります。Y軸の角度が-90~-180度になってしまうと下記の画像のように画像が反転してしまいます。

対策として、「90度になったら画像を変更する」のは同じですが「90度になったら0度に向かって回転する」という処理も追加しました。

それが以下の部分です。

            if (angle > 90f)
            {
                teban.sprite = isFirst ? ura : omote;
                deltatime = - deltatime;
                i++;
                speed -= (speed/MAXCNT);
                angle = 90f;
            }

deltatimeという変数に回転させる方向性をもたせているので、これを反転させています。そしてこのタイミングでスピードを遅くしています。

そして0度になったら再び回転する角度を正に戻します。

そうすることにより、GameObjectのeulerAnglesは、0度→90度→0度→90度と往復するので画像が反転する心配がありません。

コメント

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