kuront’s blog

主にUnityでのゲーム制作やってます。

【Unity】RPG制作 その18-探索時のイベント処理

 今回は探索時にイベントを発生させる処理を作っていきます。探索時にDangeon関連の処理を実行できるようにQuestManager.csでDangeonController型の変数を定義します。

 


クリックで展開

 次に、DangeonController.csに現在のプレイヤーの座標に配置されているイベントのIDを取得する関数を定義します。

 


クリックで展開

 イベントが配置されている地点に到達したらダイアログを表示する関数を宣言します。

 


クリックで展開

 eventIDは関数の外でint型で定義しておきます。次に、イベントを発動させるActionButtonを作成します。

f:id:kuront:20211013132801p:plain

StageUIManager.csでActionButtonを制御できるようにしておきます。

 


クリックで展開

ActionButtonはイベントが配置されている座標でのみ表示したいので、bool型のisEventPosition変数で処理の分岐をさせています。Questmanager.csのSearchingコルーチンで以下の処理を追加して探索後にボタンをアクティブにするかどうかを判定させて、フラグの変更も行います。

 


クリックで展開
これでActionButtonの制御は実装できました。次はActionButtonを押した時にイベントを発動するようにします。


 


クリックで展開

イベントを4種類作成しました。IEDangeonEventProcessの処理に入ったら現在地のeventIDを取得し、IDが1~4の場合は各イベントを実行します。イベントはdangeonEventクラスで処理を行っていくのですが、イベントを数回発生させるタイプのイベントの場合(ここでは採掘イベント、伐採イベント、釣りイベント)、RegistryEvent関数でDangeonEventMemory型の配列にEventのデータを登録しておきます。DangeonEventMemoryクラスでは、イベントの残り回数やX,Y座標、dangeonEventクラスを保持できるのですが、これらの情報を使用して、イベントをマップ上に残しておくか、消すべきかを判定させます。


 ちなみにIEDangionEventProcessのスイッチ内イベント処理の中身はこんな感じです。

 


クリックで展開

 採掘イベントのコードだけ書いています。(全部載せると膨大な量になるので・・・)採掘イベントの場合は採掘スキルとつるはしが必要になるのでつるはしの所持個数と採掘スキルを所持しているかで処理を分けています。

実際に動かし見ると以下の動画のようになります。

youtu.be

これで探索時にイベントを実行できるようになりました。このイベントを自動的に配置できるようにしたいですが、次回は先にダンジョンの次の階層に進む処理を実装していきたいと思います。

【Unity】RPG制作 その17-プレイヤー移動したら一定の確率で敵とエンカウント

 前回は探索ステージのマップを制作しました。今回はプレイヤーの移動ボタンを押したら一定の確率で敵をエンカウントするようにします。
 プレイヤーのマップ移動を実装するまでは、「進む」ボタンを押したらエンカウントするかどうかを処理していましたが、それを4方向の移動ボタンを押した時に実行させようと思います。まずはじめに、questManagerを開いて、処理を追加していきます。

 


クリックで展開

 新しくMoveOnRoom関数を作成していますが、OnNextButton関数に関数の処理が終了した時の処理を登録しているだけであとは「進む」ボタンを押した時に実行されていたOnNextButtonと一緒です。

[SerializeField] UnityEvent OnCompleteMoveRoom;

 関数の入れ物を定義しておきます。SerializeFieldにしてインスペクターから設定できるようにします。MoveOnRoom関数のはじめにOnCompleteMoveRoomのインスタンスを生成し、関数の最後のOnCompleteMoveRoom.Invoke();で登録された関数の呼び出しを行っています。
 次にDangeonMap.csにOnCompleteMoveRoomに登録する関数を作成します。

 


クリックで展開

 新しくHideDangeonMapForSearching関数とShowDangeonMapForSearching関数を用意しました。QuestManagerのOnCompleteMoveRoomにはShowDangeonMapForSearching関数を登録しておきます。そしてDangeonMapControllerにいって、プレイヤー移動ボタンを押した時にこれらの処理が実行されるように組み込みます。

 


クリックで展開

プレイヤー移動時に、元々マップが表示されていれば、移動後にサイドマップを表示するようにしました。実行すると以下の動画のようになります。

youtu.be

通常時はOKなのですが、戦闘に突入した時にマップが表示がされたまま(探索時のコマンドも)になってしまっているので、次はそれを直していきます。

 


クリックで展開

 QuestManagerに戦闘中かどうかのフラグを宣言します。そのフラグをEncountEnemy関数の処理に入る前にtrueにし、EndBattle関数の中でfalseにします。そして、MoveOnRoomコルーチンの最後で、nowBattleがfalseの場合(戦闘に突入しなかった時)に OnCompleteMoveRoomの登録された関数を実行しています。EndBattle関数の中でも呼び出しています。
 それから敵に遭遇した時にマップを表示している場合はCancelButtonとArrowsButtonsを非表示にしたいので、StageUIManager.csに処理を追加します。

 


クリックで展開

Searchingが終わった時に呼び出す新しい関数を作りました。dangeonMapが開いているときはcancelButtonとArrowButtonsをtrueにし、そうでないときはStageUIManagerのShowButton関数を実行するようにしています。
あとはQuestManagerのSearchingコルーチンとEndBattle関数内のstageUI.ShowButtons関数をstageUI.ShowButtonsForSearchingに差し替えれば終わりです。これでプレイヤー移動と敵とのエンカウント処理をうまくつなげることができました。

今回は以上です。次回はマップの特定の位置にたどり着いたらイベントを発生させる処理を作っていきたいと覆います。

【Unity】RPG制作 その16-ステージ制作 プレイヤーの移動

 前回はステージマップの見た目を作っていきました。今回はマップ上のプレイヤーの移動を実装していきます。
プレイヤーを移動させるためのボタンを以下のように配置します。

f:id:kuront:20211005052136p:plain

 次にダンジョンの処理を制御するスクリプト、DangionControllerを作成し、DangionMapSystemに貼り付けます。DangionController.csは以下のように記述します。

 


クリックで展開

 PlayerMoveDown,PlayerMoveUp,PlayerMoveLeft,PlayerMoveRightを先程作ったプレイヤー移動ボタン4方向にそれぞれ割り当てます。あとはプレイヤー画像をplayerSpriteに割り当てればとりあえず移動できるようになります。
(DangionMap.csも少し手を加えたので一応コードを載せておきます。)

 


クリックで展開

実行すると以下のようになります。

youtu.be

 現状部屋の形状や範囲外でも関係なく動けてしまう状態です。現在の部屋から移動方向への移動が可能かどうかを判定する関数を作成します。最初にダンジョンの部屋数を定義しておきます

 


クリックで展開

移動の可不可を判定する関数を以下のように定義します。

 


クリックで展開

この関数は移動前と移動後のプレイヤーの座標を使って、それぞれの部屋の形状を取得し、取得した部屋の形状が移動前から移動方向を通行できるか、移動後の部屋に移動方向から通行できるかをそれぞれ判定し、両方trueの場合にtrueを返すようになっています。ダンジョンの範囲外かどうかも判定しています。通行可能かどうかの判定方法はイカの画像のとおりです。

f:id:kuront:20211005090139p:plain

この処理を画像ごとに一つ一つ条件式にしていきます。あとはプレイヤーの移動の時にこの関数が返すbool値で実際に移動するかどうかを決めます。

 


クリックで展開

これで実行すると以下のようになります。

youtu.be

 これで部屋の形状に応じてプレイヤーの移動を制限することができました。次回は探索中のイベントを制作していきたいと思います。

【Unity】RPG制作 その15-ステージマップ作成

 前回まではアイテムの使用処理を実装しました。今回からは探索ステージのマップを作成していきたいと思います。以下の画像のようなマップの見た目を作っていきます。

f:id:kuront:20211004223538p:plain

 まずはじめに、Canvasを新規作成し、名前をDangionMapCanvaにします。次にDangeonMapCanvaの子
として、Panelを作成し、Panelの子に空のオブジェクトを2つ作成し、名前をそれぞれeventIconsとroomImagesにします。

f:id:kuront:20211004224300p:plain

f:id:kuront:20211004224629p:plain

 次はスクリプトを作成します。Dangion Mapという名前でスクリプトを作成し、DangionMapCanvasオブジェクトに貼り付けます。それから、空のゲームオブジェクトを作成、名前をDangionMapSystemにし、新規スクリプトDangionDataを作成し、DangionMapSystemに貼り付けます。
DangionDataスクリプトを作成し、以下のように記述します。

 


クリックで展開

 次に以下のような画像を用意します。

f:id:kuront:20211005011244p:plain

この画像をDangionMapSystemのDangionDataスクリプトのRoomImagesとEventIconsの配列にセットします。

f:id:kuront:20211005011411p:plain

次はDangionMapスクリプトを以下のように記述します。

 


クリックで展開

structOdDangeonとposOfEventがそれぞれステージの部屋構造とイベントの配置のデータになります。
これらのデータをSetDangion関数とSetEvent関数でCanvasに表示しています。

stageUIcanvasに新たにボタンを配置し、マップの表示非表示を切り替えられるようにしました。
実行すると動画のようになります。

RPG制作 15 ステージマップ表示非表示 - YouTube

とりあえず見た目はこんな感じで、次回はステージ内でのプレイヤーの移動を作っていこうと思います。

【Unity】RPG制作 その14-攻撃アイテム使用処理

 前回は戦闘時の回復アイテムの処理の実装を行いました。今回は攻撃アイテムの実装をやっていきます。

 アイテムのデータに命中率を設定したいので、itemData.csに以下の記述を追加しておきます。

[Header("攻撃アイテムの場合の命中率")] public int hitRate = 95;

 itemEventに命中率の判定を行う関数を定義します。

 


クリックで展開

アイテムを使用した際に、何かしらの効果があった場合にtrueにするbool変数を宣言します。

 


クリックで展開

 それから、itemDataをもとに、アイテムの対象者に状態異常を付与する関数を作成します。

 


クリックで展開

 ここでTermManagerという名前のクラスが使われていますが、これは主にアイテムのデータに応じて定義されたメッセージ(script型)を返す関数を定義しているクラスです。TermManagerの中身はこんな感じになっています。

 


クリックで展開

 他のも色々定義されたいますが、今回使うのはGet_STATUSCONDI_Message関数とGet_STATUS_EnforcedMessage関数とGet_STATUS_WeakenedMessage関数です。

 次はアイテムの使用対象にステータス強化・弱体を付与する関数を作成します。

 


クリックで展開

 ステータスの強化率はitemDataのenforceRate1(~3)で設定するのですが、この数値が+の場合は強化、-の場合は弱体です。なので、enforceRateの値が+か-か判定して、条件分岐させています。EnemyStatusEnforce関数とEnemyStatusWeakened関数はそれぞれステータスが強化・弱体された時の強化率やターン数をEnemyManagerに設定したり、メッセージを表示する関数です。

 


クリックで展開

 次はItemUIが作成された時にそれぞれのアイテムのButtonのOnclickにitemEvent登録される関数、SetItemTargetPanel関数に処理を追加していきます。

 


クリックで展開
こちらに処理を追加していくのですが、そのまえにバグの修正をします。
CommandUIManager.csに「やめる」ボタンを押した時に、itemUsePanelとuseItemMessaagePanelを閉じる処理を追加します。

 


クリックで展開

 これでItemUIが開いているときに「やめる」ボタンを押すとItemUIを閉じてCommandUIを開き、UseItemMessagePanelが表示されている時に「やめる」ボタンを押すとUseItemMessagePanelが閉じてItemUIが再度開くようになりました。
 次はATTACKアイテムを選択した時に、Enemyをタップした時に実行する関数を変更する処理を実装します。EnemyManagerでEnemyがタップされた時に実行する関数の変数tapActionを初期化する関数を作成します。

 


クリックで展開

 準備ができたので、先程のAttackアイテム使用時の箇所に処理を追加します。

 


クリックで展開

 やっていることをざっくり説明すると、Attackアイテムを選択した場合は、Enemyのタップ処理を新規に作成したAttackItemEventの関数に登録しなおしています。この処理を行った場合、処理が行われたあとにAttackItemEventを破棄しておきます。

 


クリックで展開

それから、通常攻撃を選択したときは、enemyのタップ処理に通常攻撃時の処理を登録し直すようにします。そのための関数をbattleManagerに新しく作成します。

 


クリックで展開

この関数を「攻撃」コマンドを押した時に呼び出すようにします。

実行するとこんな感じになります。

youtu.be

 次回は探索するステージの制作をしていきます。

【Unity】RPG制作 その13-戦闘時の行動タイプの保持、実行

 前回は戦闘中に回復アイテムを使用する処理を実装しようとして、アイテムを使っている途中で動かなくなったところで終わりました。
バグの原因が不明なので、アイテムの使用処理の実装を置いておいて先に戦闘時の行動タイプによる処理分けを実装していきたいと思います。
 実際の戦闘中の処理はBattleManagerが行っているのでBattleManagerに処理を追加していきます。

はじめに、戦闘中の行動の処理分けをするための列挙定数を宣言します。

public enum BATTLEACTIONTYPE
    {
        NORMALATTACK,
        GUARD,
        ITEM,
        MAGIC,
        MOVE,
    };

それから、プレイヤーと敵のBATTLEACTIONTYPEを保持するためのDictionrayも宣言します。

private Dictionary<int, BATTLEACTIONTYPE> battleActionDic = new Dictionary<int, BATTLEACTIONTYPE>();

battleActionDicを初期化する関数を定義します。

//プレイヤー、敵の行動を初期化する関数
    public void InitBattleActionDic()
    {
        //初期値はNORMALATTACKにしておく
        battleActionDic[0] = BATTLEACTIONTYPE.NORMALATTACK;
        battleActionDic[1] = BATTLEACTIONTYPE.NORMALATTACK;
        battleActionDic[2] = BATTLEACTIONTYPE.NORMALATTACK;
        battleActionDic[3] = BATTLEACTIONTYPE.NORMALATTACK;
    }

InitBattleActionDic関数をバトルのはじめに呼び出されるSetUpBattle関数で呼び出します。

public void SetUpBattle()
    {
        SoundManager.instance.PlayBGM("Battle");
        player = PlayerManager.instance; 
        playerUI.SetupUI(player);
        commandUI.gameObject.SetActive(true);
        commandUI.SetBattleCommand();
        battleResult = new BattleResult(); // クラスから実体生成
        isBattleEnd = false;
        InitBattleActionDic(); //行動タイプDictionray初期化 New
    }

 準最初の備ができたので、まずはプレイヤーの行動を処理分けできるようにしていきます。
BattleManager.csのTurnProcessの中で、行動順がプレイヤーの場合、StartPlayerTurnコルーチンを実行しているので、こちらに処理を追加していきます。
 現状StartPlayerTurn関数の中身は以下のようになっています。

 


クリックで展開

 上記のコメントで書いてある、"敵を倒した時の処理"より上は、通常攻撃を行った時の処理になるので、この処理を関数にしておきます。



クリックで展開

この関数で処理を置き換え、BATTLEACTIONTYPEで処理を分けるとこんな感じになります。


クリックで展開

 これで行動タイプによって処理の分岐をするようになりました。
 

行動タイプITEMの場合の処理の実装

 行動タイプがITEMの場合に実行される処理を実装していきます。
実際に実行させたい処理をItemEventから指定したいので、ここでは関数登録を使います。ItemEvent.csに関数登録用の変数とプレイヤーがアイテムを使うと決めた時に実行する関数を作成します。


クリックで展開

 DecideUseItem、IEUseItemRegisterへの関数の登録はItemUsePanelで行います。


クリックで展開

 Buttonを押した時の処理にDecidePlayerUseItemOnBattleを追加し、DecideUseItemにbattleManagerのStartBattleTurn関数、IEUseItemRegisterにIEUseHealItemOnBattleコルーチンを登録しました。
 あとはアイテムを使った時にこれらの処理を実行されるようにBattleManagerに処理を書いていきます。
 battleManagerでitemEventクラスのデータを保持できるように、itemEvent型の変数を作ります。

public itemEvent playerItemEvent;

PlayerのBATTLEACTIONTYPEがITEMの時に実行されるコルーチンを作成します。



クリックで展開

 このコルーチンをStartPlayerTurnの中で呼び出します。

クリックで展開

あと1点バグ修正で、CommandUIManagerのスクリプトのHideCancelButton関数を以下のように記述し直します。


クリックで展開

 これを書いておかないと、PushItemButton関数のTranslateでY座標-150したキャンセルボタンがそのままになってしまいます。

 この状態で実行すると以下の状況で問題が発生します。

f:id:kuront:20211001091553p:plain

f:id:kuront:20211001091601p:plain

BattleManagerのエラー発生箇所を確認するとif (enemysList[targetIndex].hp <= 0)となっています。
これは、攻撃した後に、攻撃対象のHPが0以下であれば敵をDestroyするという処理の判定箇所なのですが、このtargetIndexの値が、アイテムを使った場合元々の数値が入ったままで、前のターンのtargetindexが入っている状態です。敵を倒した場合、enemyListのint型の要素が削除されるようになっているのでエラーが出るのです。なので、敵を倒した時にtargetIndexの値をenemyListの存在するint型のKeyの値に変更します。


クリックで展開

 enemysList.First().KeyでenemysListのDictionaryに存在する一番最初に見つけた要素のint型のKeyを取得できます。これでもう1回実行してみます。

youtu.be

【Unity】RPG制作 その12-回復アイテム使用処理(戦闘中)

 前回は探索中にアイテムを使用する処理を実装しました。今回は戦闘中にアイテムが使えるようにしたいと思います。ItemUiは探索と戦闘の両方同じスクリプトで呼び出しているのですが、実際にボタンを押した時の挙動については戦闘時と探索時で変えたいです。現在が探索中か戦闘中かの状態は、GameManagerのGAMEPHASEが保持しているので、GAMEPHASEを使って処理を分岐させます。
 現状、戦闘中にアイテムコマンドを押すと、アイテムのリストが表示されて、回復アイテムであれば実際に使う事ができるのですが、敵とプレイヤーの行動順に関係なく即座に使えてしまい、さらに敵のターンの処理が回ってこず再度プレイヤーが行動を選べてしまいます。あと探索時のアイテム処理と共有しているので使用後に探索コマンドも出てしまいます。

f:id:kuront:20210928212451p:plain

f:id:kuront:20210928212500p:plain

f:id:kuront:20210928212508p:plain

f:id:kuront:20210928212517p:plain

f:id:kuront:20210928212525p:plain

f:id:kuront:20210928212533p:plain

f:id:kuront:20210928212543p:plain


 探索コマンドのバグはすぐに直せます。gamePhase==QUESTの場合のみ探索コマンドを表示するようにすればいいだけです。

 アイテム使用後は「やめる」ボタンを表示しないようにしたいので、ItemEventでCommandUIManagerの処理を実行できるように、ItemUsePanelでItemEventコンポーネントを追加する時に、CommandUIManagerを渡すようにします。あとgamePhaseがBATTLEのときはbuttonState.onClick.AddListenerで別の関数を登録するようにします。



 


クリックで展開

それからCommandUIManager.csで戦闘中のキャンセルボタンを非表示にする関数を定義しておきます。

 


クリックで展開


 itemEvent.csに戦闘中に回復アイテムを使用する関数を定義します。とりあえずその関数の一番初めに「やめる」ボタンを非表示するようにしておきます。

 


クリックで展開

 UseHealItemOnBattleには状態異常の回復処理や、ステータスの強化処理なども入れておきました。これらはまだ完全には実装されていないので、戦闘中に効果を及ぼすことはないですが、状態異常解除やステータス強化のメッセージは表示されるようになっています。

 これでうまくいくのかと思いきや残念ながらうまく動きませんでした。理由は不明ですが、アイテム使用後のメッセージを表示する際のコルーチンのWaitForSecondのところで止まってしまいます。

youtu.be