【Unity2D】メッセージ送りの実装
メッセージをイベントで呼び出して表示することと、ボタンカウントの仕組みができたので
お次はメッセージ送りによるイベントの進行になります。
メッセージ送りがないと勝手にウィンドウが閉じてしまうのでユーザビリティが低くなってしまいます。
メッセージ送りの仕組みを作る
現状、Linecastを飛ばしてイベントを取得してメッセージを開くという処理まではできています。
イベントモードなので動けなくなってしまっていますね。
メッセージが表示されているときにAボタンを押したらメッセージを送って、
次のイベントを呼び出すようにしてみます。
現状次のイベントはイベント番号0ということでイベント終了となっています。
ということはメッセージが出たときにもう一度Aを押したらメッセージウィンドウを閉じて、
通常のゲームモード(歩ける状態)に戻してやる必要があります。
ここで前回作ったボタンカウントが役立ちます。
ボタンカウントをしていないと、Aを押したときイベントを進むという仕組みを作った場合
処理落ちでもしていない限りメッセージが現れた瞬間メッセージ送りが作動してしまい文章を見られないままイベントが終わってしまいます。
ボタンカウントがあると、例えばAボタンカウントが1の時だけイベント送りをするという風にすれば
イベントを発動させたときにボタンを押しっぱなしにしていてもカウントは1ではないのでイベント送りが発動しなくなります。
それではイベント送りの仕組みを作っていきましょう。
結構追加したので一旦Event_Managerの全部を記載します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Event_Manager : MonoBehaviour
{
// ステート用変数
private State_Player _State;
// コントローラー用変数
private Controller_Player _Controller;
// イベント待機フラグ
private bool _isPressKey = false;
private void Start()
{
// ステートを取得
_State = GameObject.FindGameObjectsWithTag("State_Manager")[0].GetComponent<State_Player>();
// コントローラーを取得
_Controller = GameObject.FindGameObjectsWithTag("Controller_Manager")[0].GetComponent<Controller_Player>();
}
private void Update()
{
EventExecutioner();
}
// イベントを監視して執行
private void EventExecutioner()
{
// イベントが1つでもあったら処理をする
if (_State.getEventQueue.Count != 0)
{
// イベント待機フラグがONじゃなければイベント進行
if (!_isPressKey)
{
// 1.イベントキュー取り出し(大元キューの0個目を削除)
// 2. 取り出したイベントをint型配列に変換
int[] ev = _str2IntArray(_State.getEventData());
// 配列1つ目を元に処理を分岐
switch (ev[0])
{
// メッセージイベント
case 5:
// ウィンドウを開く
_State.setSystemStatus(1f, 1);
// メッセージを更新
_State.setSystemStatus(ev[1], 5);
// イベント待機フラグを立てるかチェック
if (ev[2] == 0)
{
_isPressKey = true;
}
break;
case 0:
// ウィンドウを閉じる
_State.setSystemStatus(0f, 1);
// メッセージを更新(クリア)
_State.setSystemStatus(0, 5);
break;
default:
break;
}
}
else
{
// イベント待機フラグがONであれば
// Aボタンカウントが1であればイベント待機フラグを折る
if (_Controller.getPushedKeyCount(0) == 1)
{
_isPressKey = false;
}
}
}
else
{
// イベントがなくなったら通常モードに戻す
if (_State.ActState == 9)
{
_State.ActState = 0;
}
}
}
// stringを取り出してint配列を返す
private int[] _str2IntArray(string ev)
{
int[] ev_num = new int[] { 0, 0, 0 };
string[] ev_list = ev.Split(',');
try
{
int.TryParse(ev_list[0], out ev_num[0]);
int.TryParse(ev_list[1], out ev_num[1]);
int.TryParse(ev_list[2], out ev_num[2]);
int[] ev_int_list = new int[] { ev_num[0], ev_num[1], ev_num[2] };
}
catch
{
Debug.Log("エラーデス! INTに変換できない文字列が含まれています!");
}
return ev_num;
}
};
キーが押されるまで待つのを知るためにキー入力待ちの時はフラグを立てるようにしました。
あとはキー状態を知るためにコントローラークラスの変数を作って取得します。
メッセージイベント「5,1,0」の時、0個目の5がメッセージイベントですね。
次に1個目の1がメッセージ内容です。
そして2個目の0はメッセージを待機するかどうかのフラグにしました。
0の場合はメッセージ待機モード。
それ以外の場合は自動送りだったり時間での自動送りだったり。
とりあえず0にして待機状態にします。
そして待機フラグをONにすれば、次のループでイベントが次に進まず停止するようにしました。
そこで前回作ったキーカウントの出番です。
イベントを発動したときにAキーのカウントが1より大きくなっているので、
自動でメッセージ送りが発動しないようにしています。
メッセージ送りをするにはキーを一回離してカウントをリセットする必要があります。
メッセージ送りをしたら、次のイベントリストが動きます。
次のイベントが0だったらイベント終了の合図なのでイベントモードを解除して歩行モードに戻します。
ここで、ステートを9なら0に戻すにしていますがイベント状態になったら9にするように変更します。
そうしないと強制的にイベント解除モードになってしまうので、
チェックしてステートが8になってイベントリストが取得出来たらステートを9にします。
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;
// イベントリストを格納
_State.allSetEventQueue(ev);
// イベントモードにする
_State.ActState = 9;
}
}
}
}
これでイベントを調べてイベントリストが追加されたらイベントモードという扱いになりました。
最初なんかイベント発動しなくなった!って慌てたのですが、これをやってないせいで
強制的にイベント終了モードになってたみたいです(笑)
ステート8は調べモードでステート9はイベントモードという風にしました。
しかしこのままではイベント終わった瞬間にまたイベントが発動してしまいます。
というのも、調べるときにキーAが押されたらとなっているのでそこもキーAカウントが1のときだけにします。
それをするためにキーカウントを知る必要があります。
State_ManagerのsetStateにint配列を受け取る引数を1つ増やします。
// 押しているキーによってステートを変更
protected void setState(List<KeyCode> keyList, List<KeyCode> arrowDirect, int[] keyCount)
{
// 行動ちゅうであれば抜ける
if (_actState == 2 || _actState == 106 || _actState == 107)
{
return;
}
// とりあえずステートリセット(その場止まり)
_actState = 0;
// 移動状態にするかどうか
if (keyList.Contains(KeyCode.DownArrow) || keyList.Contains(KeyCode.UpArrow) || keyList.Contains(KeyCode.LeftArrow) || keyList.Contains(KeyCode.RightArrow))
{
_actState = 1;
}
// 攻撃状態にする
if (keyList.Contains(KeyCode.Z))
{
_actState = 2;
}
// 掴み状態にする
if (keyList.Contains(KeyCode.G))
{
_actState = 5;
if (_actState >= 5 && _actState <= 7)
{
// 十字キーがどれか1つ押されて居たら稼働
if (arrowDirect.Count > 0)
{
switch (_direction)
{
case 0:
if (arrowDirect[0] == KeyCode.UpArrow) { _actState = 6; }
if (arrowDirect[0] == KeyCode.DownArrow) { _actState = 7; }
break;
case 1:
if (arrowDirect[0] == KeyCode.DownArrow) { _actState = 6; }
if (arrowDirect[0] == KeyCode.UpArrow) { _actState = 7; }
break;
case 2:
if (arrowDirect[0] == KeyCode.RightArrow) { _actState = 6; }
if (arrowDirect[0] == KeyCode.LeftArrow) { _actState = 7; }
break;
case 3:
if (arrowDirect[0] == KeyCode.LeftArrow) { _actState = 6; }
if (arrowDirect[0] == KeyCode.RightArrow) { _actState = 7; }
break;
}
// もし_actStateが6か7であればグリッド移動中ステートに変更
if (_actState == 6 || _actState == 7)
{
_actState = _actState + 100;
}
}
}
}
// 調べる(Aキーのカウントが1の時だけ)
if (keyCount[0] == 1)
{
_actState = 8;
}
}
これでキーカウント0番目=Aキーがカウント1ならステータスを調べる(ステート8)に変えるようにしました。
そして配列をとる仕組みを作ってなかったのでgetterとして配列を返す仕組みを作り、
ついでにキーカウント状態取得をprotectedにしていたのでpublicに直してイベントから参照できるようにしましょう。
// キーカウント配列取得
public int[] PushedKeyCount
{
get { return Controller_Manager._pushedKeyCount; }
}
// キーカウント配列の1つを取得
public int getPushedKeyCount(int i)
{
return Controller_Manager._pushedKeyCount[i];
}
これでようやくメッセージ送りができました。
イベント終わりに0イベントを渡していますが、今はウィンドウを閉じたり文章を0にしたりしてます。
現在0にはダミーテキストが入っているので
ボタンカウント&メッセージ送り機能追加
次は応用の選択肢の実装 pic.twitter.com/itxzrmheCE— なおキーヌ@ゲームクリエイターLv5 (@naokeyzmt) January 3, 2020
こんな感じに動きます。
続けて選択肢イベントを作ろうとしたのですが、結構長くなったのでここで切ります。
コミトレまであと15日。
正直体験版完成できるか微妙ですね……
こりゃもう有給使って一気にやりきるしかないかも!
それでは!