【Unity】RPG制作 その19-ダンジョンの下層へ進む
今回はダンジョンの下層にすすめるように階層間の移動を実装していきます。現状、DangeonMap.csに2次元配列を定義してそれをもとにダンジョンの部屋構造を定義しているのですが、その二次元配列を三次元配列に定義しなおします。
クリックで展開
public int[,,] structOfDangeon = new int[3,5,5]{ //3次元配列に変更 { { 4, 1, 5, 4, 1 }, {14,12, 9,14,12 }, {14, 0, 0, 0,12 }, {14, 0, 0, 0,12 }, { 3,13, 0,13, 2 }, }, { { 4,10,10,10, 1 }, { 9,-1,-1,-1, 9 }, { 9,-1, 4,11,12 }, { 9,-1,14, 0,12 }, { 3,10,13,13, 2 }, }, { { 4,11,11,11, 1 }, {14, 0, 0, 0,12 }, {14, 0, 0, 0,12 }, {14, 0, 0, 0,12 }, { 3,13,13,13, 2 }, } }; public int[,,] posOfEvent = new int[3,5, 5] { //3次元に配列に変更 { { -1,-1, 3,-1,-1 }, { 2,-1, 4,-1, 1 }, { 0,-1,-1,-1,-1 }, { -1, 4,-1, 2,-1 }, { -1,-1,-1,-1,-1 }, }, { { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1, 1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1,-1 }, }, { { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1, 1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1,-1 }, }, };
これで階層ごとのダンジョンの部屋配置とイベントのID配置ができます。
QuestManager.csにいって、現在の階層を保持する変数を宣言します。
QuestManager.csで実装していた、移動するごとにステージの進行度を1増やす処理を削除します。
クリックで展開
IEnumerator Searching() { DialogTextManager.instance.SetScenarios(new string[] { "探索中..." }); //背景を大きく questBG.transform.DOScale(new Vector3(1.5f, 1.5f, 1.5f), 2f) .OnComplete(() => questBG.transform.localScale = new Vector3(1, 1, 1)); //フェードアウト SpriteRenderer questBGSpriteRenderer = questBG.GetComponent<SpriteRenderer>(); questBGSpriteRenderer.DOFade(0, 2f) .OnComplete(() => questBGSpriteRenderer.DOFade(1, 0)); //2秒間処理を待機 yield return new WaitForSeconds(2f); //------------------ここから削除------------ //currentFloor++; // 進行度をUIに反映 // stageUI.UpdateUI(currentFloor); //if(stageLength <= currentFloor) //{ // QuestClear(); //} //------------------削除ここまで------------ if (encountRate >= UnityEngine.Random.Range(1, 101)) { DialogTextManager.instance.SetScenarios(new string[] { "敵と遭遇した!!" }); yield return new WaitForSeconds(1.2f); SoundManager.instance.PlaySE(8); nowBattle = true; yield return StartCoroutine(EncountEnemy()); //コルーチン呼び出し 変更 } else { stageUI.ShowButtonsForSearching(); } StartCoroutine(dangionController.InformDangeonEvent()); //プレイヤーがイベントの配置されている座標に到達したらダイアログに表示する if(dangionController.eventID != -1) //何かイベントが配置されていれば { stageUI.SetActionButton(true); //ActionButtonをActiveにする stageUI.isEventPosition = true; } else { stageUI.isEventPosition = false; } }
ダンジョン、マップを生成する時に実行するDangeonMap.csのSetDangeon関数と、SetEvent関数に現在の階層を渡すようにします。
クリックで展開
[SerializeField] QuestManager questManager; //New void Start() { this.gameObject.SetActive(false); dangionController = dangionMapSystem.GetComponent<DangionController>(); SetDangion(questManager.currentFloor); SetEvent(questManager.currentFloor); HideDangeonMap(); } public void SetDangion(int currentFloor) //変更 引数追加 { dangionController.isSetDangeonMap = true; Transform parentRoomImage = transform.Find("Panel/roomImages"); Vector3 originPos = parentRoomImage.transform.position; Vector3 pos = new Vector3(originPos.x - 200, originPos.y - 200, 0); for(int j = 0; j < 5; j++) { for(int i = 0; i < 5; i++) { roomImage[j,i] = new GameObject("roomImage" + j + "_" +i); roomImage[j,i].transform.parent = parentRoomImage; Image image = roomImage[j, i].AddComponent<Image>(); image.sprite = dangionMapSystem.GetComponent<DangionData>().roomImages[structOfDangeon[currentFloor - 1,j, i]]; //変更 二次元配列→三次元配列 pos.x = (originPos.x - 200) + (i * 100); pos.y = (originPos.y + 200) + (j * -100); roomImage[j, i].transform.position = pos; } } Transform playerParent = transform.Find("Panel/player"); Vector3 playerOPos = playerParent.transform.position; dangionController.playerMapObject = new GameObject("playerObj"); dangionController.playerMapObject.transform.parent = playerParent; Image playerimage = dangionController.playerMapObject.AddComponent<Image>(); playerimage.sprite = dangionController.playerSprite; playerimage.SetNativeSize(); Vector3 playerMapPos = new Vector3(); playerMapPos.x = (playerOPos.x - 200) + (dangionController.playerPos.x * 100); playerMapPos.y = (playerOPos.y + 200) + (dangionController.playerPos.y * -100); dangionController.playerMapObject.transform.position = playerMapPos; } public void SetEvent(int currentFloor) //変更 引数追加 { Transform parentImageIcons = transform.Find("Panel/eventIcons"); Vector3 originPos = parentImageIcons.transform.position; Vector3 pos = new Vector3(originPos.x - 200, originPos.y - 200, 0); for (int j = 0; j < 5; j++) { for (int i = 0; i < 5; i++) { eventIcons[j, i] = new GameObject("eventIcon" + j + "_" + i); eventIcons[j, i].transform.parent = parentImageIcons; Image icon = eventIcons[j, i].AddComponent<Image>(); if(posOfEvent[currentFloor - 1,j, i] != -1) //変更 二次元配列→三次元配列 { icon.sprite = dangionMapSystem.GetComponent<DangionData>().eventIcons[posOfEvent[currentFloor - 1,j, i]];//変更 二次元配列→三次元配列 icon.SetNativeSize(); } else { icon.color = new Color(1, 1, 1, 0); } pos.x = originPos.x - 200 + i * 100; pos.y = originPos.y + 200 + j * -100; eventIcons[j, i].transform.position = pos; } } }
DangeonCotroller.csのCheckCanMove関数、GetCurrentPosDangeonEventID関数、DeleteRegiEvent関数、 DeleteEvent関数で使用していた二次元配列を[現在の階層、Y座標,X座標]の形の三次元配列に置き換えます。
次に,階層を移動するイベントを作っていきます。eventID5を下階層への移動イベント、eventID6を上階層への移動イベントとします。最初に、eventID5,6に到達したら階段があることを知らせる関数をDangeonEventクラスに作成します。
クリックで展開
public IEnumerator IEInformDownFloorEvent() //New { DialogTextManager.instance.SetScenarios(new string[] { "下へ降りる階段がある"}); yield return new WaitForSeconds(2f); } public IEnumerator IEInformUpFloorEvent() //New { DialogTextManager.instance.SetScenarios(new string[] { "上へ上がる階段がある"}); yield return new WaitForSeconds(2f); }
DangeonController.csのInformDangeonEvent関数で上記のイベントを呼び出す処理を追加します。
クリックで展開
public IEnumerator InformDangeonEvent() { eventID = GetCurrentPosDangeonEventID(); DangeonEvent dangeonEvent = new DangeonEvent(); switch (eventID) { case -1://何もなし yield break; case 0://採掘イベントを知らせる StartCoroutine(dangeonEvent.IEInformMineEvent()); yield break; case 1://釣りイベントを知らせる StartCoroutine(dangeonEvent.IEInformFishingEvent()); yield break; case 2: //アイテムイベントを知らせる StartCoroutine(dangeonEvent.IEInformItemEvent()); yield break; case 3: //伐採イベントを知らせる StartCoroutine(dangeonEvent.IEInformLoggingEvent()); yield break; case 4: //金貨イベントを知らせる StartCoroutine(dangeonEvent.IEInformGoldEvent()); yield break; case 5: //下階段イベントを知らせる New StartCoroutine(dangeonEvent.IEInformDownFloorEvent()); yield break; case 6: //上階段イベントを知らせる New StartCoroutine(dangeonEvent.IEInformUpFloorEvent()); yield break; } }
イベントを知らせるイベントができたので、実際にイベントを実行する処理を追加していきます。
クリックで展開
public IEnumerator IEDownFloorEvent(DangionMap dangionMap,QuestManager questManager,StageUIManager stageUIManager) //New { stageUIManager.HideButtons(); dangionMap.HideDangeonMapForSearching(); dangionMap.DestroyMapInfo(); questManager.currentFloor++; DialogTextManager.instance.SetScenarios(new string[] { "階段を降りた。\n現在地 B" + questManager.currentFloor}); yield return new WaitForSeconds(2f); dangionMap.SetDangion(questManager.currentFloor); dangionMap.SetEvent(questManager.currentFloor); dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); } public IEnumerator IEUpFloorEvent(DangionMap dangionMap, QuestManager questManager, StageUIManager stageUIManager) //New { stageUIManager.HideButtons(); dangionMap.HideDangeonMapForSearching(); dangionMap.DestroyMapInfo(); questManager.currentFloor--; DialogTextManager.instance.SetScenarios(new string[] { "階段を上がった。\n現在地 B" + questManager.currentFloor}); yield return new WaitForSeconds(2f); dangionMap.SetDangion(questManager.currentFloor); dangionMap.SetEvent(questManager.currentFloor); dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); }
DangeonController.csのIEDangeonEventProcess関数に処理を追加します。
クリックで展開
public IEnumerator IEDangeonEventProcess() { stageUIManager.SetActionButton(false); stageUIManager.SetArrowsButton(false); eventID = GetCurrentPosDangeonEventID(); DangeonEvent dangeonEvent = new DangeonEvent(); switch (eventID) { case -1://何もなし break; case 0://採掘イベント yield return dangeonEvent.IEMineEvent(mineItemGroup); RegistryEventMemory(dangeonEvent,3,5,playerPos.x,playerPos.y,0); break; case 1://釣りイベント yield return dangeonEvent.IEFishingEvent(fisingItemGroup); RegistryEventMemory(dangeonEvent, 3,5, playerPos.x, playerPos.y, 1); break; case 2: //アイテムイベント yield return dangeonEvent.IEItemEvent(itemEventGroup); RegistryEventMemory(dangeonEvent, 3, 5, playerPos.x, playerPos.y, 2); DeleteEvent(); break; case 3: //伐採イベント yield return dangeonEvent.IELoggingEvent(loggingItemGroup); RegistryEventMemory(dangeonEvent, 3, 5, playerPos.x, playerPos.y, 3); break; case 4: //金貨イベント yield return dangeonEvent.IEGetGoldEvent(Random.Range(minGold, maxGold + 1)); playerUIManager.UpdateUI(PlayerManager.instance); DeleteEvent(); break; case 5: //階段を降りるイベント //New yield return dangeonEvent.IEDownFloorEvent(dangionMap, questManager); break; case 6: //階段を上がるイベント //New yield return dangeonEvent.IEUpFloorEvent(dangionMap, questManager); break; } if (!shouldActiveActionButton) { shouldActiveActionButton = true; } else if(shouldActiveActionButton) { stageUIManager.actionButton.SetActive(true); } stageUIManager.SetArrowsButton(true); yield return null; }
それとダンジョンの部屋生成をする時にstructOfDangeonの3次元配列で-1にしてあるところは何も表示しないようにしたいので、SetDangeon関数で処理を分岐させて画像を設定するようにします。
クリックで展開
public void SetDangion(int currentFloor) //変更 引数追加 { Debug.Log(currentFloor); dangionController.isSetDangeonMap = true; Transform parentRoomImage = transform.Find("Panel/roomImages"); Vector3 originPos = parentRoomImage.transform.position; Vector3 pos = new Vector3(originPos.x - 200, originPos.y - 200, 0); for(int j = 0; j < 5; j++) { for(int i = 0; i < 5; i++) { roomImage[j,i] = new GameObject("roomImage" + j + "_" +i); roomImage[j,i].transform.parent = parentRoomImage; Image image = roomImage[j, i].AddComponent<Image>(); //--------------------New------------------ if(structOfDangeon[currentFloor - 1, j, i] == -1) //部屋IDが-1の場合は { image.color = new Color(1, 1, 1, 0); //色を透明にしておく } else { image.sprite = dangionMapSystem.GetComponent<DangionData>().roomImages[structOfDangeon[currentFloor - 1,j, i]]; } //-----------------New------------------------- pos.x = (originPos.x - 200) + (i * 100); pos.y = (originPos.y + 200) + (j * -100); roomImage[j, i].transform.position = pos; } } Transform playerParent = transform.Find("Panel/player"); Vector3 playerOPos = playerParent.transform.position; dangionController.playerMapObject = new GameObject("playerObj"); dangionController.playerMapObject.transform.parent = playerParent; Image playerimage = dangionController.playerMapObject.AddComponent<Image>(); playerimage.sprite = dangionController.playerSprite; playerimage.SetNativeSize(); Vector3 playerMapPos = new Vector3(); playerMapPos.x = (playerOPos.x - 200) + (dangionController.playerPos.x * 100); playerMapPos.y = (playerOPos.y + 200) + (dangionController.playerPos.y * -100); dangionController.playerMapObject.transform.position = playerMapPos; }
フロアを移動した時にプレイヤーがroomのIDが-1以外の場所にランダムで配置されるようにします。そのための関数をDanceonController.csに作成します。
クリックで展開
public void DeployPlayerPositionAtRandom() { bool isDecidePosition = false; while (!isDecidePosition) { int x = Random.Range(0, dangion_width - 1); int y = Random.Range(0, dangion_height - 1); int floor = questManager.currentFloor; if (dangionMap.structOfDangeon[floor, y, x] != -1) { playerPos.x = x; playerPos.y = y; isDecidePosition = true; } } }
この関数をDangeonEvent.csのIEDownFloorEventコルーチンとIEUpFloorEventコルーチンで呼び出すようにします。
これで上下の階層に移動することができるようになりました。
次回はイベントをランダムで配置できるようにしていきます。