【自作ゲーム開発15】戦闘エリアの設定【Unity】


注意
本記事で掲載されている動作の実装方法及びプログラムのソースコードは最適な方法ではない可能性があります。
今後不具合等が判明した場合には修正及び改良をおこなう可能性があります。
また今後自分で同機能を実装する場合の参考にする可能性もあるためソースコードだけではなく説明しつつ記事を進めていきます。

はじめに

Unityによる自作ゲーム開発進捗その15になります!

今回は透明の壁を設置して戦闘エリアの設定をしていきます。

キャラクター同士はお互いがすり抜けられるようにしつつ透明の壁には当たるようにします。

既存のスクリプトを1つ更新します。

以下にソースコードを掲載します。

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

public class CharacterManager : MonoBehaviour {
    [SerializeField]
    private GameObject m_mob_prefab;

    [SerializeField]
    private HeroPlayer m_hero_script;

    [SerializeField]
    private MagePlayer m_mage_script;

    [SerializeField]
    private DragoonPlayer m_dragoon_script;

    [SerializeField]
    private PopSystem[] m_pop_point = new PopSystem[3];

    private List<GameObject> m_mob_prefab_list = new List<GameObject>();
    private List<AssultEnemy> m_mob_prefab_script = new List<AssultEnemy>();

    private GameObject[] m_left_base = new GameObject[5];
    private GameObject[] m_center_base = new GameObject[5];
    private GameObject[] m_right_base = new GameObject[5];

    private float m_time_count = 0.0f;

    private int m_left_state = 2;
    private int m_center_state = 2;
    private int m_right_state = 2;

    private short m_mob_count = 0;

    private void Start() {
        m_mob_count = 30;

        string l_line = "Left";

        for (int l_loop = 0; l_loop < m_mob_count; l_loop += 1) {
            if (l_loop == m_mob_count / 3) l_line = "Center";
            if (l_loop == m_mob_count - (m_mob_count / 3)) l_line = "Right";
            var l_instance = Instantiate(m_mob_prefab, new Vector3(75.0f, 0.0f, 65.0f), Quaternion.Euler(0, 0, 0));
            l_instance.SetActive(false);
            m_mob_prefab_list.Add(l_instance);
            m_mob_prefab_script.Add(l_instance.GetComponent<AssultEnemy>());
            m_mob_prefab_script[l_loop].Initialize(l_line);
        }

        for (int l_loop = 0; l_loop < 3; l_loop += 1) {
            // タスク2
            m_left_base[l_loop] = GameObject.Find(string.Format("LeftBase{0}", l_loop));
            m_center_base[l_loop] = GameObject.Find(string.Format("CenterBase{0}", l_loop));
            m_right_base[l_loop] = GameObject.Find(string.Format("RightBase{0}", l_loop));
        }

        m_hero_script.Initialize("Left"); // タスク3
        m_mage_script.Initialize("Center"); // タスク3
        m_dragoon_script.Initialize("Right"); // タスク3
    }

    private void Update() {
        m_time_count += Time.deltaTime;

        if (m_time_count > 1.0f) {
            BaseCheck();
            ActiveObject();
        }
    }

    private void BaseCheck() {
        if (!m_left_base[m_left_state].activeSelf) {
            m_left_state -= 1;

            if (m_left_state < 0) m_left_state = 0;

            switch (m_left_state) {
                case 1:
                    m_pop_point[0].MoveObject(new Vector3(50.0f, 0.5f, 90.0f));
                    break;

                case 0:
                    m_pop_point[0].MoveObject(new Vector3(50.0f, 0.5f, 65.0f));
                    break;
            }

            for (int l_loop = 0; l_loop < m_mob_count / 3; l_loop += 1) {
                m_mob_prefab_script[l_loop].BaseChange(m_left_state);
            }

            m_hero_script.BaseChange(m_left_state); // タスク3
        }

        if (!m_center_base[m_center_state].activeSelf) {
            m_center_state -= 1;

            if (m_center_state < 0) m_center_state = 0;

            switch (m_center_state) {
                case 1:
                    m_pop_point[1].MoveObject(new Vector3(75.0f, 0.5f, 90.0f));
                    break;

                case 0:
                    m_pop_point[1].MoveObject(new Vector3(75.0f, 0.5f, 65.0f));
                    break;
            }

            for (int l_loop = m_mob_count / 3; l_loop < m_mob_count - (m_mob_count / 3); l_loop += 1) {
                m_mob_prefab_script[l_loop].BaseChange(m_center_state);
            }

            m_mage_script.BaseChange(m_center_state); // タスク3
        }

        if (!m_right_base[m_right_state].activeSelf) {
            m_right_state -= 1;

            if (m_right_state < 0) m_right_state = 0;

            switch (m_right_state) {
                case 1:
                    m_pop_point[2].MoveObject(new Vector3(110.0f, 0.5f, 90.0f));
                    break;

                case 0:
                    m_pop_point[2].MoveObject(new Vector3(110.0f, 0.5f, 65.0f));
                    break;
            }

            for (int l_loop = m_mob_count - (m_mob_count / 3); l_loop < m_mob_count; l_loop += 1) {
                m_mob_prefab_script[l_loop].BaseChange(m_right_state);
            }

            m_dragoon_script.BaseChange(m_right_state); // タスク3
        }
    }

    private void ActiveObject() {
        m_time_count = 0.0f;

        for (int l_loop = 0; l_loop < m_mob_count / 3; l_loop += 1) {
            if (m_mob_prefab_list[l_loop].activeSelf == false) {
                m_mob_prefab_list[l_loop].SetActive(true);
                m_mob_prefab_script[l_loop].MobState(true);
                break;
            }
        }

        for (int l_loop = m_mob_count / 3; l_loop < m_mob_count - (m_mob_count / 3); l_loop += 1) {
            if (m_mob_prefab_list[l_loop].activeSelf == false) {
                m_mob_prefab_list[l_loop].SetActive(true);
                m_mob_prefab_script[l_loop].MobState(true);
                break;
            }
        }

        for (int l_loop = m_mob_count - (m_mob_count / 3); l_loop < m_mob_count; l_loop += 1) {
            if (m_mob_prefab_list[l_loop].activeSelf == false) {
                m_mob_prefab_list[l_loop].SetActive(true);
                m_mob_prefab_script[l_loop].MobState(true);
                break;
            }
        }
    }
}

/*
    [規則]
    p_ 外部アクセス
    m_ メンバー変数
    l_ ローカル変数
    a_ 引数

    [説明]

    [バージョン]
    2020-12-12 指定数生成及びプーリング呼び出し
    2021-03-12 管理拠点を配列化し拠点管理を行いモブに伝える
    2021-03-17 センターライン指揮官キャラの生成と名前変更(旧CenterMobManagerEnemy)
    2021-03-25 戦闘ラインを1から3ラインに変更
    2021-04-05 敵キャラクター生成位置を真ん中へ(左下では生成時にナビエリアが遠くエラーが出る)

    [タスク]
    (済)タスク1 プレイヤーキャラのステータスを反映させる
    (済)タスク2 臨時防衛拠点数
    タスク3 メニュー画面から各ラインのキャラクターを受け取るようにする
*/

見えない壁と当たり判定

戦闘エリアを決める壁は【Is Trigger】のチェックを外したコライダーと【Nav Mesh Obstacle】の【Crave】にチェックを入れた物を使用しています。

現在は敵と味方のコライダーの【Is Trigger】にチェックを入れているので敵が【Nav Mesh Agent】を停止させて吹き飛ばした際に他の敵味方に接触しないようになっていますが、このままでは壁にも接触しなかったため【レイヤー】で当たり判定を変更する事にしました。

【Character】のレイヤーを作成して敵味方キャラクターのレイヤーを設定しレイヤーの接触チェックを外しました。

敵味方キャラクターのコライダーの【Is Trigger】のチェックを外して壁に当たるようにしつつレイヤーで【Character】がお互いに接触しないようにしました。

戦闘エリアの設定に伴い【自作ゲーム開発12】でインポートしたアセットを使用して今まで殺風景だった地面に土の見た目を反映させてみました。


動画


記事のリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です