【Unity】クリッカーゲーム(2)アニメーションと効果音【Game A Week】

クリッカーゲームを作る(2)

前回でクリッカーゲームの基本的な動作ができ上がったので、ビジュアルを派手にして行きたいと思います。アニメーションと効果音をつけていきます。

目次

寿司の画像を本番用に

ここまで、ゲーム内で使う画像は私が描いた仮の画像を使っていましたが、ちゃんと動くゲームを作れる目処が立ったので本番用の画像に差し替えたいと思います。

画像はいらすとやさんからお借りしました。こんな感じになりました。

寿司工場03

画像の透過部分をクリックできないようにする

この巨大な寿司をクリックするとお金が増えていくというのがこのゲームなのですが、気になる点がありまして。四角いImageオブジェクトに透過PNG画像を貼り付けているのですが、透過部分(寿司じゃないところ)もクリックできてしまうわけです。

透過部分のクリック判定を無効化します。

  1. 寿司画像のインスペクターで「Advanced > Read/Write」にチェックを入れる
  2. スクリプトを修正する
public Image imageSushi; // 巨大寿司画像

void Start()
{
    ...省略...

    imageSushi.alphaHitTestMinimumThreshold = 1; // 透過部分をクリックできないようにする
}

imageSushi変数にはUnity側でSushiオブジェクトを紐付けます。

alphaHitTestMinimumThresholdはクリック判定が有効になる不透明度のしきい値です。0ならば不透明度が0%以上でクリック判定が有効(初期値)、0.5fならば50%以上で有効、1ならば100%以上で有効です。

これで、寿司部分だけをクリックできるようになりました。

寿司をクリックしたときのアニメーション

寿司をクリックしたときにアニメーションさせたい。

STEP

ヒエラルキーのSushiオブジェクトを選択した状態でメニューの「Window > Animation > Animation」を選択します。

Animationウインドウが開くので「Create」ボタンをクリック。「SushiAnimation」と名前をつけて保存します。

寿司工場05

これでAssetsフォルダにアニメーションクリップアニメーターが作成されます。また、SushiオブジェクトにはAnimatorコンポーネントが追加されます。

寿司工場06
STEP

Animationウインドウの「Add Property > Rect Transform > Scale の +」をクリックして、プロパティを追加します。Scaleはオブジェクトの拡大/縮小をすることができるプロパティです。

STEP

とりあえずアニメーションの長さを0:30に、途中の0:15あたりで x, y の値を2にしてみます。で、再生ボタンをクリックすると、ちゃんと寿司が動きました。

これだと動きが大きすぎるので、x, y は 1.2 に、長さは 0:20 にしました。

STEP

アニメーションをループさせないようにします。AssetsフォルダのSushiAnimationを選択し、インスペクターで「Loop Time」のチェックを外します。

STEP

ヒエラルキーのSushiオブジェクトを選択した状態でメニューの「Window > Animation > Animator」を選択します。

Animatorタブが開きます。Animatorはアニメーションをコントロールするための仕組みです。

STEP

「Parameters」タブをクリックして、「+」から「Trigger」を追加します。「New Trigger」という名前のトリガーが追加されるので「SushiClick」に名前を変更します。

寿司工場08

あとで、このトリガーを使って寿司がクリックされたときにアニメーションするようにします。

STEP

Animatorタブの右側の図を見ると「Entry」から「SushiAnimation」に矢印がつながっています。これだと、ゲームが開始した途端にSushiAnimationが実行されてしまうので、次のように変更します。

  1. 「Any State」を右クリックして「Make Transition」を選択。
  2. 矢印を「SushiAnimation」につなげる。
  3. 今つなげた矢印を選択してインスペクターの下のほう「Conditions」の「+」をクリックしてトリガー「SushiClick」を設定。
  4. Animatorのなにもないところで右クリックして「Create State > Empty」を選択。「New State」が作成されます。
  5. 「Entry」を右クリックして「Set StateMachine Default State」をクリック。矢印を「New State」につなげる。

以下のようになります。

寿司工場09
STEP

スクリプトを修正します。

public class SushiClicker : MonoBehaviour, IPointerClickHandler
{
    ...省略...
    public Animator sushiAnimator; // Animatorコンポーネント
    ...省略...

    // 巨大寿司をクリックしたとき
    public void OnPointerClick(PointerEventData eventData)
    {
        ...省略...
        if (sushiAnimator != null)
            sushiAnimator.SetTrigger("SushiClick"); // クリック時アニメーションを再生
    }
    ...省略...
}

sushiAnimator変数にはUnity上でSushi(Animator)を紐つけておきます。

以上で、寿司をクリックしたときにぴょこんと動くアニメーションができました。

寿司をクリックしたときの効果音

寿司をクリックしたときに音を鳴らしたいです。ボタンにクリック音を付けるのは以前やったんだけど、今回はImageオブジェクトなので違うやり方。

  1. クリック音の音声ファイルをAssetsフォルダに入れておく。効果音ラボさんからお借りしました。
  2. ヒエラルキータブの何もないところで右クリック「Audio > Audio Source」を選択して Audio Source を作成。
  3. スクリプトの修正
public class SushiClicker : MonoBehaviour, IPointerClickHandler
{
    ...省略...
    public AudioSource audioSource; // Audio Source
    public AudioClip clickSound; // 寿司のクリック音
    ...省略...

    // 巨大寿司をクリックしたとき
    public void OnPointerClick(PointerEventData eventData)
    {
        ...省略...

        if (clickSound != null)
            audioSource.PlayOneShot(clickSound); // クリック音を再生
    }
    ...省略...
}

Unity側でaudioSourceclickSoundを設定。

効果音を再生するメソッドはPlayOneShotを使います。PlayメソッドはBGMを再生するとき、PlayOneShotメソッドは効果音を再生するとき。

おしながきのレベルに合わせて寿司画像を変更したい

おしながきのレベルをアップしたら巨大寿司の画像が別の寿司ネタに変わるようにしたい。ついでに右下に「?」マークのリストを作っておいて、1つずつアンロックされていくみたいにしたい。

寿司工場10

スクリプトをゴリゴリ書いていきます。

public class SushiClicker : MonoBehaviour, IPointerClickHandler
{
    ...省略...
    public Image[] sushiMenuImages; // 小さい寿司画像を表示するImageオブジェクトの配列
    public TextMeshProUGUI[] sushiMenuTexts; // 寿司の名前を表示するTMPの配列
    public Sprite[] sushiSprites; // 寿司画像の配列
    public string[] sushiNames; // 寿司の名前の配列
    ...省略...

    // メニューのレベルアップ
    void UpgradeMenu()
    {
        if (menuCurrentLevel < menuUpgradeCosts.Length - 1) // メニューのレベルが最大でない場合
        {
            double upgradeCost = menuUpgradeCosts[menuCurrentLevel + 1]; // 次のメニューのアップグレードコストの取得

            if (money >= upgradeCost) // 所持金がアップグレードコスト以上の場合
            {
                ...省略...
                UpdateSushiImage(); // 寿司画像の更新
            }
        }
    }

    // メニューの寿司画像の更新
    void UpdateSushiImage()
    {
        int level = Mathf.Clamp(menuCurrentLevel, 0, sushiSprites.Length - 1);

        GetComponent<Image>().sprite = sushiSprites[level]; // 巨大寿司の画像を変更

        for (int i = 0; i < sushiMenuImages.Length; i++)
        {
            if (i == level)
            {
                sushiMenuImages[i].sprite = sushiSprites[level]; // ?マークを寿司画像に変更
                sushiMenuTexts[i].text = sushiNames[level]; // 寿司の名前を表示
            }
        }
    }
    ...省略...
}

これで実行してみたところ以下のエラーが発生。

Sprite was changed for one not readable or with Crunch Compression. Resetting the AlphaHitThreshold to 0. UnityEngine.UI.Image:set_sprite (UnityEngine.Sprite)

新しく追加した寿司画像の「Advanced > Read/Write」にチェックが入っていないことが原因でした。てへぺろ(古い)。

画像の透過部分をクリックできないようにしたとき、まぐろ画像はチェック入れたんだけど、他の画像入れてませんでした。

うしろに寿司を流したい

巨大寿司のうしろが殺風景なので寿司を流したい。自動収益(寿司ロボ)のレベルが1になったら流れ始めて、寿司ネタがアンロックされたら流れる寿司の種類も増えていったら楽しそう。こんな感じで。

頭で想像するのは簡単だけど、実現するのは大変だったばい。

STEP

小さい寿司を流すためのレーンを「UI > Panel」で作ります。これは大きい寿司オブジェクト(Sushi)と同じ階層に作ります。そして大きい寿司オブジェクトよりも上に配置します。

寿司工場12

大きい寿司オブジェクトよりも上に配置するの大事。ヒエラルキーの兄弟オブジェクト(同じ階層にあるオブジェクト)は、上にあるものが後ろ、下にあるものが前に表示されます。

STEP

SushiLane1の下にImageオブジェクトを作成して「RunningSushi」と名付けます。

インスペクターでオブジェクト名の横のチェックを外します。これでオブジェクトが非アクティブになりました。

非アクティブにするのは、ゲーム画面ではこのオブジェクト自体を使わないからです。このオブジェクトから作成したプレハブを元に新しく作成するオブジェクトを使います(ややこしい)。

STEP

RunningSushiのアニメーションを作成します。プロパティは「Rect Transform > Anchored Position」を使います。8秒かけて左から右へ流れていくアニメーションを作りました。

寿司工場13

このとき、Position.xの値を数値で指定しただけではうまくいきませんでした。一定の速度で移動させたいのに、最初はゆっくりで徐々に加速し減速して止まるという動きになってしまいます。これで半日悩みました。

答えはAnimationウインドウの下にある「Curves」をクリックしたところにありました。

寿司工場14

ベジェ曲線みたいなのが表示されました。横軸が時間で縦軸が座標です。ハンドルをいじってこの曲線が直線になるようにすると一定の速度でオブジェクトが移動するようになります。

寿司工場15
STEP

RunningSushiオブジェクトをプレハブ化します。Assetsフォルダの下にPrefabsフォルダを作成し、ヒエラルキーのRunningSushiオブジェクトをPrefabsフォルダにドラッグ&ドロップします。

STEP

逆方向に流れる寿司を作ります。

  1. SushiLane2の下にImageオブジェクトを作成して「RunningSushiReverse」と名付けます。
  2. アニメーションを作ります。
  3. プレハブ化します。

もしかしたら、RunningSushiオブジェクトを元にして逆方向に流れる寿司を作ることができるかもしれませんが、方法が思いつかなかったのでこうなりました。

STEP

スクリプトを書きます。スクリプトでは次のことをしています。

  • コルーチンを使って1秒おきに1つプレハブを元に新しい寿司オブジェクトを生成する。
  • 奇数の寿司レーンでは左から右へ、偶数の寿司レーンでは右から左へ流れるオブジェクトを生成する。
  • おしながきレベルに応じて寿司画像を変更する。
  • 流れる寿司が画面から消えたら削除する。
public class SushiClicker : MonoBehaviour, IPointerClickHandler
{
    ...省略...
    public GameObject[] sushiLanes; // 寿司レーンを格納する配列
    public GameObject runningSushiPrefab; // 流れる寿司画像のプレハブ
    public GameObject runningSushiReversePrefab; // 逆に流れる寿司画像のプレハブ
    ...省略...
    private int runningSushiCount = 0; // 流れる寿司の生成数をカウントする変数

    void Start()
    {
        ...省略...
        StartCoroutine(CreateRunningSushi()); // 流れる寿司のコルーチンを開始
    }

    ...省略...

    // 流れる寿司を作成するコルーチン
    IEnumerator CreateRunningSushi()
    {
        while (true)
        {
            yield return new WaitForSeconds(1f); // 1秒待つ

            if (roboCurrentUpgradeIndex >= 1) // 寿司ロボのレベルが1以上ならば
            {
                for (int i = 0; i < sushiLanes.Length; i++)
                {
                    // プレハブを元に新しいオブジェクトを作成
                    GameObject newSushi = Instantiate(
                        i % 2 == 0 ? runningSushiPrefab : runningSushiReversePrefab,
                        Vector3.zero,
                        Quaternion.identity,
                        sushiLanes[i].transform
                    );
                    // Imageコンポーネントを取得し、Spriteを変更
                    Image image = newSushi.GetComponent<Image>();
                    if (image != null)
                    {
                        int spriteIndex = runningSushiCount % (menuCurrentLevel + 1);
                        image.sprite = sushiSprites[spriteIndex];
                    }
                    // 寿司のアクティブ化と削除
                    newSushi.SetActive(true);
                    Destroy(newSushi, 8f);
                }
                // カウントを増加
                runningSushiCount++;
            }
        }
    }
}

振り返り

  • はじめてゲームらしいゲームを作ることができた。余は満足じゃ。
  • もっといろんな要素を入れたかったけど、時間が足りなかった。(そもそも Game A Week といいながら2週間かかってる
  • 巨大寿司をクリックしたときのアニメーション、1回目だけ大きくて2回目以降が小さくなる現象の原因はわからないままだった。
  • ゲームって思ってた以上にグラフィックやサウンドで面白く感じるようになるもんなんだなぁと思った。もっと見た目にこだわらなきゃいけないね。

このゲームはunityroomで公開しています。

でわでわ

クリッカーゲームを作る(2)

この記事が気に入ったら
いいね または フォローしてね!

シェアしてね

コメント

コメントする

目次