【Unity2d】イベントを発動する仕組みを作る

Unity2D

Unity2D ARPG

こんにちは。なおキーヌです。

ブログ毎日更新は363日目になります。

プレイヤーが調べるとイベントが発動するという仕組みを作ります。

最初のエリアでハンマーを取るときや壊せる岩を調べた時にそのオブジェクトがもつイベント情報を取得し、
それをイベント駆動配列にAddすればイベントシーンに切り替わるという仕組みがよさそうです。

既に押す引く処理で似たような処理を作っているのでそれの応用ですね。

ステータスにイベントキューを作る

プレイヤーのステータスにイベント用のキュー配列を作っておきましょう。

イベントキューは毎フレーム監視しておき、キューに1つでも要素が入ったときイベントシーンに切り替わるようにします。

State_Playerに以下を追記しましょう。

  // イベントキュー(プレイヤーステータス専用
  private static List<string> _eventQueue;
  // _eventQueueのプロパティ
  public List<string> getEventQueue{
      get { return State_Player._eventQueue; }
  }  
  public string setEventQueue{
      set { State_Player._eventQueue.Add(value); }
  }

  protected override void Start() {
    // コントローラープレイヤースクリプトの取得
    _cm = GameObject.FindGameObjectsWithTag("Controller_Manager")[0].GetComponent<Controller_Player>();
    // アニメーターを取得
    _animator = GameObject.FindGameObjectsWithTag("Player")[0].GetComponent<Animator>();
    _hammer = GameObject.FindGameObjectsWithTag("Weapon")[0].GetComponent<Animator>();

    // マップのエリア座標リストを取得(一旦リテラルで表記
    _trialMapVector2 = new List<Vector2>() {
      new Vector2(240,712), new Vector2(528,712), new Vector2(816,712), new Vector2(1104,712),
      new Vector2(240,520), new Vector2(528,520), new Vector2(816,520), new Vector2(1104,520),
      new Vector2(240,328), new Vector2(528,328), new Vector2(816,328), new Vector2(1104,328),
      new Vector2(240,136), new Vector2(528,136), new Vector2(816,136), new Vector2(1104,136)
    };

    // イベントキューの初期化
    _eventQueue = new List<string>();
  }

  // イベント一括セット関数
  public void allSetEventQueue (string[] eventList ) {
    for (int i = 0; i < eventList.Length; i++) {
      setEventQueue = eventList[i];
    }
  }

  // イベントを1つ取り出す関数
  public string getEventData () {
    // 返す用のローカル変数定義
    int getEventNo = "";

    // イベントキュー配列に1つでもあれば取り出す
    if (EventQueue.Count() > 0) {
      // 0個目の値を取り出す
      getEventNo = getEventQueue[0];
      // 0個目の値を削除
      getEventQueue.RemoveAt(0);
    }

    // 取り出した値を返す
    return getEventNo;

  }

このようにイベントキュー変数をState_Player側でprivate変数として用意し、
一応ゲッターとセッターを作っておきます。

プロパティをsetとgetで分けているのは型の問題です。

getはList型のstringを返しますが、setはstring型を受け取りたいので一緒にすることはできませんでした。

セッターはイベントを調べた時にリストにAddできるようにしておけばイベント発生がかなり楽ですね。

イベントキューに入れるときはint配列をまとめて挿入する関数を利用して、
取り出す時は0個目を取り出す関数を使用します。

取り出す関数はイベントマネージャーで利用するのでpublicにしておきました。

正直どこまで必要かはわかりませんが、関数が要らなかった場合後から削除してもOKです。

後はこの変数を監視しておけばOKです。

  protected override void Update() {
    // イベントキューを監視
    if (EventQueue.Count() == 0) {
      // フリーズ対策のイベントモードを解除


      switch(this.GameSceneState) {
        // 操作可能モード
        case 0:
          // 十字キーが一つでも格納されてたら稼働
          if (_cm.PushedArrowKeyList.Count > 0) { setDirection(_cm.PushedArrowKeyList); }
          // ステートをセットする
          setState(_cm.PushedKeyList,_cm.PushedArrowKeyList);
          // 向きとステートを元にアニメーションを設定
          setNowAnim(_animator, _hammer);
          // 移動タイプ変更
          setMoveType();
          break;

        // エリアスクロールモード
        case 1:
        case 2:
        case 3:
        case 4:
          // 向きとステートを元にアニメーションを設定
          setNowAnim(_animator, _hammer);
          break;
      }
    } else {
      // イベントキューが1つ入っていればイベントモードにする

    }
  }

イベントキュー監視はこんな感じにします。

移動イベントで「_gameSceneState」で管理してましたね。

イベントはこの変数で管理していくので移動イベントも後にキューにイベントリストを渡すように修正していきましょう。

現状ステート1~4が移動処理になっているので、5をメッセージイベントと見立てて組み立てます。

イベントスプライトを調べられるようにする

これはもう押す引くで基本的な処理が出来上がっているのでそれを利用します。

向いてる方向に決定ボタンを押したら調べるというものにしましょう。

方法をおさらいしておくと、Linecastを使って前方に判定を飛ばしてそのオブジェクトが持つイベントリストを取得してイベントキューに渡せば
監視スクリプトがイベント発動とみなしてイベント処理状態になります。

まずはハンマーにイベントリストを持たせましょう。

State_Eventスクリプトを作成します。

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

public class State_Event : MonoBehaviour
{
    public string[] eventList;
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}

シンプルにstring型のインスタンス配列を持たせてpublicにしてプロパティで設定できるようにしました。

int配列でもよかったのですが、stringにして数字をカンマ区切りにして

  • 0個目がイベント種類
  • 1個目がイベント内容
  • 2個目が次のイベントに続くかどうかのフラグ

最後に0のイベントを入れることでイベント終了の合図とします。

string型のsplit関数を使えば指定した文字を区切り文字として対象の文字列を分割して配列を返してくれます。

数字とカンマだけにしておけば数字の文字配列ができあがるため、intにキャストしてあげることで数値を取ることが出来ますね。

正直プロセス的に非効率な気もしますが、視覚的にわかりやすいのを一旦優先します。

いい方法が見つかったらそちらに載せ替えて実装しなおしですね。

jsonでの管理が便利そうだったのでそのうちjsonを使えるようにしてみます。

一旦はstring配列でいきましょう。

それではスクリプトをハンマーオブジェクトに取り付けてみます。

Unity2D プロパティ

こんな感じで管理していきます。

内訳を説明すると

配列0個目の1つ目の数値の5はメッセージイベントという意味です。

そして2つ目の1はメッセージイベントの配列1つ目のメッセージデータを取ってくるというわけですね。

次に3つめの0はこのイベントが最後だよという合図です。

一応念のために最後は0のイベントを入れておき、この0イベントがあった場合は強制的にイベントを終了するという仕組みにしておけば
イベント状態でのフリーズを回避することができます。

0イベントの2個目の数値を弄れば別のイベントシフトするという仕組みを作ることも出来ますが、
体験版では使用するかは不明です。

オブジェクトを調べて保持しているイベントリストの取得をしてみよう

プレイヤーオブジェクトを調べられるようにしてイベントリストを取得できるところまでやってみます。

Zは攻撃キーなのでAキーを割り当てましょう。

    // キーチェック関数
    private void KeyCheck() {
        // 十字(上下左右)
        KeyAddRemove(KeyCode.LeftArrow);
        KeyAddRemove(KeyCode.RightArrow);
        KeyAddRemove(KeyCode.UpArrow);
        KeyAddRemove(KeyCode.DownArrow);

        // 攻撃(Z)
        KeyAddRemove(KeyCode.Z);

        // 掴み(G)
        KeyAddRemove(KeyCode.G);
        // 防御(S)
        KeyAddRemove(KeyCode.S);
        // 回避(D)
        KeyAddRemove(KeyCode.D);

        // 調べる
        KeyAddRemove(KeyCode.A);
    }

これでAキーが有効になりました。

次にAキーを押したときにLinecastを飛ばすように作ります。

Action_Managerに以下の関数を作ります。

    // 調べる処理
    protected virtual void Check() { }

これを引き継いでAction_Playerで実装しましょう。

    // 調べる処理
    protected override void Check() {
        if (_State.ActState == 8 ) {
            // 衝突判定をしたオブジェクトのcolliderがnullでなければ
            _isLcastFront = getLineCast2Object(_State.Direction, _Player, _layerMaskEvent, true);
            Debug.Log(_isLcastFront.collider);
            if (_isLcastFront.collider != null ) {
                // イベントリストの有無を調べる
                if (_isLcastFront.collider.GetComponent<State_Event>().eventList.Length > 0) {
                    string[] ev = _isLcastFront.collider.GetComponent<State_Event>().eventList;
                    Debug.Log(ev[0]);
                }
            }
        }
    }

押す引くオブジェクト取得の仕組みをそのまま使えますね。

取得対象レイヤーをEventにすればイベントレイヤーに属するオブジェクトだけをチェックすることが出来ます。

Unity側でレイヤー作成で「Event」レイヤーを作りましょう。

これでハンマーの持つイベントリストを取得することができました。

Unity2D イベント駆動

イベントキューに渡してイベントモードにする

今回はイベントの仕組みを作るということでここまでにします。

次回は取得できたイベントリストをもとにイベントキューに格納していき、
イベントモードに切り替えて対応するイベントを判断する仕組みを作ります。

この仕組みが出来てしまえばあとは対応するイベントの分岐を作っていくだけですね。

最初はメッセージを表示するイベントを作っていきます。

それでは。