今日こそは、ゲームのメイン部分である、イベントの仕組みを作成していきます。
しまづさんの動画で、すでにDrag.csとDrop.cs、それをベースにアイテムをドラッグするためのDragObj.csと
カバンからアイテムをDragするためのDragObjUI.csを作成しているのですが、
単純にアイテムをクリックした時にメッセージ表示やBoolを変化させる、いわゆるゲームイベントの働きをする機能も欲しいと思ったので、
それを作成することにします。
せっかくなので汎用的に色々な機能を持たせたいと思いますので、まずは、代表的なイベントを定義します。
定義したイベントは3つ。
・メッセージを表示するイベント。
・アイテムを取得するイベント。
・flagを操作するイベント。
です。
イベントが決まったので、このイベントを定義するクラス。ObjEvent.csを作成します。
using System; [Serializable] public class ObjEvent { public enum Type { Message,//メッセージを表示するイベント GetItem,//アイテムを取得するイベント FlagSet,//Flagを操作するイベント } public Type type;//イベントの種類 public Item.Type item;//獲得するアイテムの種類 public String message;//メッセージ public int True_messageNo;//Trueの時のメッセージNo、もしくは通常のメッセージNo public int False_messageNo;//falseの時のメッセージNo public int BoolNo;//FlagのNo public bool EventOutcome;//イベントの結果でフラグに設定される値 public int SoundNo1;//イベントで鳴らすSEのNo public int SoundNo2;//イベントで鳴らすSEのNo public ObjEvent(Type type, Item.Type item,String message,int True_messageNo,int False_messageNo,int BoolNo,bool EventOutcome,int SoundNo1,int SoundNo2) { this.type = type; this.item = item; this.message = message; this.True_messageNo = True_messageNo; this.False_messageNo = False_messageNo; this.BoolNo = BoolNo; this.EventOutcome = EventOutcome; this.SoundNo1 = SoundNo1; this.SoundNo2 = SoundNo2; } }
ObjEventの定義ができたので、次はアイテムにこのObjEventを設定するクラス、EventObj.csを作成します。
名前が似ているのは、センスのなさを感じますが、自分的には、これが一番しっくりきました😅
EventObjは、そのアイテムで発生するイベントを設定し、イベントを起動する働きを持たせます。
ただ、イベントを数多く作るときに、EventObj全部にイベント処理を実行する機能まで持たせるのは、ちょっと無駄なので、
EventObj.csはあくまでイベントの設定と、イベントの起動だけを行い、
イベントの処理は共通クラスのEvent Controllerで行うことにしました。
using UnityEngine; using Cysharp.Threading.Tasks; public class EventObj : MonoBehaviour, IEvent //ここに定義していないイベント用にIEventインターフェースも用意 { [Header("イベント発動に必要な距離")][SerializeField] float EventDistance; [SerializeField] private Transform SetPos; [Header("クリックしたときのイベント")][SerializeField] ObjEvent Click_event; [SerializeField]bool IsSerchEvent=false;//サーチモードでイベントを変えるかどうか [Header("サーチした時のイベント")][SerializeField] ObjEvent Serch_event; public void Event() { Transform PlayerTransform= GameObject.Find("Player").transform; GameManager.instance.beforeGameMode=GameManager.instance.gameMode;//ゲームモードを保存 if(Vector3.Distance(PlayerTransform.position,transform.position)>EventDistance)//イベント発動に必要な距離以下か確認 { if(GameManager.instance.gameMode==GameMode.Type.Normal || GameManager.instance.gameMode==GameMode.Type.Search) { GameManager.instance.gameMode=GameMode.Type.Message;//ゲームモードをメッセージモードに変更 MessageManager.instance.ShowGetMessage(2).Forget(); } return;//プレイヤーが近くにいない場合は処理を抜ける。 } if(GameManager.instance.gameMode==GameMode.Type.Normal) { EventController.instance.Event(Click_event); } else if(GameManager.instance.gameMode==GameMode.Type.Search) { if(IsSerchEvent) { EventController.instance.Event(Serch_event); } else { EventController.instance.Event(Click_event); } } } }
EventObj.cs自身は単純なもので、ノーマルモードでクリックした時のイベントとサーチモードでクリックした時の
2つのイベントを格納しておき、それぞれのゲームモードに応じたイベントをEventControllerに送るだけの機能です。
その際、Playerとの距離を確認して、遠すぎる場合は近づくことを促すメッセージを表示するように作成しました。
メッセージ関係は全く別の仕組みのMessageManager.csで制御しています。
この時、メッセージウィンドウの開閉状態で、二重にメッセージを表示させようとするとおかしな動きをするため
ゲームモードをMessagaモードに変更し、この時にはイベント発動ができないように制限しています。
ここに定義しきれないイベントを作成するときに備えて、IEventというEventメソッドを保証するインターフェースも用意して、
次は、イベントを実際に処理するクラスEventContorollerです。
using UnityEngine; using TMPro; using DG.Tweening; using Cysharp.Threading.Tasks; using System.Threading; using UnityEngine.UI; using System; public class EventController : MonoBehaviour { ObjEvent.Type eventType=ObjEvent.Type.Message; Item.Type item; String message; //Trueの時のメッセージNoもしくは通常のメッセージ int True_messageNo; int False_messageNo;//falseの時のメッセージNo int BoolNo;//FlagのNo bool EventOutcome; int SoundNo; [SerializeField] ZoomPanel zoomPanel; public static EventController instance; private void Awake() { instance=this; } public void Event(ObjEvent objEvent) { eventType=objEvent.type; switch(eventType) { case ObjEvent.Type.Message://メッセージを表示するイベント GameManager.instance.beforeGameMode=GameManager.instance.gameMode; GameManager.instance.gameMode=GameMode.Type.Message; if(GameManager.instance.GameFlag[objEvent.BoolNo]) { MessageManager.instance.ShowGetMessage(objEvent.True_messageNo).Forget(); } else { MessageManager.instance.ShowGetMessage(objEvent.False_messageNo).Forget(); } break; case ObjEvent.Type.GetItem://アイテムを取得するイベント if(GameManager.instance.GameFlag[objEvent.BoolNo]) { GameManager.instance.gameMode=GameMode.Type.Message; MessageManager.instance.ShowGetMessage(objEvent.True_messageNo).Forget(); return; } var GetItem = ItemGenerator.instance.Spawn(objEvent.item); GameManager.instance.GameFlag[objEvent.BoolNo]=true; //**将来ここで音を鳴らす ItemBox.instance.SetItem(GetItem); zoomPanel.ShowPanel(GetItem); GameManager.instance.gameMode=GameMode.Type.Message; var GetMessage=GetItem.ItemName+"を手に入れた"; MessageManager.instance.ShowMessage(GetMessage).Forget(); break; case ObjEvent.Type.FlagSet://Flagを立てるイベント GameManager.instance.beforeGameMode=GameManager.instance.gameMode; GameManager.instance.gameMode=GameMode.Type.Message; if(GameManager.instance.GameFlag[objEvent.BoolNo]) { MessageManager.instance.ShowGetMessage(objEvent.True_messageNo).Forget(); } else { //**将来ここで音を鳴らす MessageManager.instance.ShowGetMessage(objEvent.False_messageNo).Forget(); GameManager.instance.GameFlag[objEvent.BoolNo]=objEvent.EventOutcome; } break; } } }
テストしながら作成しているので、実はまだ未完成だったりします😅
ただ、これで一応、アイテム取得やメッセージを表示することはできるので、続きはのんびり作成していこうと思っています。
さて、これでイベントシステムまで完成したので、ちょっとここらで一旦休憩して
次は、前々から興味のあったGodotでちょっと遊んでみようと思っています。