超初心者のゲーム開発記~Unity~

超初心者がUnityでゲーム(目標はAndroidアプリ )を開発していくブログです!

【Unity 2Dローグライク】公式チュートリアルをやってみる part.12~敵のアニメーションの管理

こんにちは!ヤギです!

Unityの2Dローグライクの
公式チュートリアルをやってみる part.12になります!
※前回(part.11)の記事はこちら
www.yagigame.com

記事概要

今回の記事では、敵のアニメーションの管理についてご説明していきます。
※part.12に対応する公式チュートリアルの章は、Enemy Animator Controllerです!
unity3d.com
※この記事は、ひよこのたまご様の記事をリスペクトしています。
hiyotama.hatenablog.com

敵のアニメーションコントローラの修正

1. Enemy1のアニメーションコントローラを開きます。
2. Enemy1IdleとEnemy1Attackを右クリックし、Make Transitionで矢印を結びます。
3. Animator view > Parameters > +をクリックし、アニメーションを遷移させるTriggerを新規作成します。
※名前はEnemyAttackとします。
f:id:yagigame:20181104164537p:plain
4. Enemy1IdleからEnemy1Attackに遷移する矢印をクリックし、Inspector viewを開きます。
5. Conditionsに先ほど作成した、EnemyAttackを設定します。
f:id:yagigame:20181104164707p:plain
6. Enemy1Idleはループして表示するため、Has Exit Timeのチェックを外し、アニメーションを即座に切り替えるため、Transition Durationを0にします。
f:id:yagigame:20181104164951p:plain
7. Enemy1AttackからEnemyIdleにつながる矢印をクリックし、Inspector viewを開きます。
8. Enemy1Attackは一定時間表示したら、自動でEnemy1Idleに戻るため、Has Exit Timeもチェックをつけたままにします。
9. 一定時間表示する時間を設定するために、Exit Timeを1と設定します。
10. アニメーションを即座に切り替えるため、Transition Durationを0にします。
※8~10の設定後のInspector viewは以下の通りです。
f:id:yagigame:20181104165351p:plain

※これで敵のアニメーションコントローラが完成しました!

GameManager.csの修正

GameManager.csをゲーム内のターンなどを管理できるように修正していきます。
※ソース内に解説を記載いたしました。ご参照ください。

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

public class GameManager : MonoBehaviour
{

    //ここからpart.12で追加
    public float turnDelay = .1f; //1ターンの時間
    private List<Enemy> enemies; //複数の敵を管理
    private bool enemiesMoving; //敵の移動フラグ
    //ここまでpart.12で追加

    //クラスに属し、複数のシーンで使われる変数を宣言
    //Staticにすることで、他のスクリプトからも呼び出すことができます
    public static GameManager instance = null;

    //ここから:part.10で追加
    public int playerFoodPoints = 100; //プレイヤーの食料
    //HideInspectorをつけることで、Inspector viewに表示されなくなる
    [HideInInspector] public bool playerTurn = true; //プレイヤーのターンかの判定フラグ
    //ここまで:part.10で追加

    //BoardManager型の変数を宣言
    private BoardManager boardScript;

    //テストとして、敵が出現するレベルの3とする
    private int level = 3;

    // AwakeはStartよりも前、最初に呼ばれる
    void Awake()
    {
        //GameManagerが存在しなければ、このオブジェクトを設定する
        if (instance == null)
            instance = this;

        else if (instance != this)
            //すでに存在する場合、このオブジェクトは不要なため破壊する
            Destroy(gameObject);

        //シーン遷移時に、このオブジェクトは破壊せず引き継ぐ
        DontDestroyOnLoad(gameObject);

        //ここからpart.12で追加
        enemies = new List<Enemy>(); //敵を初期化
        //ここまでpart.12で追加

        //BoardManagerのコンポーネントを取得
        boardScript = GetComponent<BoardManager>();
        //ステージ生成の関数を呼ぶための、関数を呼ぶ
        InitGame();
    }

    void InitGame()
    {
        //ここからpart.12で追加
        enemies.Clear(); //ステージ移動時は敵をリセットする
        //ここまでpart.12で追加

        //ステージ生成の関数を呼ぶ
        boardScript.SetupScene(level);
    }

    //ここまでpart.10で追加

    //ここからpart.12で追加
    void Update()
    {
        //プレイヤーのターンか、敵の動いている場合は、アップデートしない
        if (playerTurn || enemiesMoving)
            return;
        //敵の動いていない、敵のターンのみ敵を動かす
        StartCoroutine(MoveEnemies());
    }

    //敵をリストに加える処理
    public void AddEnemyList(Enemy script){
        enemies.Add(script);
    }

   //敵を移動させる処理
    IEnumerator MoveEnemies()
    {
        //エネミー移動フラグをtrueにする
        enemiesMoving = true;
        //1ターン待つ
        yield return new WaitForSeconds(turnDelay);
        //敵がいなければ
        if (enemies.Count == 0)
        {
            //1ターン待つ
            yield return new WaitForSeconds(turnDelay);
        }
        //敵の数だけ、敵を移動させる
        for (int i = 0; i < enemies.Count; i++)
        {
            enemies[i].MoveEnemy();
            //1ターン待つ
            yield return new WaitForSeconds(turnDelay);
        }

        //プレイヤーのターンにする
        playerTurn = true;
        enemiesMoving = false;
    }
    //ここまでpart.12で追加

    //ここかpart.10で追加
    public void GameOver()
    {
        //enabledをfalseにすることで、GameManagerが無効になる
        enabled = false;
    }
}

※これでGameManager.csの修正は完了です。

Enemy.csの修正

最後に、Enemy.csに敵の攻撃アニメーションの呼び出しなどを追加しましょう。
※ソースの中に解説を記載しています!

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

//MovingObjectを継承する
public class Enemy : MovingObject {

    public int playerDamage; //プレイヤーへのダメージ

    private Animator animator;
    private Transform target; //プレイヤー場所
    private bool skipMove; //動くか判定


	// Use this for initialization
    //継承クラス
    protected override void Start () {

        //ここからpart.12で追加
        //敵をリストに加える
        GameManager.instance.AddEnemyList(this);
        //ここまでpart.12で追加

        //Animatorコンポーネント取得
        animator = GetComponent<Animator>();
        //プレイヤーの場所を取得する
        target = GameObject.FindGameObjectWithTag("Player").transform;
        //MovingObjectクラスのStartを呼び出す
        base.Start();
	}

    //敵のターンか判定、移動を試みる処理
    protected override void AttemptMove<T>(int xDir, int yDir)
    {
        //敵のターンではない場合
        if(skipMove){
            //敵のターンにする
            skipMove = false;
            return;
        }

        base.AttemptMove<T>(xDir, yDir);
        //敵のターンを終わる
        skipMove = true;
    }

    //敵を移動させる処理
    public void MoveEnemy(){
        int xDir = 0; //左右の移動量
        int yDir = 0; //上下の移動量

        //敵とプレイヤーの左右の距離がほぼ0の場合
        if(Mathf.Abs(target.position.x - transform.position.x) < float.Epsilon){
            //プレイヤーが上にいれば、1とし、下にいれば、-1とする
            yDir = target.position.y > transform.position.y ? 1 : -1;
        }else{
            //プレイヤーが右にいれば、1とし、左にいれば、-1とする
            xDir = target.transform.position.x > transform.position.x ? 1 : -1;
        }
        //移動する
        AttemptMove<Player>(xDir, yDir);
    }

    //敵が移動できない時の処理
    protected override void OnCantMove<T>(T component)
    {
        //衝突したプレイヤーを設定
        Player hitPlayer = component as Player;

        //ここからpart.12で追加
        //プレイヤーに攻撃するアニメーションを呼び出す
        animator.SetTrigger("EnemyAttack");
        //ここまでpart.12で追加

        //プレイヤーの食料を減らす
        hitPlayer.LoseFood(playerDamage);
    }
}

※これでEnemy.csの修正は完了です。

Enemy Prefabの設定を修正する

作成したEnemy.csをEnemyにアタッチしましょう。
1. Prefabs > Enemy1とEnemy2をシフトを押しながらクリックし、両方選択します。
2. 画面上部のConponent > Scripts > Enemyをクリックし、Enemy.csをアタッチします。
f:id:yagigame:20181104172740p:plain
3. Enemy PrefabのInspector > Blocking Layer をblocking Layerに設定します。
f:id:yagigame:20181104172927p:plain
4. Enemy PrefabのInspector > Player Damegeに任意の数値を設定します。
f:id:yagigame:20181104173054p:plain
※これで、Enemy Prefabの設定も完了です!

ゲームを実行してみよう!

ここまででゲームを実行してみましょう!
プレイヤーや敵がスムーズに動くことが確認できると思います!!!
f:id:yagigame:20181104180101p:plain

次回予告

次回の記事では、画面のUIや、ステージのレベル管理について書いていきたいと思います。
※次回の記事はこちら
www.yagigame.com
※Unityのチュートリアルの章としては、次回は(Adding UI & Level Transitions)となります!

読んでいただきありがとうございました!