top of page

2Dランゲーム編

Lesson3 ルールを作ろう

3-1

3-1 ゲームステートの実装

3-1 ゲームステートの実装

1

ステートを追加

 まずは今がプレイ中なのか、ゲームオーバー中なのか、ゲームクリア中なのかを判別するための変数を作成しましょう。

 ゲームの状態はGameManagerスクリプトで管理するようにします。

​ GameManagerスクリプトを開いて赤い部分のコードを追加してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

 

public class GameManager : MonoBehaviour
{
    // ゲームの状態
    public enum GameState
    {
        enGameState_Play,           // プレイ中
        enGameState_GameOver,       // ゲームオーバー
        enGameState_Clear,          // ゲームクリア
    }
    [SerializeField, Header("ゲームの状態")]
    GameState m_gameState = GameState.enGameState_Play;
    // ステートを設定
    public void SetState(GameState state)
    {
        m_gameState = state;
    }
    // ステートを取得
    public GameState GetState()
    {
        return m_gameState;
    }

 

    [SerializeField, Header("スコア")]
    int Score = 0;

 

    // スコアを加算
    public void AddScore(int score)
    {
        Score += score;
    }
    // スコアを取得
    public int GetScore()
    {
        return Score;
    }

 

    void Start()
    {
        
    }

    void Update()
    {
        
    }
}

【プログラムの解説】

・enumは列挙型と言い、複数の定数を一つにまとめておくことができます。今回のパターンではenGameState_Play=0、enGameState_GameOver=1、enGameState_Clear=2 といった風に内部的に値が分けられます。

 列挙型についてはC++の教科書なども参考にしてみてください。

​ コードが書けたら保存して、GameManagerのインスペクターを確認してみてください。

 ゲームの状態を表す変数が追加されています。変数の型を列挙型にした場合、インスペクターでの表示も列挙型になります。

3-2

3-2 ゲームオーバーの実装

3-2 ゲームオーバーの実装

1

ゲームマネージャーの取得

 それでは適切なタイミングでゲームの状態を変更してみましょう。今までは仮実装だったゲームオーバーを本格的に実装していきます。

​ PlayerMoveスクリプトを開いて、赤い部分のコードを追加してください。

~前略~
 

    [SerializeField, Header("レイの始点")]
    GameObject m_rayOrigin;
    // 坂に触れているかどうか
    bool m_isSlope = false;
    // 坂道かつ空中にいるかどうか
    bool m_isSlopeAir = false;
    // 重力の初期値を保存
    float m_defGravity = 0.0f;

 

    // 角度変更タイマー
    float angleTimer = 0.0f;
    const float ANGLE_LIMIT = 0.1f;

 

    // アニメーションコントローラー
    Animator m_animator;
    // アニメーション管理用フラグ
    bool m_airFlag;

 

    // ゲームマネージャー
    GameManager m_gameManager;

 

    void Start()
    {
        // 自身にアタッチされているRigidBody2Dを取得する
        m_player_rb2d = GetComponent<Rigidbody2D>();
        // 自身にアタッチされているAnimatorを取得する
        m_animator = GetComponent<Animator>();
        // GameControllerタグつきのオブジェクトにアタッチされているGameManagerを取得する
        m_gameManager = GameObject.FindGameObjectWithTag("GameController").GetComponent<GameManager>();

        // 空中ジャンプ回数を初期化
        m_airJumpCount = MaxAirJump;
        // 重力の初期値を保存
        m_defGravity = m_player_rb2d.gravityScale;
    }

 まずはゲームの状態を管理するためにGameManagerコンポーネントを取得しています。タグの名前を間違えないように注意してください。

2

プレイ中以外の
​動作を制限する

~前略~
 

    // Fixedなので注意!
    void FixedUpdate()
    {
        // プレイ中でないなら中断
        if (m_gameManager.GetState() != GameManager.GameState.enGameState_Play)
        {
            return;
        }

 

        // 常に右へ移動する
        Vector3 move = Vector3.zero;
        move.x = MoveSpeed * Time.deltaTime;
        transform.Translate(move);
    }

 

    void Update()
    {


​~後略~

~前略~
 

        // ジャンプアニメーション切り替え
        if (m_groundCheck.GetIsGround() == false || Input.GetKeyDown(KeyCode.Space))
        {
            m_airFlag = true;
        }
        if (m_airFlag && m_groundCheck.GetIsGround() && m_player_rb2d.velocity.y == 0.0f)
        {
            m_airFlag = false;
            // アニメーションも戻す
            AnimationReset();
        }

    }
 

    // ジャンプ
    void Jump(bool airJump)
    {
        // プレイ中でないなら中断
        if (m_gameManager.GetState() != GameManager.GameState.enGameState_Play)
        {
            return;
        }

 

        // 加わっている力を一旦リセット
        m_player_rb2d.velocity = Vector2.zero;
        // 上方向に力を加える
        m_player_rb2d.AddForce(new Vector2(0.0f, JumpPower), ForceMode2D.Impulse);


​~後略~

~前略~
 

    // 坂道判定
    void Slope()
    {
        // プレイ中でないなら中断
        if (m_gameManager.GetState() != GameManager.GameState.enGameState_Play)
        {
            return;
        }

 

        // タイマー減少
        if (angleTimer > 0.0f)


​~後略~

 関数の途中にreturn; を書くとそこで処理が中断され、以降のコードは実行されなくなります
​ 今回はゲームの状態がプレイ中でない場合は中断して、自動移動、ジャンプ、坂道判定の処理が実行されないようにしました。

3

ゲームステートを
​変更する

~前略~
 

    // ゲームオーバー
    public void GameOver()
    {

        // ゲームの状態を変更する
        m_gameManager.SetState(GameManager.GameState.enGameState_GameOver);
    }


​~後略~

 最後にゲームオーバーになったらゲームステートを切り替えます。

 ここまで入力できたら保存して、ゲームオーバーになるとGameStateがGameOverに切り替わることを確認してみてください。

 また、ゲームオーバーになると右への自動移動やジャンプ操作などが停止することも確認してみましょう。

4

アニメーションを
​繋げる

 次はゲームオーバーの演出を作りましょう。ただし、今作るのはユニティちゃんと演出のみになります。

​ まずは1-7で作成をスキップしたゲームオーバーとゲームクリアのアニメーションの遷移設定をしましょう。

​ AnimatonフォルダからプレイヤーのAnimatorControllerをダブルクリックして開いてください。

 Parametersのプラスボタンをクリックして、新しいパラメータを追加しましょう。

​ 今まではBoolを使ってきましたが、今回はTriggerを使用します。Triggerはfalse/trueの概念がなく、実行した一瞬だけ有効になるパラメータになります。例えるなら、実行した瞬間trueになって、その後自動でfalseに戻るbool型をイメージしてください。

​ Trigger型のパラメータ「GameOver」と「Clear」を作成してください。

 今回は「Any State」というステートを使用します。Any(どれでも)の名の通り、このステートから繋いだステートはどこからでも遷移することができます。RunやJumpなどからチマチマTransitionを繋いでいっても良いのですが、かなり大変なので「どこからでもいいから遷移したい!」という時はAny Stateを使用しましょう。

​ Any Stateを見やすい場所へ移動させて、GameOverとClearへTransitionを繋いでください。

 Transitionの設定をしてください。

【Any State→GameOver】

Transition Duration : 0.1(0にするとエラーが出ます)

Conditions : GameOver
 

【Any State→Clear】

Transition Duration : 0.0

Conditions : Clear

5

ゲームオーバーの
​演出を実装

 これでどこからでも遷移できるステートが完成しました。ゲームオーバーになった瞬間にパラメータを変更しましょう。ついでにユニティちゃんを左上に軽く飛ばす演出も加えます。

​ PlayerMoveスクリプトを開いて、赤い部分のコードを追加してください。

~前略~
 

    // ゲームオーバー
    public void GameOver()
    {
        // プレイ中でないなら中断
        if (m_gameManager.GetState() != GameManager.GameState.enGameState_Play)
        {
            return;
        }


        // ゲームの状態を変更する
        m_gameManager.SetState(GameManager.GameState.enGameState_GameOver);

 

        // アニメーションを変更
        m_animator.SetTrigger("GameOver");

 

        // 重力をリセット
        m_player_rb2d.velocity = Vector2.zero;
        // 重力を戻す
        m_player_rb2d.gravityScale = m_defGravity;
        // 左上に力を加える
        m_player_rb2d.AddForce(new Vector2(-5.0f, 7.0f), ForceMode2D.Impulse);

        // コライダーを無効にする
        GetComponent<CapsuleCollider2D>().enabled = false;

    }


​~後略~

【プログラムの解説】

・SetTriggerは今まで使っていたSetBoolと使い方は同じです。ここでアニメーションをGameOverへ切り替えています。名前の打ち間違いには注意しましょう。

・ほとんどのコンポーネントはenabledというパラメータを持ちます。これはコンポーネントのアクティブを示す値で、falseにすることでコンポーネントを一時的に無効にすることができます。

​ ここではゲームオーバーになった瞬間にプレイヤーの当たり判定を無効にすることで、地形への衝突を防いでいます。

​ ここまで書けたら保存して、地形やギミックに衝突することでゲームオーバーになってみてください。

6

ゲームオーバー時
​カメラを止める

 ゲームオーバーになったらカメラと背景の移動が止まるようにしましょう。

​ GameCameraスクリプトを開いて、赤い部分のコードを追加してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

 

public class GameCamera : MonoBehaviour
{
    GameObject m_player;

 

    [SerializeField]
    Vector3 CameraAddPos = Vector2.zero;

 

    [SerializeField]
    Vector2 CameraMaxPos = Vector2.zero;
    [SerializeField]
    Vector2 CameraMinPos = Vector2.zero;

 

    // ゲームマネージャー
    GameManager m_gameManager;

 

    void Start()
    {
        // ゲームマネージャーを取得
        m_gameManager = GameObject.FindGameObjectWithTag("GameController").GetComponent<GameManager>();

 

        // Playerタグのついたオブジェクトをターゲットにする
        m_player = GameObject.FindGameObjectWithTag("Player");
        // 最初に座標更新しておく
        CameraUpdate();
    }

 

    void Update()
    {
        // プレイヤーがいないなら何もしない
        if (m_player == null)
        {
            return;
        }
        // ゲームオーバーなら何もしない
        if (m_gameManager.GetState() == GameManager.GameState.enGameState_GameOver)
        {
            return;
        }

 

        // 座標の更新
        CameraUpdate();
    }

7

ゲームオーバー時
​背景を止める

 これでゲームオーバーになるとカメラの移動が止まるようになりました。

​ 同じように背景の移動も停止させてみましょう。

 BG_Scrollスクリプトを開いて「ゲームステートがプレイ中でない時は移動しない」スクリプトを書いてください。上記のGameCameraスクリプトのコードを参考にしましょう。

 これでゲームオーバーの処理は一旦完成にしておきます。​後のLessonでゲームオーバーのUIを実装していきます。

3-3

3-3 落下時にゲームオーバーにする

3-3 落下時にゲームオーバーにする

1

落下時の処理を
​追加する

 現在では壁かギミックに衝突することでゲームオーバーになっていますが、穴に落下した際にもゲームオーバーになるようにしましょう。考え方は3Dアクションゲーム編と同じです。

​ PlayerMoveスクリプトを開いて、赤い部分のコードを追加してください。

~前略~

    // ゲームマネージャー
    GameManager m_gameManager;

 

    [SerializeField, Header("落下判定になる高さ")]
    float Y_Border = -10.0f;

 

    void Start()
    {

​~後略~

~前略~
 

        // ジャンプアニメーション切り替え
        if (m_groundCheck.GetIsGround() == false || Input.GetKeyDown(KeyCode.Space))
        {
            m_airFlag = true;
        }
        if (m_airFlag && m_groundCheck.GetIsGround() && m_player_rb2d.velocity.y == 0.0f)
        {
            m_airFlag = false;
            // アニメーションも戻す
            AnimationReset();
        }

 

        // 落下判定
        if(transform.position.y <= Y_Border)
        {
            // ゲームオーバーにする
            GameOver();
        }

    }
 

    // ジャンプ
    void Jump(bool airJump)
    {


​~後略~

 落下判定はUpdate関数内に書いてください。

 これでプレイヤーのY座標がボーダー以下になったらゲームオーバーになります。

​ 落下判定のボーダーはインスペクターで調整してください。

3-4

3-4 ゲームクリアの実装

3-4 ゲームクリアの実装

1

ゴールラインを
​追加

 ゲームクリアを実装していきましょう。

 まずは「ゴールラインにユニティちゃんが触れたら、ゲームステートをClearに変更する」という処理を実装していきます。

​ 「Sprite」→「Gimmick」からGoalの画像を選択して、Mesh Typeを「Full Rect」に変更してください。これで背景と同じように画像がループする設定になります。

2

ゴールラインの
​画像を調整

 Goalの画像をシーン上にドラッグ&ドロップしてください。

 

 ゴールラインの画像を調整しましょう。

 Draw Typeを「Tiled」に変更してHeightの値を大きくすると、縦にループする画像になります。座標や大きさ、優先度などもお好みで変更してください。

3

タグとレイヤーの
​設定

 GoalオブジェクトにGoalタグを追加して設定してください。今は使いませんが、後ほどUIを作成する際に必要になります。

​ また、レイが衝突しないようにLayerを「Ignore Raycast」に変更しておいてください。

4

当たり判定を追加

 GoalオブジェクトにBox Collider 2Dをアタッチしてください。

​ Is Triggerにチェックを入れ、Sizeを調整してください。SizeはSprite RendererのSizeと同じにするとちょうどよくなります。

5

ステートを
​変更する

 それでは「ゴールラインにユニティちゃんが触れたら、ゲームステートをClearに変更する」処理を実装していきましょう。

 まずはPlayerMoveスクリプトにクリア用の関数を追加します。

​ PlayerMoveスクリプトを開いて、赤い部分のコードを追加してください。

~前略~
 

    // ゲームオーバー
    public void GameOver()
    {
        // プレイ中でないなら中断
        if (m_gameManager.GetState() != GameManager.GameState.enGameState_Play)
        {
            return;
        }

        // ゲームの状態を変更する
        m_gameManager.SetState(GameManager.GameState.enGameState_GameOver);

        // アニメーションを変更
        m_animator.SetTrigger("GameOver");

 

        // 重力をリセット
        m_player_rb2d.velocity = Vector2.zero;
        // 左上に力を加える
        m_player_rb2d.AddForce(new Vector2(-5.0f, 7.0f), ForceMode2D.Impulse);

 

        // コライダーを無効にする
        GetComponent<CapsuleCollider2D>().enabled = false;
    }

 

    // ゲームクリア
    public void GameClear()
    {
        // プレイ中でないなら中断
        if (m_gameManager.GetState() != GameManager.GameState.enGameState_Play)
        {
            return;
        }

        // ゲームの状態を変更する
        m_gameManager.SetState(GameManager.GameState.enGameState_Clear);
    }

 

    void AnimationReset()
    {
        // アニメーションのパラメータをリセットする
        m_animator.SetBool("JumpFlag", false);
        m_animator.SetBool("AirJumpFlag", false);
        m_animator.SetBool("FallFlag", false);
    }
}

6

ゴールの処理を
​実装する

 Goalスクリプトを作成して、以下のように入力してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

 

public class Goal : MonoBehaviour
{
    private void OnTriggerEnter2D(Collider2D collision)
    {
        // もしプレイヤーと衝突したら…
        if (collision.CompareTag("Player"))
        {
            // ゲームクリアにする
            collision.GetComponent<PlayerMove>().GameClear();
        }
    }
}

 コードが書けたら保存して、GoalオブジェクトにGoalスクリプトをアタッチしてください。

​ ゲームを実行して、ゴールするとゲームステートがClearに切り替わることを確認してみてください。

7

ゴール演出を
​追加する

​ よりクオリティを高めるために、ゴール演出を実装しましょう。

 ゴールラインに触れる→しばらくゆっくり右へ移動→ユニティちゃんがクリアアニメーションをする という流れにしていきます。

​ まずはクリアアニメーションに使う変数を追加しましょう。

​ PlayerMoveスクリプトを開いて、赤い部分のコードを追加してください。

~前略~
 

    [SerializeField, Header("落下判定になる高さ")]
    float Y_Border = -10.0f;

 

    // クリア演出用
    [SerializeField, Header("クリア演出用"),Tooltip("クリアアニメーションまで待つ時間")]
    float ClearRunTime = 1.0f;
    [SerializeField, Tooltip("クリアアニメーションまで走る速さ")]
    float ClearRunSpeed = 3.0f;
    // 演出フラグ
    bool m_claerRun, m_claerWait;

 

    void Start()
    {

~後略~

【プログラムの解説】

・Tooltipはアトリビュートの一種で、変数名にマウスカーソルが重なった時に注釈を表示させることができます。

​ 自分で作った変数の用途を後で忘れることはよくあるので、複雑な用途の変数に注釈をつけて確認しやすいようにしておくと良いでしょう。

 追加した変数を使って、クリア演出を実装します。

 内部的な流れとしては ゲームクリアステートになって、地面に接地していたらしばらく歩く→歩き終わったらクリアアニメーション再生 という流れです(完璧に理解する必要はありません)

​ PlayerMoveスクリプトを開いて、赤い部分のコードを追加してください。​細かい部分が変わっているので注意してください。

~前略~
 

    // Fixedなので注意!
    void FixedUpdate()
    {
        // ゲームオーバーなら中断
        if (m_gameManager.GetState() == GameManager.GameState.enGameState_GameOver)
        {
            return;
        }
        // クリア演出の移動待機が終わっていたら中断
        if (m_claerWait)
        {
            return;
        }

 

        // 常に右へ移動する
        Vector3 move = Vector3.zero;
        move.x = MoveSpeed * Time.deltaTime;
        // クリア中ならゆっくり移動するように補正する
        if (m_gameManager.GetState() == GameManager.GameState.enGameState_Clear)
        {
            move.x /= ClearRunSpeed;
        }

        transform.Translate(move);
    }


~後略~

​ ここではゴールした後しばらくの間、右へゆっくり移動する処理を実装しています。

 PlayerMoveスクリプトを開いて、赤い部分のコードを追加してください。​

~前略~
 

        // 落下判定
        if(transform.position.y <= Y_Border)
        {
            // ゲームオーバーにする
            GameOver();
        }

 

        // ゲームクリア演出
        // クリア中かつ移動中でない時

        if(m_gameManager.GetState() == GameManager.GameState.enGameState_Clear &&
            m_claerRun == false)
        {
            // 接地したら移動待機状態になる
            if (m_groundCheck.GetIsGround())
            {
                m_claerRun = true;
                // (ClearRunTime)秒待ってからアニメーションする
                Invoke("GameClearAnimation", ClearRunTime);
            }
        }

 

    }
 

    // ジャンプ
    void Jump(bool airJump)
    {


~後略~

~前略~
 

    // ゲームクリア
    public void GameClear()
    {
        // プレイ中でないなら中断
        if (m_gameManager.GetState() != GameManager.GameState.enGameState_Play)
        {
            return;
        }

 

        // ゲームの状態を変更する
        m_gameManager.SetState(GameManager.GameState.enGameState_Clear);
    }

 

    // クリア演出
    void GameClearAnimation()
    {
        // もう終わっている場合は中断
        if (m_claerWait)
        {
            return;
        }

 

        // アニメーションを変更
        m_animator.SetTrigger("Clear");

 

        // ゲームクリア演出終了
        m_claerWait = true;
    }

 

    void AnimationReset()
    {


~後略~

​​【プログラムの解説】

Invoke関数は指定した関数を一定秒数後に呼び出すことができる関数です。k2Engineではタイマーを設定するなどしていたと思いますが、Unityでは単純に一定秒数後に呼び出すだけならInvoke関数を使うと便利です。第一引数に関数名、第二引数に待機時間を設定します。

 Invoke(呼び出す関数の名前,何秒後に呼び出すか);

※ 関数名で検索しているので名前間違いに注意!

 ここまで書けたら保存してください。

Invoke

 他にも便利なInvokeに類似する関数があります。

 InvokeRepeating関数は第一引数に指定した名前の関数が(第二引数)秒後に呼び出され、その後(第三引数)秒ごとに繰り返し呼ばれるというものです。

 例えば InvokeRepeating("Hoge", 5, 1); と指定すると、関数Hogeが5秒後に呼ばれ、それ以降は1秒ごとに繰り返し呼ばれ続けるようになります。

 InvokeRepeating(呼び出す関数の名前, 呼び出す秒数, 何秒ごとに呼び出すか);

 CancelInvoke関数はInvokeの実行を止めることができます。前述したInvokeRepeating関数の実行を止める時にも使えます。

 CancelInvoke(止める関数の名前);

 ただしInvoke関数は引数や戻り値を使用できず、処理を途中で止めたり変更することができないので、高度なタイマー処理を実装するには不向きです。​引数などを使いたい場合はコルーチンを使うようにしましょう(参考サイト

Unity Tips!

​ コードが書けたら保存して、実際にゴールしてみてください。​ゴールするとしばらくゆっくり移動して、クリアアニメーションが再生されます。

8

カメラのアニメーションを作成

​ クリア時はユニティちゃんのポーズが見えやすいようにカメラを拡大させましょう。

​ カメラの拡大演出もアニメーションで制御します。

​ Animationフォルダ内にCameraAnimationフォルダを作成してください。

​ 「Create」→「Animaton」を選択して、CameraAnimationフォルダ内にCameraWaitアニメーションを作成してください。

​ 作成したアニメーションをヒエラルキー内のMain Cameraにドラッグ&ドロップしてください。

​ CameraWaitアニメーションをダブルクリックして、Animatonウィンドウを開いてください。

 

 ヒエラルキー内のMain Cameraをクリックした後、アニメーション名をクリックして「Create New Clip…」を選択すると新しいアニメーションを作成することができます​。作成するアニメーションの名前をCameraClearにして保存してください。

​ CameraWaitアニメーションは通常時の待機用アニメーションなので、中身を作る必要はありません。

​ それでは、クリア時に再生するズームアニメーションを作成していきましょう。編集しているアニメーションがCameraClearアニメーションになっていることを確認してください。

​ 「Add Property」を選択して、「Camera」→「Orthographic size」横のプラスボタンをクリックして項目を追加してください。

​ パラメータを設定していきます。新しいキーを追加して、中間に配置してください。

​ 最初のキーの値は初期値である6にしておきます。

​ 中間のキーは大きくズームするために2にしておきます。

​ 最後のキーはバウンドするように3にしておきます。

​ サンプルゲームでは中間のキーを12フレーム目、最後のキーを20フレーム目に配置しています。

 キーの配置やパラメータはお好みで変更して構いません。再生ボタンでプレビューしながら調整してください。

 このままでは中央にズームするだけで、肝心のユニティちゃんが画面から外れてしまいます。

​ カメラの移動も同時に実行するようにしましょう。

 「Add Property」→「Transform」→「Position」と選択して、座標の項目を追加してください。

​ 最初のキーの値は初期値でOKです。

​ 最後のキーでX座標を-5してください。

​ 移動方法を相対移動にするために、Main CameraのAnimatorのApply Root Motionにチェックを入れてください(相対移動については2-4を参照)

​ クリア時のズームアニメーションがループしないように、CameraClearアニメーションのLoop Timeのチェックを外しておいてください。

9

アニメーションの
​遷移を設定

​ アニメーションの遷移を設定していきましょう。

 

 プロジェクト内に自動で追加されたMain Camera(Animator Controller)をダブルクリックして、Animatorウィンドウを開いてください。

​ 新しくトリガー型のパラメータを追加してください。​名前はClearにしておきます。

​ CameraWaitからCameraClearに伸びるTransitionを作成してください。

 Has Exit Timeのチェックを外し、Transition Durationを0にしておきます。

​ 遷移する条件に先ほど作成したClearを設定してください。

10

アニメーターの
パラメータを操作

​ ゲームクリアした瞬間にパラメータを操作するスクリプトを書きましょう。

​ GameCameraスクリプトを開いて、赤い部分のコードを追加してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

 

public class GameCamera : MonoBehaviour
{
    GameObject m_player;

 

    [SerializeField]
    Vector3 CameraAddPos = Vector2.zero;

    [SerializeField]
    Vector2 CameraMaxPos = Vector2.zero;
    [SerializeField]
    Vector2 CameraMinPos = Vector2.zero;

 

    // ゲームマネージャー
    GameManager m_gameManager;

 

    // アニメーター
    Animator m_animator;
    // クリアアニメーションフラグ
    bool m_clearAnimFlag = false;

 

    void Start()
    {
        // ゲームマネージャーを取得
        m_gameManager = GameObject.FindGameObjectWithTag("GameController").GetComponent<GameManager>();

 

        // 自身にアタッチされているアニメーターを取得
        m_animator = GetComponent<Animator>();

 

        // Playerタグのついたオブジェクトをターゲットにする
        m_player = GameObject.FindGameObjectWithTag("Player");
        // 最初に座標更新しておく
        CameraUpdate();
    }

 

    void Update()
    {
        // プレイヤーがいないなら何もしない
        if (m_player == null)
        {
            return;
        }
        // ゲームオーバーなら何もしない
        if (m_gameManager.GetState() == GameManager.GameState.enGameState_GameOver)
        {
            return;
        }
        // クリアアニメーション後なら何もしない
        if (m_clearAnimFlag)
        {
            return;
        }

 

        // 座標の更新
        CameraUpdate();
    }

 

    void CameraUpdate()
    {
        // カメラの位置を設定
        transform.position = m_player.transform.position + CameraAddPos;

 

        // 座標がオーバーしないように調整
        Vector3 cameraPos = transform.position;
        cameraPos.x = Mathf.Clamp(cameraPos.x, CameraMinPos.x, CameraMaxPos.x);
        cameraPos.y = Mathf.Clamp(cameraPos.y, CameraMinPos.y, CameraMaxPos.y);
        transform.position = cameraPos;
    }

 

    // クリアアニメーション
    public void CameraClearAnimation()
    {
        // アニメーション再生
        m_animator.SetTrigger("Clear");

        // アニメーションフラグを立てる
        m_clearAnimFlag = true;
    }

}

11

クリア時の
​処理を追加する

​ CameraClearAnimation関数はpublicになっているので、適切なタイミングで外部から呼び出しましょう。

​ PlayerMoveスクリプトを開いて、赤い部分のコードを追加してください。

~前略~
 

    // クリア演出
    void GameClearAnimation()
    {
        // もう終わっている場合は中断
        if (m_claerWait)
        {
            return;
        }

        // アニメーションを変更
        m_animator.SetTrigger("Clear");

 

        // カメラ演出
        Camera.main.GetComponent<GameCamera>().CameraClearAnimation();

 

        // ゲームクリア演出終了
        m_claerWait = true;
    }


~後略~

​​【プログラムの解説】

・Camera.main でメインカメラ(画面に表示しているカメラ)を取得することができます。

 これでゲームクリアになった瞬間にカメラのアニメーションも再生されるようになりました。

​ 実行してクリア時にカメラがズームすることを確認してみてください。ユニティちゃんが画面から外れてしまう場合は、CameraClearアニメーションのX座標の移動量を調整してください。

​ これで一通りのゲームのルールは実装できました。

​ 次のレッスンではUIを作成して、スコアや進行状況を確認できるようにしてみましょう。

まとめ

・Animatorの「Any State」から繋げたアニメーションはどのステートからでも遷移できる

・Invoke関数は「指定した関数をX秒後に実行する」という非同期処理が行える

評価テスト

評価テスト

河原電子ビジネス専門学校
​ゲームクリエイター科

bottom of page