【Unity】RPG制作 その25-武器、防具アイテム実装その2 装備画面実装
今回は武器と防具の装備画面の作成をやっていきます。
装備画面はこんな感じです。
左のグレーの部分がボタンになっており、押すとその部位に装備できる武器・防具がスクロールビューに表示されるように作ります。
まずはじめに、GeneralEnum.csに装備部位の列挙型定数を宣言します。
クリックで展開
public enum EQUIP_SLOT //装備部位の列挙型定数 New { RIGHTHAND, LEFTHAND, HEAD, BODY, WEIST, LEG, ACCESSORIES1, ACCESSORIES2, }
PlayerManagerに現在プレイヤーが装備している武器と防具を保持するDictionaryの宣言と、プレイヤーの装備状態の初期化関数を作成します。
クリックで展開
//-----------現在つけている装備品のDictionary-------------- public Dictionary<GeneralEnum.EQUIP_SLOT, WeaponEntity> equipWeapons = new Dictionary<GeneralEnum.EQUIP_SLOT, WeaponEntity>();//New public Dictionary<GeneralEnum.EQUIP_SLOT,ArmorEntity> equipArmors = new Dictionary<GeneralEnum.EQUIP_SLOT,ArmorEntity>();//New //プレイヤーの装備の状態を初期化する public void InitEquipWeaponsAndArmor() { equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new ArmorEntity(); equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new ArmorEntity(); equipArmors[GeneralEnum.EQUIP_SLOT.HEAD] = new ArmorEntity(); equipArmors[GeneralEnum.EQUIP_SLOT.BODY] = new ArmorEntity(); equipArmors[GeneralEnum.EQUIP_SLOT.WEIST] = new ArmorEntity(); equipArmors[GeneralEnum.EQUIP_SLOT.LEG] = new ArmorEntity(); equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1] = new ArmorEntity(); equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2] = new ArmorEntity(); }
WeaponManagerとArmorManagerに、所持装備のDctionaryの空きにEntityを登録する関数と、Dictionaryの指定したIndexの装備を削除する関数、Entityから元Dataを取得する関数を作成します。
クリックで展開
public bool RegiEntity(WeaponEntity weaponEntity) //New { bool successAdd = false; for (int i = 0; i < possessionWeapon.Length; i++) { if (!possessionWeapon[i].isRegistry) { possessionWeapon[i] = weaponEntity; successAdd = true; return successAdd; } } return successAdd; } public void DeleteWeapon(int index) //New { possessionWeapon[index] = new WeaponEntity(); } /// <summary> /// WeaponEnityから元のWeaponDataを取得する /// </summary> public WeaponData GetWeaponDataFromEntity(WeaponEntity weaponEntity) //New { for(int i = 0; i < instance.possessionWeapon.Length; i++) { if(instance.weaponDatas[i].weaponID == weaponEntity.weaponID) { return instance.weaponDatas[i]; } } return instance.weaponDatas[0]; }
クリックで展開
public bool RegiEntity(ArmorEntity armorEntity) { bool successAdd = false; for (int i = 0; i < possessionArmor.Length; i++) { if (!possessionArmor[i].isRegistry) { possessionArmor[i] = armorEntity; successAdd = true; return successAdd; } } return successAdd; } public void DeleteArmor(int index) { possessionArmor[index] = new ArmorEntity(); } public ArmorData GetArmorDataFromEntity(ArmorEntity armorEntity) { for (int i = 0; i < instance.possessionArmor.Length; i++) { if(instance.armorDatas[i].armorID == armorEntity.armorID) { return instance.armorDatas[i]; } } return instance.armorDatas[0]; }
装備画面内での処理を行うEquipmentUIクラスを新規作成します。一応コードを全部載せますがめちゃくちゃ長いので流し読みすることをおすすめします。(笑)
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class EquipmentUI : MonoBehaviour { public Canvas weaponCanvas; public GameObject listPanel; GameObject scrollView; Transform viewPort; Transform content; public Dictionary<WeaponEntity,int> partWeaponArray; public Button RHandEquipButton; public Button LHandEquipButton; public Button HeadEquipButton; public Button BodyEquipButton; public Button WeistEquipButton; public Button LegEquipButton; public Button Accessories1EquipButton; public Button Accessories2EquipButton; public Button RemoveEquipButton; public Text RHandEquipText; public Text LHandEquipText; public Text HeadEquipText; public Text BodyEquipText; public Text WeistEquipText; public Text LegEquipText; public Text Accessories1EquipText; public Text Accessories2EquipText; // 関数リスト(2021/11/09作成) // void Start() // public void ShowEquipUI() // public void HideEquipUI() // public void SetEquipButtonListener()・・・それぞれのEquipButtonを押した時のイベントを登録する // public void ProhibitEquipButton()・・・それぞれのEquipButtonの押下を禁止する // public void PermissionEquipButton()・・・それぞれのEquipButtonの押下を許可する // public void PushRemoveEquipButton(PlayerManager playerManager, GeneralEnum.EQUIP_SLOT equipSlot)・・・外すボタンを押した時の処理実行 // public bool SetWeaponEntity(GeneralEnum.EQUIP_SLOT equip_slot)・・・listPanelのScrollViewに所持武器のContentをセット // public bool SetArmorEntity(GeneralEnum.EQUIP_SLOT equip_slot)・・・listPanelのScrollViewに所持防具のContentをセット // public void ShowListPanel() // public void HideListPanel() // public void DestroyAllItem()・・・ScrollViewのContentをすべて消去する // public void ChangeWeapon(GeneralEnum.EQUIP_SLOT equip_slot,WeaponEntity weaponEntity, PlayerManager playerManager, int index) ・・・装備武器を変更する処理 // public void ChangeArmor(GeneralEnum.EQUIP_SLOT equip_slot, ArmorEntity armorEntity, PlayerManager playerManager, int index)・・・装備防具を変更する処理 // public void UpdateWeaponText(PlayerManager playerManager,WeaponEntity weaponEntity, GeneralEnum.EQUIP_SLOT equip_slot)・・・装備武器のテキストを更新する // public void UpdateAllWeaponText(PlayerManager playerManager)・・・装備武器のテキストをすべて更新する // public void UpdateArmorText(PlayerManager playerManager, ArmorEntity armorEntity, GeneralEnum.EQUIP_SLOT equip_slot)・・・装備防具のテキストを変更する // public void UpdateAllArmorText(PlayerManager playerManager)・・・装備防具のテキストをすべて更新する void Start() { scrollView = GameObject.Find("EquipmentUI_Scroll View");//(注)同じ名前を作らない viewPort = scrollView.transform.Find("Viewport"); content = viewPort.transform.Find("Content"); SetEquipButtonListener(); this.gameObject.SetActive(false); listPanel.gameObject.SetActive(false); } public void ShowEquipUI() { SoundManager.instance.PlaySE(22); this.gameObject.SetActive(true); } public void HideEquipUI() { SoundManager.instance.PlaySE(7); this.gameObject.SetActive(false); } public void SetEquipButtonListener() { RHandEquipButton.onClick.AddListener(() => {SetWeaponEntity(GeneralEnum.EQUIP_SLOT.RIGHTHAND);}); RHandEquipButton.onClick.AddListener(() => { SetArmorEntity(GeneralEnum.EQUIP_SLOT.RIGHTHAND); }); LHandEquipButton.onClick.AddListener(() => { SetWeaponEntity(GeneralEnum.EQUIP_SLOT.LEFTHAND); }); LHandEquipButton.onClick.AddListener(() => { SetArmorEntity(GeneralEnum.EQUIP_SLOT.LEFTHAND); }); HeadEquipButton.onClick.AddListener(() => { SetArmorEntity(GeneralEnum.EQUIP_SLOT.HEAD); }); BodyEquipButton.onClick.AddListener(() => { SetArmorEntity(GeneralEnum.EQUIP_SLOT.BODY); }); WeistEquipButton.onClick.AddListener(() => { SetArmorEntity(GeneralEnum.EQUIP_SLOT.WEIST); }); LegEquipButton.onClick.AddListener(() => { SetArmorEntity(GeneralEnum.EQUIP_SLOT.LEG); }); Accessories1EquipButton.onClick.AddListener(() => { SetArmorEntity(GeneralEnum.EQUIP_SLOT.ACCESSORIES1); }); Accessories2EquipButton.onClick.AddListener(() => { SetArmorEntity(GeneralEnum.EQUIP_SLOT.ACCESSORIES2); }); } public void ProhibitEquipButton() { RHandEquipButton.interactable = false; LHandEquipButton.interactable = false; HeadEquipButton.interactable = false; BodyEquipButton.interactable = false; WeistEquipButton.interactable = false; LegEquipButton.interactable = false; Accessories1EquipButton.interactable = false; Accessories2EquipButton.interactable = false; } public void PermissionEquipButton() { RHandEquipButton.interactable = true; LHandEquipButton.interactable = true; HeadEquipButton.interactable = true; BodyEquipButton.interactable = true; WeistEquipButton.interactable = true; LegEquipButton.interactable = true; Accessories1EquipButton.interactable = true; Accessories2EquipButton.interactable = true; } public void PushRemoveEquipButton(PlayerManager playerManager, GeneralEnum.EQUIP_SLOT equipSlot) { //武器と防具両方のEntityの変数を用意する WeaponEntity tempWeapon; ArmorEntity tempArmor; if (equipSlot == GeneralEnum.EQUIP_SLOT.RIGHTHAND || equipSlot == GeneralEnum.EQUIP_SLOT.LEFTHAND)//右手か左手の場合 { //装備している武器もしくは防具を一時変数に入れる if (playerManager.equipWeapons[equipSlot].nowEquip) { tempWeapon = playerManager.equipWeapons[equipSlot]; tempArmor = new ArmorEntity(); } else if (playerManager.equipArmors[equipSlot].nowEquip) { tempWeapon = new WeaponEntity(); tempArmor = playerManager.equipArmors[equipSlot]; } else { tempWeapon = new WeaponEntity(); tempArmor = new ArmorEntity(); } //装備していた武器・防具の装備中フラグをfalseにする tempWeapon.nowEquip = false; tempArmor.nowEquip = false; //装備部位の装備を削除する playerManager.equipWeapons[equipSlot] = new WeaponEntity(); playerManager.equipArmors[equipSlot] = new ArmorEntity(); //リストに装備していた武器もしくは防具を代入する。 if(tempWeapon.isRegistry) WeaponManager.instance.RegiEntity(tempWeapon); if(tempArmor.isRegistry) ArmorManager.instance.RegiEntity(tempArmor); } else//右手左手以外の場合 { //装備していた防具を一時変数に入れる tempArmor = playerManager.equipArmors[equipSlot]; //装備していた防具の装備中フラグをfalseにする tempArmor.nowEquip = false; //装備部位の装備を削除する playerManager.equipArmors[equipSlot] = new ArmorEntity(); //リストに装備していた防具を代入する。 if (tempArmor.isRegistry) ArmorManager.instance.RegiEntity(tempArmor); } SoundManager.instance.PlaySE(35); } /// <summary> /// ListPanelに所持している武器を表示させる関数。表示する武器が一つでもある場合はtrue,一つもない場合はfalseを返す。 /// </summary> /// <param name="equip_slot"></param> /// <returns></returns> public bool SetWeaponEntity(GeneralEnum.EQUIP_SLOT equip_slot) { bool existWeapon = false; for(int i = 0; i < 500; i++) { bool b1 = WeaponManager.instance.possessionWeapon[i].isRegistry; if (b1) { bool b2 = false; WeaponManager.WeaponItem weaponID = WeaponManager.instance.possessionWeapon[i].weaponID;//登録してあるWeaponEntityの元WeaponDataを取得 for (int j = 0; j < WeaponManager.instance.weaponDatas.Length; j++) { b2 = (WeaponManager.instance.weaponDatas[j].weaponID == weaponID); if (b2)//WeaponEntityの元WeaponDataがWeaponManagerに登録されていたら { GameObject Contents = new GameObject("Contents" + (i + 1).ToString()); existWeapon = true;//武器存在フラグをtrueにする。 Contents.transform.parent = content.transform; var Rect = Contents.AddComponent<RectTransform>(); Rect.transform.localPosition = new Vector3(0, 0, 0); Rect.transform.localScale = new Vector3(1, 1, 1); Rect.sizeDelta = new Vector2(0, 80); Contents.AddComponent<CanvasRenderer>(); Contents.AddComponent<Image>(); Contents.AddComponent<LayoutElement>().preferredHeight = 80; var buttonState = Contents.AddComponent<Button>(); var colors = buttonState.colors; colors.normalColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.highlightedColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.pressedColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.disabledColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); buttonState.colors = colors; GameObject text = new GameObject("WeaponEntity" + (i + 1).ToString()); text.transform.parent = Contents.transform; var rect = text.AddComponent<RectTransform>(); rect.transform.localPosition = new Vector3(1, 1, 1); rect.sizeDelta = new Vector2(900, 90); text.AddComponent<CanvasRenderer>(); var textChild = text.AddComponent<Text>(); //テキスト生成 //-----------武器名+強化値--------- string viewtext = ""; if(WeaponManager.instance.possessionWeapon[i].enhancementValue > 0) { viewtext = WeaponManager.instance.weaponDatas[j].weaponName + "+" + WeaponManager.instance.possessionWeapon[i].enhancementValue; } else if (WeaponManager.instance.possessionWeapon[i].enhancementValue < 0) { viewtext = WeaponManager.instance.weaponDatas[j].weaponName + WeaponManager.instance.possessionWeapon[i].enhancementValue; } else { viewtext = WeaponManager.instance.weaponDatas[j].weaponName; } textChild.text = viewtext; textChild.color = new Color(40f/255f,40f/255f,40f/255f,255f/255f); textChild.fontSize = 25; textChild.alignment = TextAnchor.MiddleLeft; textChild.horizontalOverflow = HorizontalWrapMode.Overflow; textChild.font = Resources.GetBuiltinResource(typeof(Font), "Arial.ttf") as Font; //テキストここまで //ボタンを押した時に対応する装備に変更する //ラムダ式を使用してOnclickに処理を登録する場合、引数をそのまま入れてしまうと参照がうまくいかないらしいので、一時変数を用意してそちらに一旦引数に使うデータを入れて登録する。 GeneralEnum.EQUIP_SLOT temp_Equip_slot = equip_slot; WeaponEntity temp_WeaponEntity = WeaponManager.instance.possessionWeapon[i]; PlayerManager temp_PlayerManager = PlayerManager.instance; int tempIndex = i; buttonState.onClick.AddListener(() => { ChangeWeapon(temp_Equip_slot, temp_WeaponEntity, temp_PlayerManager, tempIndex); }); buttonState.onClick.AddListener(DestroyAllItem); buttonState.onClick.AddListener(HideListPanel); buttonState.onClick.AddListener(PermissionEquipButton); RemoveEquipButton.onClick.RemoveAllListeners(); RemoveEquipButton.onClick.AddListener(() => { PushRemoveEquipButton(temp_PlayerManager, temp_Equip_slot); }); RemoveEquipButton.onClick.AddListener(DestroyAllItem); RemoveEquipButton.onClick.AddListener(HideListPanel); RemoveEquipButton.onClick.AddListener(PermissionEquipButton); RemoveEquipButton.onClick.AddListener(() => { DeleatEquipText(temp_PlayerManager, temp_Equip_slot); }); //ContentsにGridLayoutGroupをAddする var cGridLayout = Contents.AddComponent<GridLayoutGroup>() ; cGridLayout.constraint = GridLayoutGroup.Constraint.FixedColumnCount; cGridLayout.constraintCount = 2; //左側に武器のアイコンを表示する GameObject weaponIcon = new GameObject("WeaponIcon" + (i + 1).ToString()); weaponIcon.transform.parent = buttonState.transform; weaponIcon.transform.SetAsFirstSibling(); var iconRect = weaponIcon.AddComponent<RectTransform>(); iconRect.transform.localPosition = new Vector3(0, 0, 0); iconRect.transform.localScale = new Vector3(0.8f, 0.8f, 0.8f); weaponIcon.AddComponent<CanvasRenderer>(); var iconImage = weaponIcon.AddComponent<Image>(); iconImage.sprite = WeaponManager.instance.weaponDatas[j].weaponSprite; } } } } if (existWeapon) { ShowListPanel(); ProhibitEquipButton(); } else { SoundManager.instance.PlaySE(11); } return existWeapon; } public bool SetArmorEntity(GeneralEnum.EQUIP_SLOT equip_slot) { bool existArmor = false; for (int i = 0; i < 500; i++) { bool b1 = ArmorManager.instance.possessionArmor[i].isRegistry; if (b1) { bool b2 = false; ArmorManager.ArmorItem armorID = ArmorManager.instance.possessionArmor[i].armorID; for (int j = 0; j < ArmorManager.instance.armorDatas.Length; j++) { b2 = (ArmorManager.instance.armorDatas[j].armorID == armorID); if (b2)//ArmorEntityの元ArmorDataがArmorManagerに登録されていたら { bool b3 = false; //b3に入れる条件式をアクセサリー部位か右手・左手かそうでないかで分ける if (equip_slot == GeneralEnum.EQUIP_SLOT.ACCESSORIES1 || equip_slot == GeneralEnum.EQUIP_SLOT.ACCESSORIES2) { b3 = (ArmorManager.instance.armorDatas[j].equipPart == GeneralEnum.EQUIP_SLOT.ACCESSORIES); }else if (equip_slot == GeneralEnum.EQUIP_SLOT.RIGHTHAND || equip_slot == GeneralEnum.EQUIP_SLOT.LEFTHAND) { b3 = (ArmorManager.instance.armorDatas[j].equipPart == GeneralEnum.EQUIP_SLOT.ONEHAND); } else { b3 = (ArmorManager.instance.armorDatas[j].equipPart == equip_slot); } if (b3) { GameObject Contents = new GameObject("Contents" + (i + 1).ToString()); existArmor = true;//防具存在フラグをtrueにする。 Contents.transform.parent = content.transform; var Rect = Contents.AddComponent<RectTransform>(); Rect.transform.localPosition = new Vector3(0, 0, 0); Rect.transform.localScale = new Vector3(1, 1, 1); Rect.sizeDelta = new Vector2(0, 80); Contents.AddComponent<CanvasRenderer>(); Contents.AddComponent<Image>(); Contents.AddComponent<LayoutElement>().preferredHeight = 80; var buttonState = Contents.AddComponent<Button>(); var colors = buttonState.colors; colors.normalColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.highlightedColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.pressedColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.disabledColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); buttonState.colors = colors; GameObject text = new GameObject("ArmorEntity" + (i + 1).ToString()); text.transform.parent = Contents.transform; var rect = text.AddComponent<RectTransform>(); rect.transform.localPosition = new Vector3(1, 1, 1); rect.sizeDelta = new Vector2(900, 90); text.AddComponent<CanvasRenderer>(); var textChild = text.AddComponent<Text>(); //テキスト生成 //-----------防具名+強化値--------- string viewtext = ""; if(ArmorManager.instance.possessionArmor[i].enhancementValue > 0) { viewtext = ArmorManager.instance.armorDatas[j].armorName + "+" + ArmorManager.instance.possessionArmor[i].enhancementValue; }else if(ArmorManager.instance.possessionArmor[i].enhancementValue < 0) { viewtext = ArmorManager.instance.armorDatas[j].armorName + ArmorManager.instance.possessionArmor[i].enhancementValue; } else { viewtext = ArmorManager.instance.armorDatas[j].armorName; } textChild.text = viewtext; textChild.color = new Color(40f / 255f, 40f / 255f, 40f / 255f, 255f / 255f); textChild.fontSize = 25; textChild.alignment = TextAnchor.MiddleLeft; textChild.horizontalOverflow = HorizontalWrapMode.Overflow; textChild.font = Resources.GetBuiltinResource(typeof(Font), "Arial.ttf") as Font; //テキストここまで //ボタンを押した時に対応する装備に変更する //ラムダ式を使用してOnclickに処理を登録する場合、引数をそのまま入れてしまうと参照がうまくいかないらしいので、一時変数を用意してそちらに一旦引数に使うデータを入れて登録する。 GeneralEnum.EQUIP_SLOT temp_Equip_slot = equip_slot; ArmorEntity temp_ArmorEntity = ArmorManager.instance.possessionArmor[i]; PlayerManager temp_PlayerManager = PlayerManager.instance; int tempIndex = i; buttonState.onClick.AddListener(() => { ChangeArmor(temp_Equip_slot, temp_ArmorEntity, temp_PlayerManager, tempIndex); }); buttonState.onClick.AddListener(DestroyAllItem); buttonState.onClick.AddListener(HideListPanel); buttonState.onClick.AddListener(PermissionEquipButton); RemoveEquipButton.onClick.RemoveAllListeners(); RemoveEquipButton.onClick.AddListener(() => { PushRemoveEquipButton(temp_PlayerManager, temp_Equip_slot); }); RemoveEquipButton.onClick.AddListener(DestroyAllItem) ; RemoveEquipButton.onClick.AddListener(HideListPanel) ; RemoveEquipButton.onClick.AddListener(PermissionEquipButton); RemoveEquipButton.onClick.AddListener(() => { DeleatEquipText(temp_PlayerManager, temp_Equip_slot); }); //ContentsにGridLayoutGroupをAddする var cGridLayout = Contents.AddComponent<GridLayoutGroup>(); cGridLayout.constraint = GridLayoutGroup.Constraint.FixedColumnCount; cGridLayout.constraintCount = 2; //左側に防具のアイコンを表示する GameObject armorIcon = new GameObject("ArmorIcon" + (i + 1).ToString()); armorIcon.transform.parent = buttonState.transform; armorIcon.transform.SetAsFirstSibling(); var iconRect = armorIcon.AddComponent<RectTransform>(); iconRect.transform.localPosition = new Vector3(0, 0, 0); iconRect.transform.localScale = new Vector3(0.8f, 0.8f, 0.8f); armorIcon.AddComponent<CanvasRenderer>(); var iconImage = armorIcon.AddComponent<Image>(); iconImage.sprite = ArmorManager.instance.armorDatas[j].armorSprite; } } } } } if (existArmor) { ShowListPanel(); ProhibitEquipButton(); } else { SoundManager.instance.PlaySE(11); } return existArmor; } public void ShowListPanel() { listPanel.gameObject.SetActive(true); SoundManager.instance.PlaySE(33); } public void HideListPanel() { listPanel.gameObject.SetActive(false); } public void DestroyAllItem() { if (content.gameObject.transform.childCount != 0) { foreach (Transform child in content.gameObject.transform) { //全要素削除 Destroy(child.gameObject); } } } public void ChangeWeapon(GeneralEnum.EQUIP_SLOT equip_slot,WeaponEntity weaponEntity, PlayerManager playerManager, int index) { WeaponData weaponData = WeaponManager.instance.GetWeaponDataFromEntity(weaponEntity); WeaponData nowEquipRWeaponData = WeaponManager.instance.GetWeaponDataFromEntity(playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND]); WeaponData nowEquipLWeaponData = WeaponManager.instance.GetWeaponDataFromEntity(playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND]); //武器と防具の一時変数を用意する ArmorEntity tempRHandAEntity; ArmorEntity tempLHandAEntity; WeaponEntity tempREntity; WeaponEntity tempLEntity; //右手からチェック if (playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND].nowEquip)//防具装備中なら { tempRHandAEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND]; tempREntity = new WeaponEntity(); } else if (playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].nowEquip)//武器装備中なら { tempRHandAEntity = new ArmorEntity(); tempREntity = playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND]; } else { tempRHandAEntity = new ArmorEntity(); tempREntity = new WeaponEntity(); } //左手からチェック if (playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND].nowEquip)//防具装備中なら { tempLHandAEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND]; tempLEntity = new WeaponEntity(); } else if (playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].nowEquip)//武器装備中なら { tempLHandAEntity = new ArmorEntity(); tempLEntity = playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND]; } else { tempLHandAEntity = new ArmorEntity(); tempLEntity = new WeaponEntity(); } if (weaponData.equipPart == GeneralEnum.EQUIP_SLOT.ONEHAND)//新しく装備する武器が片手用なら { if(tempREntity.equipPart == GeneralEnum.EQUIP_SLOT.BOTHHANDS || tempLEntity.equipPart == GeneralEnum.EQUIP_SLOT.BOTHHANDS) {//両手武器を装備中なら tempREntity.nowEquip = false; tempLEntity.nowEquip = false; weaponEntity.nowEquip = true; //右手左手のEntityを初期化 playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); playerManager.equipWeapons[equip_slot] = weaponEntity;//選択した武器を装備部位に代入する WeaponManager.instance.possessionWeapon[index] = new WeaponEntity(); if (tempREntity.isRegistry) WeaponManager.instance.RegiEntity(tempREntity); if (tempLEntity.isRegistry) WeaponManager.instance.RegiEntity(tempLEntity); //装備部位のテキストを反映する UpdateAllWeaponText(playerManager); } else//両手武器を装備していない場合 { if(equip_slot == GeneralEnum.EQUIP_SLOT.RIGHTHAND)//右手の場合 { //装備していた武器・防具の装備中フラグをfalseにする tempREntity.nowEquip = false; tempRHandAEntity.nowEquip = false; weaponEntity.nowEquip = true;//今から装備する武器の装備中フラグをtrueにする //右手の武器・防具を削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new ArmorEntity(); playerManager.equipWeapons[equip_slot] = weaponEntity;//選択した武器を装備部位に代入する。 WeaponManager.instance.possessionWeapon[index] = new WeaponEntity(); if (tempREntity.isRegistry) WeaponManager.instance.RegiEntity(tempREntity); if (tempRHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempRHandAEntity); }else if (equip_slot == GeneralEnum.EQUIP_SLOT.LEFTHAND)//左手の場合 { //装備していた武器・防具の装備中フラグをfalseにする tempLEntity.nowEquip = false; tempLHandAEntity.nowEquip = false; weaponEntity.nowEquip = true;//今から装備する武器の装備中フラグをtrueにする //左手の武器・防具を削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new ArmorEntity(); playerManager.equipWeapons[equip_slot] = weaponEntity;//選択した武器を装備部位に代入する。 WeaponManager.instance.possessionWeapon[index] = new WeaponEntity(); if (tempLEntity.isRegistry) WeaponManager.instance.RegiEntity(tempLEntity); if (tempLHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempLHandAEntity); } UpdateWeaponText(playerManager,weaponEntity,equip_slot); } }else if (weaponData.equipPart == GeneralEnum.EQUIP_SLOT.BOTHHANDS) {//新しく装備する武器が両手用なら //装備中フラグをfalseに tempREntity.nowEquip = false; tempLEntity.nowEquip = false; tempRHandAEntity.nowEquip = false; tempLHandAEntity.nowEquip = false; weaponEntity.nowEquip = true;//今から装備する武器のフラグをtrueに //右手左手のEntityを削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new ArmorEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new ArmorEntity(); //選択した武器を装備部位に代入する。 playerManager.equipWeapons[equip_slot] = weaponEntity; //選択した武器をリストから削除する WeaponManager.instance.possessionWeapon[index] = new WeaponEntity(); //リストに装備していた武器もしくは防具を代入する。 if (tempREntity.isRegistry) WeaponManager.instance.RegiEntity(tempREntity); if (tempLEntity.isRegistry) WeaponManager.instance.RegiEntity(tempLEntity); if (tempRHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempRHandAEntity); if (tempLHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempLHandAEntity); //装備部位のテキストを反映する UpdateAllWeaponText(playerManager); } SoundManager.instance.PlaySE(34); } public void ChangeArmor(GeneralEnum.EQUIP_SLOT equip_slot, ArmorEntity armorEntity, PlayerManager playerManager, int index) { //装備部位が右手か左手の場合 if(equip_slot==GeneralEnum.EQUIP_SLOT.RIGHTHAND || equip_slot == GeneralEnum.EQUIP_SLOT.LEFTHAND) { //右手・左手の装備をそれぞれチェックする ArmorEntity tempRHandAEntity; ArmorEntity tempLHandAEntity; WeaponEntity tempRHandWEntity; WeaponEntity tempLHandWEntity; //右手からチェック if (playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND].nowEquip)//防具装備中なら { tempRHandAEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND]; tempRHandWEntity = new WeaponEntity(); }else if (playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].nowEquip)//武器装備中なら { tempRHandAEntity = new ArmorEntity(); tempRHandWEntity = playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND]; } else { tempRHandAEntity = new ArmorEntity(); tempRHandWEntity = new WeaponEntity(); } //左手からチェック if (playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND].nowEquip)//防具装備中なら { tempLHandAEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND]; tempLHandWEntity = new WeaponEntity(); } else if (playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].nowEquip)//武器装備中なら { tempLHandAEntity = new ArmorEntity(); tempLHandWEntity = playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND]; } else { tempLHandAEntity = new ArmorEntity(); tempLHandWEntity = new WeaponEntity(); } //両手武器を装備していたら if(tempRHandWEntity.equipPart == GeneralEnum.EQUIP_SLOT.BOTHHANDS || tempLHandWEntity.equipPart == GeneralEnum.EQUIP_SLOT.BOTHHANDS) { tempRHandWEntity.nowEquip = false; tempLHandWEntity.nowEquip = false; armorEntity.nowEquip = true; //右手左手の装備を削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); playerManager.equipArmors[equip_slot] = armorEntity;//選択した防具を装備部位に代入する。 UpdateArmorText(playerManager, playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND], GeneralEnum.EQUIP_SLOT.RIGHTHAND); UpdateArmorText(playerManager, playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND], GeneralEnum.EQUIP_SLOT.LEFTHAND); //選択した防具をリストから削除する ArmorManager.instance.possessionArmor[index] = new ArmorEntity(); //リストに装備していた武器を代入する。(両手武器の場合は武器だけ処理すればいい.isRegistryがfalseなら装備されてない部位) if (tempRHandWEntity.isRegistry) WeaponManager.instance.RegiEntity(tempRHandWEntity); if (tempLHandWEntity.isRegistry) WeaponManager.instance.RegiEntity(tempLHandWEntity); } else//両手武器を装備していない場合 { if(equip_slot == GeneralEnum.EQUIP_SLOT.RIGHTHAND)//右手の場合 { //装備していた武器・防具の装備中フラグをfalseにする tempRHandWEntity.nowEquip = false; tempRHandAEntity.nowEquip = false; armorEntity.nowEquip = true;//今から装備する防具の装備中フラグをtrueにする //右手の武器・防具を削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new ArmorEntity(); playerManager.equipArmors[equip_slot] = armorEntity;//選択した防具を装備部位に代入する。 UpdateArmorText(playerManager, armorEntity, equip_slot); //選択した防具をリストから削除する ArmorManager.instance.possessionArmor[index] = new ArmorEntity(); //リストに装備していた武器もしくは防具を代入する。 if (tempRHandWEntity.isRegistry) WeaponManager.instance.RegiEntity(tempRHandWEntity); if (tempRHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempRHandAEntity); } else if(equip_slot == GeneralEnum.EQUIP_SLOT.LEFTHAND)//左手の場合 { //装備していた武器・防具の装備中フラグをfalseにする tempLHandWEntity.nowEquip = false; tempLHandAEntity.nowEquip = false; armorEntity.nowEquip = true;//今から装備する防具の装備中フラグをtrueにする //右手の武器・防具を削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new ArmorEntity(); playerManager.equipArmors[equip_slot] = armorEntity;//選択した防具を装備部位に代入する。 UpdateArmorText(playerManager, armorEntity, equip_slot); //選択した防具をリストから削除する ArmorManager.instance.possessionArmor[index] = new ArmorEntity(); //リストに装備していた武器もしくは防具を代入する。 if (tempLHandWEntity.isRegistry) WeaponManager.instance.RegiEntity(tempLHandWEntity); if (tempLHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempLHandAEntity); } } } else//装備部位が右手左手じゃない場合 { //現在装備中の防具を一時変数に入れる ArmorEntity tempEntity = playerManager.equipArmors[equip_slot]; //装備中フラグをfalseに tempEntity.nowEquip = false; armorEntity.nowEquip = true;//今から装備する防具のフラグをtrueに //選択した防具を装備部位に代入する。 playerManager.equipArmors[equip_slot] = armorEntity; //装備部位のテキストを反映する UpdateArmorText(playerManager, armorEntity, equip_slot); //リストに装備していた防具を代入する。 ArmorManager.instance.possessionArmor[index] = tempEntity; } SoundManager.instance.PlaySE(34); } public void UpdateWeaponText(PlayerManager playerManager,WeaponEntity weaponEntity, GeneralEnum.EQUIP_SLOT equip_slot) { WeaponData weaponData = WeaponManager.instance.GetWeaponDataFromEntity(weaponEntity); string viewtext = ""; string weaponName = weaponData.weaponName; if (weaponEntity.enhancementValue > 0) { viewtext = weaponName + " +" + weaponEntity.enhancementValue; } else if(weaponEntity.enhancementValue < 0) { viewtext = weaponName + weaponEntity.enhancementValue; } else { viewtext = weaponName; } switch (equip_slot) { case GeneralEnum.EQUIP_SLOT.RIGHTHAND: RHandEquipText.text = viewtext; break; case GeneralEnum.EQUIP_SLOT.LEFTHAND: LHandEquipText.text = viewtext; break; default: break; } } public void UpdateAllWeaponText(PlayerManager playerManager) { WeaponEntity RHandWeaponEntity = playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND]; WeaponData RHandWeaponData = WeaponManager.instance.GetWeaponDataFromEntity(RHandWeaponEntity); WeaponEntity LHandWeaponEntity = playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND]; WeaponData LHandWeaponData = WeaponManager.instance.GetWeaponDataFromEntity(LHandWeaponEntity); string RHandviewtext = ""; string RWeaponName = RHandWeaponData.weaponName; if (RHandWeaponEntity.enhancementValue > 0) { RHandviewtext = RWeaponName + " +" + RHandWeaponEntity.enhancementValue; } else if (RHandWeaponEntity.enhancementValue < 0) { RHandviewtext = RWeaponName + RHandWeaponEntity.enhancementValue; } else { RHandviewtext = RWeaponName; } string LHandviewtext = ""; string LWeaponName = LHandWeaponData.weaponName; if (LHandWeaponEntity.enhancementValue > 0) { LHandviewtext = LWeaponName + " +" + LHandWeaponEntity.enhancementValue; } else if (LHandWeaponEntity.enhancementValue < 0) { LHandviewtext = LWeaponName + LHandWeaponEntity.enhancementValue; } else { LHandviewtext = LWeaponName; } RHandEquipText.text = RHandviewtext; LHandEquipText.text = LHandviewtext; } public void UpdateArmorText(PlayerManager playerManager, ArmorEntity armorEntity, GeneralEnum.EQUIP_SLOT equip_slot) { ArmorData armorData = ArmorManager.instance.GetArmorDataFromEntity(armorEntity); string viewtext = ""; string armorName = armorData.armorName; if (armorEntity.enhancementValue > 0) { viewtext = armorName + " +" + armorEntity.enhancementValue; } else if (armorEntity.enhancementValue < 0) { viewtext = armorName + armorEntity.enhancementValue; } else { viewtext = armorName; } switch (equip_slot) { case GeneralEnum.EQUIP_SLOT.RIGHTHAND: RHandEquipText.text = viewtext; break; case GeneralEnum.EQUIP_SLOT.LEFTHAND: LHandEquipText.text = viewtext; break; case GeneralEnum.EQUIP_SLOT.HEAD: HeadEquipText.text = viewtext; break; case GeneralEnum.EQUIP_SLOT.BODY: BodyEquipText.text = viewtext; break; case GeneralEnum.EQUIP_SLOT.WEIST: WeistEquipText.text = viewtext; break; case GeneralEnum.EQUIP_SLOT.LEG: LegEquipText.text = viewtext; break; case GeneralEnum.EQUIP_SLOT.ACCESSORIES1: Accessories1EquipText.text = viewtext; break; case GeneralEnum.EQUIP_SLOT.ACCESSORIES2: Accessories2EquipText.text = viewtext; break; default: break; } } public void UpdateAllArmorText(PlayerManager playerManager) { ArmorEntity headArmorEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.HEAD]; ArmorData headArmorData = ArmorManager.instance.GetArmorDataFromEntity(headArmorEntity); ArmorEntity bodyArmorEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.BODY]; ArmorData bodyArmorData = ArmorManager.instance.GetArmorDataFromEntity(bodyArmorEntity); ArmorEntity weistArmorEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.WEIST]; ArmorData weistArmorData = ArmorManager.instance.GetArmorDataFromEntity(bodyArmorEntity); ArmorEntity legArmorEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEG]; ArmorData legArmorData = ArmorManager.instance.GetArmorDataFromEntity(legArmorEntity); ArmorEntity accessories1ArmorEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1]; ArmorData accessories1ArmorData = ArmorManager.instance.GetArmorDataFromEntity(accessories1ArmorEntity); ArmorEntity accessories2ArmorEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2]; ArmorData accessories2ArmorData = ArmorManager.instance.GetArmorDataFromEntity(accessories2ArmorEntity); string headViewText = ""; string headArmorName = headArmorData.armorName; if (headArmorEntity.enhancementValue > 0) { headViewText = headArmorName + " +" + headArmorEntity.enhancementValue; } else if (headArmorEntity.enhancementValue < 0) { headViewText = headArmorName + headArmorEntity.enhancementValue; } else { headViewText = headArmorName; } string bodyViewText = ""; string bodyArmorName = bodyArmorData.armorName; if (bodyArmorEntity.enhancementValue > 0) { bodyViewText = bodyArmorName + " +" + bodyArmorEntity.enhancementValue; } else if (bodyArmorEntity.enhancementValue < 0) { bodyViewText = bodyArmorName + bodyArmorEntity.enhancementValue; } else { bodyViewText = bodyArmorName; } string weistViewText = ""; string weistArmorName = weistArmorData.armorName; if (weistArmorEntity.enhancementValue > 0) { weistViewText = weistArmorName + " +" + weistArmorEntity.enhancementValue; } else if (weistArmorEntity.enhancementValue < 0) { weistViewText = weistArmorName + weistArmorEntity.enhancementValue; } else { weistViewText = weistArmorName; } string legViewText = ""; string legArmorName = legArmorData.armorName; if (legArmorEntity.enhancementValue > 0) { legViewText = legArmorName + " +" + legArmorEntity.enhancementValue; } else if (legArmorEntity.enhancementValue < 0) { legViewText = legArmorName + legArmorEntity.enhancementValue; } else { legViewText = legArmorName; } string accessories1ViewText = ""; string accessories1ArmorName = accessories1ArmorData.armorName; if (accessories1ArmorEntity.enhancementValue > 0) { accessories1ViewText = accessories1ArmorName + " +" + accessories1ArmorEntity.enhancementValue; } else if (accessories1ArmorEntity.enhancementValue < 0) { accessories1ViewText = accessories1ArmorName + accessories1ArmorEntity.enhancementValue; } else { accessories1ViewText = accessories1ArmorName; } string accessories2ViewText = ""; string accessories2ArmorName = accessories2ArmorData.armorName; if (accessories2ArmorEntity.enhancementValue > 0) { accessories2ViewText = accessories2ArmorName + " +" + accessories2ArmorEntity.enhancementValue; } else if (accessories2ArmorEntity.enhancementValue < 0) { accessories2ViewText = accessories2ArmorName + accessories2ArmorEntity.enhancementValue; } else { accessories2ViewText = accessories2ArmorName; } HeadEquipText.text = headViewText; BodyEquipText.text = bodyViewText; WeistEquipText.text = weistViewText; LegEquipText.text = legViewText; Accessories1EquipText.text = accessories1ViewText; Accessories2EquipText.text = accessories2ViewText; } public void DeleatEquipText(PlayerManager playerManager, GeneralEnum.EQUIP_SLOT equip_slot) { switch (equip_slot) { case GeneralEnum.EQUIP_SLOT.RIGHTHAND: RHandEquipText.text = ""; break; case GeneralEnum.EQUIP_SLOT.LEFTHAND: LHandEquipText.text = ""; break; case GeneralEnum.EQUIP_SLOT.HEAD: HeadEquipText.text = ""; break; case GeneralEnum.EQUIP_SLOT.BODY: BodyEquipText.text = ""; break; case GeneralEnum.EQUIP_SLOT.WEIST: WeistEquipText.text = ""; break; case GeneralEnum.EQUIP_SLOT.LEG: LegEquipText.text = ""; break; case GeneralEnum.EQUIP_SLOT.ACCESSORIES1: Accessories1EquipText.text = ""; break; case GeneralEnum.EQUIP_SLOT.ACCESSORIES2: Accessories2EquipText.text = ""; break; } } }
以前作成したアイテムのリストを応用して作っています。ざっくり説明すると、装備画面内で装備を変更したい箇所の部位のボタンを押すと、Start関数で実行しているSetEquipButtonListener関数が各々のEquipButtonを押した時に実行させたい関数(所持装備をリストに表示するSetWeaponEntity関数とSetArmorEntity関数)を登録します。
SetWeaponEntity,SetArmorEntity関数の中で、リスト内の武器及び防具の項目(Buttonコンポーネントを追加している)を押した時の処理も登録しています。登録している関数は、ChangeWeapon関数(もしくはDhangeArmor関数)、DestroyAllItem関数、HideListPanel関数、PermissionEquipButton関数です。
ChangeWeapon及びChangeArmor関数は指定した装備部位の装備を指定した装備に変更する処理です。今回、両手武器と盾の概念を入れたかったので、それぞれ装備した時にうまく機能するために関数内では結構複雑な処理をさせています。ChangeWeapon及びChangeArmor関数は元々装備していた武器を所持装備リストに登録する処理も行います。
DestroyAllItem関数はリストのコンテンツをすべて削除する関数です。これを実行しないと装備部位ボタンを押すたびに所持装備をリストに追加してしまうためおかしなことになります。
HideListPanel関数は装備一覧のリストを非表示にする関数です。武器及び防具の項目を押して装備変更したらリストを消したいのでこの関数も登録しておきます。
PermissionEquipButton関数は各EquipButtonの押下ができるようにする関数です。SetWeaponEntity,SetArmorEntity関数の最後で、その部位で装備できる武器もしくは防具が一つでもあればProhibitEquipButton関数を実行するようにしているのですが、これは装備一覧を出しているときは各EquipButtonを押せないようにしたいためです。装備変更を終えたらEquipButtonを押せるようにしたいのでこのPermissionEquipButton関数を登録しておきます。
更に、外すボタンを押した時の処理も登録させています。関数を登録する前にRemoveAllListenersでイベントをすべて削除します。そして、PushRemoveEquipButton関数、DestroyAllItem関数、HideListPanel関数、PermissionEquipButton関数、DeleatEquipText関数を登録します。PushRemoveEquipButton関数は、指定した装備部位の装備を外す関数で、DeleatEquipText関数は指定した装備部位のテキストを空白にする関数です。
EquipmentUIスクリプトを装備画面のCanvasに貼り付け、インスペクターの各々のオブジェクトを設定して実行すると以下の動画のようになります。
次回は装備による能力値の変化を実装していきます。
【Unity】RPG制作 その24-武器、防具アイテム実装
今回からは武器と防具の実装をやっていきたいと思います。
過去の記事(RPG制作 その4)で作成したWeaponData、ArmorDataクラスを武器と防具のベースのデータに使います。少し修正もしておきます。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; public class WeaponData : MonoBehaviour { public enum WEAPONTYPE { Dagger, //短剣 Sword, //剣 Spear, //槍 Club, //棍棒 Axe, //斧 Bow, //弓 Wand, //杖 Nail, //爪 Gun, //銃 } public enum EQUIPPART { RIGHTHAND, LEFTHAND, BOTHHANDS, //両手持ち。このタイプの武器を装備すると盾などの装備は外れる } [Header("武器識別変数")]public ItemManager.WeaponItem weaponID = ItemManager.WeaponItem.Knife; //アイテムの識別変数 [Header("武器のアイコン")] public Sprite weaponSprite; [Header("武器の説明")]public string explanation = ""; [Header("武器の名前")] public string weaponName; [Header("装備のタイプ")]public WEAPONTYPE weaponType = WEAPONTYPE.Dagger; [Header("装備部位")]public EQUIPPART equipPart = EQUIPPART.RIGHTHAND; [Header("攻撃アニメーション")]public GameObject attackAnimation = null; [Header("MaxHP変化量")]public int changeMaxHP = 0; [Header("MaxMP変化量")]public int changeMaxMP = 0; [Header("MaxTP変化量")]public int changeMaxTP = 0; [Header("攻撃力変化量")]public int changeAtk = 0; [Header("防御力変化量")]public int changeDef = 0; [Header("速さ変化量")]public int changeAgi = 0; [Header("運の良さ変化量")]public int changeLuk = 0; [Header("感覚の鋭さ変化量")]public int changeSence = 0; [Header("命中率変化量")]public int changeHitRate = 0; [Header("回避率変化量")]public int changeEvasionRate = 0; [Header("魔力変化量")]public int changeMagPow = 0; [Header("習得力変化量")]public int changeLearnAbi = 0; [Header("クリティカル率変化量")]public int changeCriticalRate = 0; [Header("基本販売価格")]public int price = 0; [Header("アイテムとして使えるか?(1:使える,0:使えない)")] public int canUseForItem = 0; //--------STATUSCONDITIONからGeneralEnum.STATUSCONDITIONに変更 [Header("付与ステータス状態1")]public GeneralEnum.STATUSCONDITION addStatusCondi1 = GeneralEnum.STATUSCONDITION.NONE; [Header("付与確率1")] public int addProbability1 = 0; [Header("付与ステータス状態2")]public GeneralEnum.STATUSCONDITION addStatusCondi2 = GeneralEnum.STATUSCONDITION.NONE; [Header("付与確率2")] public int addProbability2 = 0; [Header("付与ステータス状態3")]public GeneralEnum.STATUSCONDITION addStatusCondi3 = GeneralEnum.STATUSCONDITION.NONE; [Header("付与確率3")] public int addProbability3 = 0; //-------------------------------------------------- //-----------------------New--------------------- [Header("付与属性1")]public GeneralEnum.ELEMENT addElement1 = GeneralEnum.ELEMENT.NONE; [Header("付与属性2")] public GeneralEnum.ELEMENT addElement2 = GeneralEnum.ELEMENT.NONE; [Header("エンチャントスロット数")] public int slotCount = 0;//実際はここで決めた数値に+αする予定 }
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ArmorData : MonoBehaviour { public enum EQUIPTYPE { CLOTHES, ARMOR, ROBE, SHIELD, GREATSHIELD, HAT, HELM, } public enum EQUIPPART //装備スロットの列挙型定数 New { RIGHTHAND, LEFTHAND, HEAD, BODY, WEIST, LEG, ACCESSORIES1, ACCESSORIES2, } [Header("防具識別変数")] public ItemManager.ArmorItem armorID = ItemManager.ArmorItem.紙の帽子; [Header("防具のアイコン")] public Sprite armorSprite; [Header("防具の名前")] public string itemName = ""; [Header("アイテムの説明")] public string explanation = ""; [Header("装備タイプ")] public EQUIPTYPE equipType = EQUIPTYPE.SHIELD; [Header("装備部位")] public EQUIPPART equipPart = EQUIPPART.HEAD; [Header("MaxHP変化量")] public int changeMaxHP = 0; [Header("MaxMP変化量")] public int changeMaxMP = 0; [Header("MaxTP変化量")] public int changeMaxTP = 0; [Header("攻撃力変化量")] public int changeAtk = 0; [Header("防御力変化量")] public int changeDef = 0; [Header("速さ変化量")] public int changeAgi = 0; [Header("運の良さ変化量")] public int changeLuk = 0; [Header("感覚の鋭さ変化量")] public int changeSence = 0; [Header("命中率変化量")] public int changeHitRate = 0; [Header("回避率変化量")] public int changeEvasionRate = 0; [Header("魔力変化量")] public int changeMagPow = 0; [Header("習得力変化量")] public int changeLearnAbi = 0; [Header("クリティカル率変化量")] public int changeCriticalRate = 0; [Header("基本販売価格")] public int price = 0; [Header("アイテムとして使えるか?(1:使える,0:使えない)")] public int canUseForItem = 0; [Header("使用時の文章(探索時)")] public string useMessage_quest = ""; [Header("使用時の文章(戦闘時)")] public string useMessage_battle = ""; [Header("使用後のアイテム変化")] public ItemManager.ArmorItem changeItemAfterUse; //----------ELEMENTをGeneralEnum.ELEMENTに変更--------- [Header("属性耐性1")] public GeneralEnum.ELEMENT resiElement1; [Header("|__防御率(%)")] public int resiValueOfElement1; [Header("属性耐性2")] public GeneralEnum.ELEMENT resiElement2; [Header("|__防御率(%)")] public int resiValueOfElement2; [Header("属性耐性3")] public GeneralEnum.ELEMENT resiElement3; [Header("|__防御率(%)")] public int resiValueOfElement3; //------------------------------------------------- //----------STATUSCONDITIONをGeneralEnum.STATUSCONDITIONに変更------ [Header("状態耐性1")] public GeneralEnum.STATUSCONDITION resiStatusCondi1; [Header("|__防御率(%)")] public int resiValueOfCondi1; [Header("状態耐性2")] public GeneralEnum.STATUSCONDITION resiStatusCondi2; [Header("|__防御率(%)")] public int resiValueOfCondi2; [Header("状態耐性3")] public GeneralEnum.STATUSCONDITION resiStatusCondi3; [Header("|__防御率(%)")] public int resiValueOfCondi3; //------------------------------------------------------ [Header("エンチャントスロット数")] public int slotNumber = 0; //New }
これらのデータをもとに作成される武器、防具の個体データを扱うクラス、WeaponEntityとArmorEntityを作成します。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; //WeaponDataをもとに作成される武器の個体クラス public class WeaponEntity : MonoBehaviour { public enum ENCHANTMENTTYPE { EMPTY, //空きスロット NONE,//使えないスロット MAXHP_PLUS,//MAXHP増加 MAXMP_PLUS,//MAXMP増加 MAXTP_PLUS,//MAXTP増加 ATK_PLUS,//攻撃力増加 DEF_PLUS, //防御力増加 AGI_PLUS, //速さ増加 LUK_PLUS, //運の良さ増加 SENCE_PLUS, //感覚の鋭さ増加 HITRATE_PLUS,//命中率増加 EVASIONRATE_PLUS,//回避率増加 MAGPOW_PLUS, //魔力増加 LEARNABI_PLUS, //習得増加 MAXHP_MINUS,//MAXHP減少 MAXMP_MINUS,//MAXMP減少 MAXTP_MINUS,//MAXTP減少 ATK_MINUS,//攻撃力減少 DEF_MINUS, //防御力減少 AGI_MINUS, //速さ減少 LUK_MINUS, //運の良さ減少 SENCE_MINUS, //感覚の鋭さ減少 HITRATE_MINUS,//命中率減少 EVASIONRATE_MINUS,//回避率減少 MAGPOW_MINUS, //魔力減少 LEARNABI_MINUS, //習得減少 } //武器識別変数、各ステータスの変化量、販売価格、アイテムとして使えるか、付与ステータス1~3及び付与確率 [System.NonSerialized] public bool isRegistry = false; [System.NonSerialized] public ItemManager.WeaponItem weaponID; //武器の識別変数 [System.NonSerialized] public int changeMaxHP;//MaxHP変化量 [System.NonSerialized] public int changeMaxMP;//MaxMP変化量 [System.NonSerialized] public int changeMaxTP;//MaxTP変化量 [System.NonSerialized] public int changeAtk;//攻撃力変化量 [System.NonSerialized] public int changeDef;//防御力変化量 [System.NonSerialized] public int changeAgi;//速さ変化量 [System.NonSerialized] public int changeLuk;//運の良さ変化量 [System.NonSerialized] public int changeSence;//感覚の鋭さ変化量 [System.NonSerialized] public int changeHitRate;//命中率変化量 [System.NonSerialized] public int changeEvasionRate;//回避率変化量 [System.NonSerialized] public int changeMagPow;//魔力変化量 [System.NonSerialized] public int changeLearnAbi;//習得力変化量 [System.NonSerialized] public int changeCriticalRate;//クリティカル率変化量 [System.NonSerialized] public int price;//この武器個体の販売価格 [System.NonSerialized] public GeneralEnum.STATUSCONDITION addStatusCondi1;//付与状態異常1 public int addProbability1;//付与確率1 [System.NonSerialized] public GeneralEnum.STATUSCONDITION addStatusCondi2;//付与状態異常2 public int addProbability2;//付与確率2 [System.NonSerialized] public GeneralEnum.STATUSCONDITION addStatusCondi3;//付与状態異常3 public int addProbability3;//付与確率3 //-------ここまではWeaponDataをもとに数値を決める //-------ここからはWeaponDataの数値によらない変数 [System.NonSerialized] public int enhancementValue;//武器個体の強化値 [System.NonSerialized] public int slotCount;//武器個体のエンチャントスロット数 [System.NonSerialized] public ENCHANTMENTTYPE[] enchantSlots = new ENCHANTMENTTYPE[10]; //エンチャントスロットの配列 void Start() { } void Update() { } /// <summary> /// WeaponDataをもとにWeaponEntityを初期化する /// </summary> public void InitWeaponEntity(WeaponData weaponData) { weaponID = weaponData.weaponID; changeMaxHP = weaponData.changeMaxHP; changeMaxMP = weaponData.changeMaxMP; changeMaxTP = weaponData.changeMaxTP; changeAtk = weaponData.changeAtk; changeDef = weaponData.changeDef; changeAgi = weaponData.changeAgi; changeLuk = weaponData.changeLuk; changeSence = weaponData.changeSence; changeHitRate = weaponData.changeHitRate; changeEvasionRate = weaponData.changeEvasionRate; changeMagPow = weaponData.changeMagPow; changeLearnAbi = weaponData.changeLearnAbi; changeCriticalRate = weaponData.changeCriticalRate; price = weaponData.price; addStatusCondi1 = weaponData.addStatusCondi1; addProbability1 = weaponData.addProbability1; addStatusCondi2 = weaponData.addStatusCondi2; addProbability2 = weaponData.addProbability2; addStatusCondi3 = weaponData.addStatusCondi3; addProbability3 = weaponData.addProbability3; for (int i = 0; i < 10; i++) { enchantSlots[i] = ENCHANTMENTTYPE.NONE; } slotCount = weaponData.slotCount; if(slotCount > 0) { for(int i = 0;i < slotCount; i++) { enchantSlots[i] = ENCHANTMENTTYPE.EMPTY; } } } }
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ArmorEntity : MonoBehaviour { public enum ENCHANTMENTTYPE { EMPTY, //空きスロット NONE,//使えないスロット MAXHP_PLUS,//MAXHP増加 MAXMP_PLUS,//MAXMP増加 MAXTP_PLUS,//MAXTP増加 ATK_PLUS,//攻撃力増加 DEF_PLUS, //防御力増加 AGI_PLUS, //速さ増加 LUK_PLUS, //運の良さ増加 SENCE_PLUS, //感覚の鋭さ増加 HITRATE_PLUS,//命中率増加 EVASIONRATE_PLUS,//回避率増加 MAGPOW_PLUS, //魔力増加 LEARNABI_PLUS, //習得増加 MAXHP_MINUS,//MAXHP減少 MAXMP_MINUS,//MAXMP減少 MAXTP_MINUS,//MAXTP減少 ATK_MINUS,//攻撃力減少 DEF_MINUS, //防御力減少 AGI_MINUS, //速さ減少 LUK_MINUS, //運の良さ減少 SENCE_MINUS, //感覚の鋭さ減少 HITRATE_MINUS,//命中率減少 EVASIONRATE_MINUS,//回避率減少 MAGPOW_MINUS, //魔力減少 LEARNABI_MINUS, //習得減少 } [System.NonSerialized] public bool isRegistry = false;//ArmorData登録済みか? [System.NonSerialized] public ItemManager.ArmorItem armorID; //防具の識別変数 [System.NonSerialized] public int changeMaxHP;//MaxHP変化量 [System.NonSerialized] public int changeMaxMP;//MaxMP変化量 [System.NonSerialized] public int changeMaxTP;//MaxTP変化量 [System.NonSerialized] public int changeAtk; //攻撃力変化量 [System.NonSerialized] public int changeDef; //防御力変化量 [System.NonSerialized] public int changeAgi;//速さ変化量 [System.NonSerialized] public int changeLuk;//運の良さ変化量 [System.NonSerialized] public int changeSence;//感覚の鋭さ変化量 [System.NonSerialized] public int changeHitRate;//命中率変化量 [System.NonSerialized] public int changeEvasionRate;//回避率変化量 [System.NonSerialized] public int changeMagPow;//魔力変化量 [System.NonSerialized] public int changeLearnAbi;//習得変化量 [System.NonSerialized] public int changeCriticalRate;//クリティカル率変化量 [System.NonSerialized] public int price; //この防具個体の販売価格 [System.NonSerialized] public GeneralEnum.ELEMENT resiElement1;//属性耐性1 [System.NonSerialized] public int resiValueOfElement1;//属性耐性1変化量(%) [System.NonSerialized] public GeneralEnum.ELEMENT resiElement2;//属性耐性2 [System.NonSerialized] public int resiValueOfElement2;//属性耐性2変化量(%) [System.NonSerialized] public GeneralEnum.ELEMENT resiElement3;//属性耐性3 [System.NonSerialized] public int resiValueOfElement3;//属性耐性3変化量(%) [System.NonSerialized] public GeneralEnum.STATUSCONDITION resiStatusCondi1;//状態耐性1 [System.NonSerialized] public int resiValueOfCondi1;//状態耐性1変化量(%) [System.NonSerialized] public GeneralEnum.STATUSCONDITION resiStatusCondi2;//状態耐性2 [System.NonSerialized] public int resiValueOfCondi2;//状態耐性2変化量(%) [System.NonSerialized] public GeneralEnum.STATUSCONDITION resiStatusCondi3;//状態耐性3 [System.NonSerialized] public int resiValueOfCondi3;//状態耐性3変化量(%) //-------ここまではArmorDataをもとに数値を決める //-------ここからはArmorDataの数値によらない変数 [System.NonSerialized] public int enhancementValue;//防具個体の強化値 [System.NonSerialized] public int slotCount; //防具個体のエンチャントスロット数 [System.NonSerialized] public ENCHANTMENTTYPE[] enchantSlots = new ENCHANTMENTTYPE[10]; //エンチャントスロットの配列 // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } public void InitArmorEntity(ArmorData armorData) { isRegistry = true; armorID = armorData.armorID; changeMaxHP = armorData.changeMaxHP; changeMaxMP = armorData.changeMaxMP; changeMaxTP = armorData.changeMaxTP; changeAtk = armorData.changeAtk; changeDef = armorData.changeDef; changeAgi = armorData.changeAgi; changeLuk = armorData.changeLuk; changeSence = armorData.changeSence; changeHitRate = armorData.changeHitRate; changeEvasionRate = armorData.changeEvasionRate; changeMagPow = armorData.changeMagPow; changeLearnAbi = armorData.changeLearnAbi; changeCriticalRate = armorData.changeCriticalRate; price = armorData.price; resiElement1 = armorData.resiElement1; resiValueOfElement1 = armorData.resiValueOfElement1; resiElement2 = armorData.resiElement2; resiValueOfElement2 = armorData.resiValueOfElement2; resiElement3 = armorData.resiElement3; resiValueOfElement3 = armorData.resiValueOfElement3; resiStatusCondi1 = armorData.resiStatusCondi1; resiValueOfCondi1 = armorData.resiValueOfCondi1; resiStatusCondi2 = armorData.resiStatusCondi2; resiValueOfCondi2 = armorData.resiValueOfCondi2; resiStatusCondi3 = armorData.resiStatusCondi3; resiValueOfCondi3 = armorData.resiValueOfCondi3; for (int i = 0; i < 10; i++) { enchantSlots[i] = ENCHANTMENTTYPE.NONE; } slotCount = armorData.slotNumber; if (slotCount > 0) { for (int i = 0; i < slotCount; i++) { enchantSlots[i] = ENCHANTMENTTYPE.EMPTY; } } } }
実際に武器、防具を手に入れるイベントを作成します。イベントIDをそれぞれ13,14とします。DangeonController.csのInformDangeonEventコルーチンに処理を追加します。
クリックで展開
public IEnumerator InformDangeonEvent() { eventID = GetCurrentPosDangeonEventID(); DangeonEvent dangeonEvent = new DangeonEvent(); stageUIManager.isEventPosition = true; switch (eventID) { case -1://何もなし stageUIManager.isEventPosition = false; 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: //下階段イベントを知らせる StartCoroutine(dangeonEvent.IEInformDownFloorEvent()); yield break; case 6: //上階段イベントを知らせる StartCoroutine(dangeonEvent.IEInformUpFloorEvent()); yield break; case 7: //トラップイベントを実行する yield return StartCoroutine(dangeonEvent.IETrapEvent(5,questManager,playerUIManager)); DeleteEvent(); stageUIManager.isEventPosition = false; dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); questManager.nowEvent = false; yield break; case 8: //スイッチで開く扉イベントを知らせる StartCoroutine(dangeonEvent.IEInformSwitchDoorEvent()); yield break; case 9://青いスイッチ(OFF)イベント StartCoroutine(dangeonEvent.IEInformOffBlueSwitchEvent()); yield break; case 10://青いスイッチ(ON)イベント StartCoroutine(dangeonEvent.IEInformOnBlueSwitchEvent()); yield break; case 11://ワープイベントを知らせる StartCoroutine(dangeonEvent.IEInformWarpEvent()); yield break; case 12: //帰還イベントを知らせる StartCoroutine(dangeonEvent.IEInformReturnTownEvent()); yield break; //--------------New----------- case 13://武器入手イベントを知らせる StartCoroutine(dangeonEvent.IEInformGetWeaponEvent()); yield break; case 14://防具入手イベントを知らせる StartCoroutine(dangeonEvent.IEInformGetArmorEvent()); yield break; //--------------Newここまで----------- } if (eventID != -1 && eventID != 7) { shouldActiveActionButton = true; } else { shouldActiveActionButton = false; } }
武器、防具入手イベント時に参照するWeaponGroupクラスとArmorGroupクラスを作成します。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(fileName = "weaponGroup", menuName = "ScriptableObject/weaponGroup")] public class WeaponGroup : ScriptableObject { public string groupName; public WeaponData weaponData1; public int gainProbability1 = 0; public WeaponData weaponData2; public int gainProbability2 = 0; public WeaponData weaponData3; public int gainProbability3 = 0; public WeaponData weaponData4; public int gainProbability4 = 0; public WeaponData weaponData5; public int gainProbability5 = 0; public bool usePriority = false; public int item1Priority = 0; public int item2Priority = 0; public int item3Priority = 0; public int item4Priority = 0; public int item5Priority = 0; public WeaponData DecideWeaponData() //weaponData1~5の中からランダムでWeaponDataを一つ入手する { WeaponData weaponData = null; int tempValue = 0; int tempValue2 = 0; int sumValue = 0; if (!usePriority) { int randValue = Random.Range(0, 101); if (0 <= randValue && randValue < gainProbability1) { weaponData = weaponData1; } else if (gainProbability1 <= randValue && randValue < gainProbability2) { weaponData = weaponData2; } else if (gainProbability2 <= randValue && randValue < gainProbability3) { weaponData = weaponData3; } else if (gainProbability3 <= randValue && randValue < gainProbability4) { weaponData = weaponData4; } else if (gainProbability4 <= randValue && randValue < gainProbability5) { weaponData = weaponData5; } else { weaponData = null; } } else//プライオリティーを使用する場合 { if (item1Priority > 0) { sumValue += Mathf.Clamp(item1Priority, 0, 100); } if (item2Priority > 0) { sumValue += Mathf.Clamp(item2Priority, 0, 100); } if (item3Priority > 0) { sumValue += Mathf.Clamp(item3Priority, 0, 100); } if (item4Priority > 0) { sumValue += Mathf.Clamp(item4Priority, 0, 100); } if (item5Priority > 0) { sumValue += Mathf.Clamp(item5Priority, 0, 100); } if (sumValue == 0) { sumValue = 1; } int randValue = Random.Range(0, sumValue); if (0 <= randValue && randValue < item1Priority) { weaponData = weaponData1; } tempValue += item1Priority; tempValue2 = tempValue + item2Priority; if (tempValue <= randValue && randValue < tempValue2) { weaponData = weaponData2; } tempValue += item2Priority; tempValue2 = tempValue + item3Priority; if (tempValue <= randValue && randValue < tempValue2) { weaponData = weaponData3; } tempValue += item3Priority; tempValue2 = tempValue + item4Priority; if (tempValue <= randValue && randValue < tempValue2) { weaponData = weaponData4; } tempValue += item4Priority; tempValue2 = tempValue + item5Priority; if (tempValue <= randValue && randValue < tempValue2) { weaponData = weaponData5; } if (weaponData == null) { weaponData = weaponData1; } } return weaponData; } }
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(fileName = "armorGroup", menuName = "ScriptableObject/armorGroup")] public class ArmorGroup : ScriptableObject { public string groupName; public ArmorData armorData1; public int gainProbability1 = 0; public ArmorData armorData2; public int gainProbability2 = 0; public ArmorData armorData3; public int gainProbability3 = 0; public ArmorData armorData4; public int gainProbability4 = 0; public ArmorData armorData5; public int gainProbability5 = 0; public bool usePriority = false; public int item1Priority = 0; public int item2Priority = 0; public int item3Priority = 0; public int item4Priority = 0; public int item5Priority = 0; public ArmorData DecideArmorData() //armorData1~5の中からランダムでArmorDataを一つ入手する { ArmorData armorData = null; int tempValue = 0; int tempValue2 = 0; int sumValue = 0; if (!usePriority) { int randValue = Random.Range(0, 101); if (0 <= randValue && randValue < gainProbability1) { armorData = armorData1; } else if (gainProbability1 <= randValue && randValue < gainProbability2) { armorData = armorData2; } else if (gainProbability2 <= randValue && randValue < gainProbability3) { armorData = armorData3; } else if (gainProbability3 <= randValue && randValue < gainProbability4) { armorData = armorData4; } else if (gainProbability4 <= randValue && randValue < gainProbability5) { armorData = armorData5; } else { armorData = null; } } else//プライオリティーを使用する場合 { if (item1Priority > 0) { sumValue += Mathf.Clamp(item1Priority, 0, 100); } if (item2Priority > 0) { sumValue += Mathf.Clamp(item2Priority, 0, 100); } if (item3Priority > 0) { sumValue += Mathf.Clamp(item3Priority, 0, 100); } if (item4Priority > 0) { sumValue += Mathf.Clamp(item4Priority, 0, 100); } if (item5Priority > 0) { sumValue += Mathf.Clamp(item5Priority, 0, 100); } if (sumValue == 0) { sumValue = 1; } int randValue = Random.Range(0, sumValue); if (0 <= randValue && randValue < item1Priority) { armorData = armorData1; } tempValue += item1Priority; tempValue2 = tempValue + item2Priority; if (tempValue <= randValue && randValue < tempValue2) { armorData = armorData2; } tempValue += item2Priority; tempValue2 = tempValue + item3Priority; if (tempValue <= randValue && randValue < tempValue2) { armorData = armorData3; } tempValue += item3Priority; tempValue2 = tempValue + item4Priority; if (tempValue <= randValue && randValue < tempValue2) { armorData = armorData4; } tempValue += item4Priority; tempValue2 = tempValue + item5Priority; if (tempValue <= randValue && randValue < tempValue2) { armorData = armorData5; } if (armorData == null) { armorData = armorData1; } } return armorData; } }
入手した武器と防具(WeaponEntityとArmorEntity)を管理するWeaponManagerとArmorManagerを作成します。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; //手に入れた武器を管理するクラス public class WeaponManager : MonoBehaviour { //シングルトン(すべてのシーンで共有する)) public static WeaponManager instance; private void Awake() { if (instance == null) { instance = this; DontDestroyOnLoad(this.gameObject); } else { Destroy(this.gameObject); } } //--シングルトン終わり-- public WeaponData[] weaponDatas; [System.NonSerialized] public WeaponEntity[] possessionWeapon = new WeaponEntity[500]; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } public void InitPossessionWeapon() { for(int i = 0; i < possessionWeapon.Length; i++) { possessionWeapon[i] = new WeaponEntity(); } } /// <summary> /// 武器の強化値を上げる関数 /// </summary> public void StrengthenWeapon(int index, int upValue) { possessionWeapon[index].enhancementValue += upValue; } /// <summary> /// 指定した武器をpossessionWeaponに加える。 /// </summary> /// <param name="weaponData"></param> public bool AddWeapon(WeaponData weaponData) { bool successAdd = false; WeaponEntity weaponEntity = new WeaponEntity(); weaponEntity.InitWeaponEntity(weaponData); for(int i = 0; i < possessionWeapon.Length; i++) { if(!possessionWeapon[i].isRegistry) { possessionWeapon[i] = weaponEntity; successAdd = true; } } return successAdd; } public void DeleteWeapon(int index) { possessionWeapon[index] = new WeaponEntity(); } }
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ArmorManager : MonoBehaviour { //シングルトン(すべてのシーンで共有する)) public static ArmorManager instance; private void Awake() { if (instance == null) { instance = this; DontDestroyOnLoad(this.gameObject); } else { Destroy(this.gameObject); } } //--シングルトン終わり-- public ArmorData[] armorDatas; [System.NonSerialized] public ArmorEntity[] possessionArmor = new ArmorEntity[500]; // Start is called before the first frame update void Start() { InitPossessionArmor(); } // Update is called once per frame void Update() { } public void InitPossessionArmor() { for (int i = 0; i < possessionArmor.Length; i++) { possessionArmor[i] = new ArmorEntity(); } } /// <summary> /// 防具の強化値を上げる関数 /// </summary> public void StrengthenArmor(int index, int upValue) { possessionArmor[index].enhancementValue += upValue; } }
DangeonController.csにWeaponGroup型とArmorGroup型の変数を宣言します。
クリックで展開
//-------------------New---------------- [SerializeField] WeaponGroup weaponGroup1; [SerializeField] WeaponGroup weaponGroup2; [SerializeField] WeaponGroup weaponGroup3; [SerializeField] ArmorGroup armorGroup1; [SerializeField] ArmorGroup armorGroup2; [SerializeField] ArmorGroup armorGroup3; //-------------------Newここまで----------------
DangeonEvent.csでイベントを定義します。
クリックで展開
public IEnumerator IEInformGetWeaponEvent() { DialogTextManager.instance.SetScenarios(new string[] { "武器が落ちている・・・"}); yield return new WaitForSeconds(2f); } public IEnumerator IEInformGetArmorEvent() { DialogTextManager.instance.SetScenarios(new string[] { "防具が落ちている・・・"}); yield return new WaitForSeconds(2f); } public IEnumerator IEGetWeaponEvent(WeaponGroup weaponGroup) { WeaponData getWeapon; SoundManager.instance.PlaySE(23); getWeapon = weaponGroup.DecideWeaponData(); if (getWeapon != null) { DialogTextManager.instance.SetScenarios(new string[] { getWeapon.weaponName + "を手に入れた!"}); WeaponManager.instance.AddWeapon(getWeapon); yield return new WaitForSeconds(1.2f); } else { DialogTextManager.instance.SetScenarios(new string[] { "??何もない??"}); yield return new WaitForSeconds(1.2f); } } public IEnumerator IEGetArmorEvent(ArmorGroup armorGroup) { ArmorData getArmor; SoundManager.instance.PlaySE(23); getArmor = armorGroup.DecideArmorData(); if (getArmor != null) { DialogTextManager.instance.SetScenarios(new string[] { getArmor.armorName + "を手に入れた!"}); ArmorManager.instance.AddArmor(getArmor); yield return new WaitForSeconds(1.2f); } else { DialogTextManager.instance.SetScenarios(new string[] { "??何もない??"}); yield return new WaitForSeconds(1.2f); } }
DangeonController.csのIEDangeonEventProcessコルーチンにeventIDが13,14の時の処理を追加します。
クリックで展開
public IEnumerator IEDangeonEventProcess() { stageUIManager.SetActionButton(false); stageUIManager.SetArrowsButton(false); if (dangionMap.isOpenDangeonMap) { stageUIManager.SetCancelButton(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(); stageUIManager.isEventPosition = false; break; case 5: //階段を降りるイベント yield return dangeonEvent.IEDownFloorEvent(dangionMap, questManager,stageUIManager,this); break; case 6: //階段を上がるイベント yield return dangeonEvent.IEUpFloorEvent(dangionMap, questManager, stageUIManager,this); break; case 7://7はトラップイベントだが配置された位置に到達した時に実行されるのでここでは何もしない(というかここには処理が来ない) break; case 8: //スイッチで開く扉イベント yield return dangeonEvent.IEUpSwitchDoorEvent(); break; case 9: ////青いスイッチ(OFF)イベント yield return dangeonEvent.IEOFFBlueSwitchEvent(dangionMap,questManager,this); break; case 10: ////青いスイッチ(ON)イベント yield return dangeonEvent.IEONBlueSwitchEvent(); break; case 11: //ワープイベント yield return dangeonEvent.IEWarpEvent(dangionMap,questManager,this); UpdatePlayerPosition(); ActivePlayerPosRoom(); ActivePlayerPosEvent(); break; case 12: //帰還イベント yield return dangeonEvent.IEReturnEvent(questManager); break; //------------------New--------- case 13: //武器入手イベント yield return dangeonEvent.IEGetWeaponEvent(weaponGroup1); break; case 14: //防具入手イベント yield return dangeonEvent.IEGetArmorEvent(armorGroup1); break; //-----------------Newここまで------------ } if (shouldActiveActionButton) { stageUIManager.actionButton.SetActive(true); } else { stageUIManager.actionButton.SetActive(false); } stageUIManager.SetArrowsButton(true); if (dangionMap.isOpenDangeonMap) { stageUIManager.SetCancelButton(true); } yield return null; }
ダンジョンのフロア生成時に武器、防具入手イベントが配置されるようにします。DangeonMap.csのeventIDListにIDを追加します。
クリックで展開
public List<int> eventIDList = new List<int>() {0,1,2,3,4,7,13,14 }; //ランダムで生成させるイベントIDのリスト //13,14追加
これでイベントで武器と防具を入手できるようになりました。
ヒエラルキーにWeaponManagerとArmorManagerの名前でゲームオブジェクトを作成し、同名のスクリプトを貼り付けます。WeaponDatas、ArmorDatasにゲーム中で登場させる武器と防具を設定しておきます。それからResourceフォルダ配下にWeaponGroupとArmorGroupのScriptableObjectを作成します。それぞれ仮に設定しておきます。
あとはこのWeaponGroupとArmorGroupをDangeonController.csの方で読み込みます。
クリックで展開
private void Start() { //ResourceのScriptableObjectから各ItemGroupを読み込む mineItemGroup = Resources.Load<ItemGroup>("ItemGroups/itemGroup_MIne"); fisingItemGroup = Resources.Load<ItemGroup>("ItemGroups/itemGroup_Fising"); itemEventGroup = Resources.Load<ItemGroup>("ItemGroups/itemGroup_ItemEvent1"); loggingItemGroup = Resources.Load<ItemGroup>("ItemGroups/itemGroup_Logging"); weaponGroup1 = Resources.Load<WeaponGroup>("WeaponGroups/weaponGroup1"); //New armorGroup1 = Resources.Load<ArmorGroup>("ArmorGroups/armorGroup1"); //New //探索イベントのメモリ(イベントの残り回数保持)を初期化する InitDangeonEventmemories(); }
今回は以上です。次回は装備画面を作成したいと思います。
【Unity】RPG制作 その23-ワープイベント、帰還イベントの作成
今回はワープイベントを作成していきます。eventIDを11とします。ワープイベントを知らせる処理を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: //下階段イベントを知らせる StartCoroutine(dangeonEvent.IEInformDownFloorEvent()); yield break; case 6: //上階段イベントを知らせる StartCoroutine(dangeonEvent.IEInformUpFloorEvent()); yield break; case 7: //トラップイベントを実行する yield return StartCoroutine(dangeonEvent.IETrapEvent(5,questManager,playerUIManager)); DeleteEvent(); stageUIManager.isEventPosition = false; dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); questManager.nowEvent = false; yield break; case 8: //スイッチで開く扉イベントを知らせる StartCoroutine(dangeonEvent.IEInformSwitchDoorEvent()); yield break; case 9://青いスイッチ(OFF)イベント StartCoroutine(dangeonEvent.IEInformOffBlueSwitchEvent()); yield break; case 10://青いスイッチ(ON)イベント StartCoroutine(dangeonEvent.IEInformOnBlueSwitchEvent()); yield break; //--------------New----------- case 11://ワープイベント StartCoroutine(dangeonEvent.IEInformWarpEvent()); yield break; //--------------Newここまで----------- } }
DangeonEvent.csにIEInformWarpEventコルーチンの定義を記述します。
クリックで展開
public IEnumerator IEInformWarpEvent() //New { DialogTextManager.instance.SetScenarios(new string[] { "ワープポイントがある"}); yield return new WaitForSeconds(2f); }
実際にワープするイベントも追加します。ワープポイントは2つで1組として機能するのですが、同じフロアで2組以上設置できるように、それぞれのワープポイントがどのワープポイントに関連付けられているかをマップ横数×マップ縦数の配列で設定するようにします。DangeonMap.csに新しく配列を宣言します。
クリックで展開
public int[,,] WarpEventAssociation = new int[6, 5, 5] { { //B1F { -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 }, }, { //B2F { -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 }, }, { //B3F { -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 }, }, { //B4F { -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 }, }, { //B5F { -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 }, }, { //B6F { -1,-1,-1, 0,-1 }, { -1, 0,-1,-1, 1 }, { -1,-1,-1,-1,-1 }, { -1, 2,-1,-1,-1 }, { 1,-1,-1, 2,-1 }, } };
B6Fのワープイベントを3組設定するので、0~2の3組の数値を設定しています。B6Fのイベントのは位置と部屋構造は
以下のとおりです。
ワープイベントをDangeonEventに記述します。
クリックで展開
public IEnumerator IEWarpEvent(DangionMap dangionMap,QuestManager questManager,DangionController dangionController) //New { SoundManager.instance.PlaySE(31); int floor = questManager.currentFloor - 1; int px = dangionController.playerPos.x; int py = dangionController.playerPos.y; int warpID = dangionMap.WarpEventAssociation[floor, py, px]; for(int j = 0; j < dangionController.dangion_height; j++) { for (int i = 0; i < dangionController.dangion_width; i++) { if(dangionMap.WarpEventAssociation[floor, j, i] == warpID && (px != i || py != j)) { dangionController.playerPos.x = i; dangionController.playerPos.y = j; } } } DialogTextManager.instance.SetScenarios(new string[] { PlayerManager.instance.pname + "はワープした"}); yield return new WaitForSeconds(2f); }
プレイヤーの現在地にあるワープのIDでWarpEventAssociation配列の要素を検索して、一致するIDのワープポイントの位置に移動します。このコルーチンをDangeonController.csのIEDangeonEventProcessコルーチンで呼び出します。
クリックで展開
public IEnumerator IEDangeonEventProcess() { stageUIManager.SetActionButton(false); stageUIManager.SetArrowsButton(false); if (dangionMap.isOpenDangeonMap) { stageUIManager.SetCancelButton(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(); stageUIManager.isEventPosition = false; break; case 5: //階段を降りるイベント yield return dangeonEvent.IEDownFloorEvent(dangionMap, questManager,stageUIManager,this); break; case 6: //階段を上がるイベント yield return dangeonEvent.IEUpFloorEvent(dangionMap, questManager, stageUIManager,this); break; case 7://7はトラップイベントだが配置された位置に到達した時に実行されるのでここでは何もしない(というかここには処理が来ない) break; case 8: //スイッチで開く扉イベント yield return dangeonEvent.IEUpSwitchDoorEvent(); break; case 9: ////青いスイッチ(OFF)イベント yield return dangeonEvent.IEOFFBlueSwitchEvent(dangionMap,questManager,this); break; case 10: ////青いスイッチ(ON)イベント yield return dangeonEvent.IEONBlueSwitchEvent(); break; //------------------New--------- case 11: //ワープイベント yield return dangeonEvent.IEWarpEvent(dangionMap,questManager,this); UpdatePlayerPosition(); ActivePlayerPosRoom(); ActivePlayerPosEvent(); break; //-----------------Newここまで------------ } if(shouldActiveActionButton) { stageUIManager.actionButton.SetActive(true); } else { stageUIManager.actionButton.SetActive(false); } stageUIManager.SetArrowsButton(true); if (dangionMap.isOpenDangeonMap) { stageUIManager.SetCancelButton(true); } yield return null; }
これでワープイベントは完成しました。次に帰還イベントの作成をします。帰還イベントのIDはイベントIDは12にします。帰還イベントを知らせる処理をDangeonController.csのInformDangeonEventコルーチンに追加します。
クリックで展開
public IEnumerator InformDangeonEvent() { eventID = GetCurrentPosDangeonEventID(); DangeonEvent dangeonEvent = new DangeonEvent(); stageUIManager.isEventPosition = true; switch (eventID) { case -1://何もなし stageUIManager.isEventPosition = false; 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: //下階段イベントを知らせる StartCoroutine(dangeonEvent.IEInformDownFloorEvent()); yield break; case 6: //上階段イベントを知らせる StartCoroutine(dangeonEvent.IEInformUpFloorEvent()); yield break; case 7: //トラップイベントを実行する yield return StartCoroutine(dangeonEvent.IETrapEvent(5,questManager,playerUIManager)); DeleteEvent(); stageUIManager.isEventPosition = false; dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); questManager.nowEvent = false; yield break; case 8: //スイッチで開く扉イベントを知らせる StartCoroutine(dangeonEvent.IEInformSwitchDoorEvent()); yield break; case 9://青いスイッチ(OFF)イベント StartCoroutine(dangeonEvent.IEInformOffBlueSwitchEvent()); yield break; case 10://青いスイッチ(ON)イベント StartCoroutine(dangeonEvent.IEInformOnBlueSwitchEvent()); yield break; case 11://ワープイベントを知らせる StartCoroutine(dangeonEvent.IEInformWarpEvent()); yield break; //--------------New----------- case 12: //帰還イベントを知らせる StartCoroutine(dangeonEvent.IEInformReturnTownEvent()); yield break; //--------------Newここまで----------- } if (eventID != -1 && eventID != 7) { shouldActiveActionButton = true; } else { shouldActiveActionButton = false; } }
IEInformReturnTownEventコルーチンと実際に帰還するイベントをDangeonEvent.csで定義します。
クリックで展開
public IEnumerator IEInformReturnTownEvent() //New { DialogTextManager.instance.SetScenarios(new string[] { "帰還ポイントがある"}); yield return new WaitForSeconds(2f); } public IEnumerator IEReturnEvent(QuestManager questManager) //New { SoundManager.instance.PlaySE(32); //帰還装置SE DialogTextManager.instance.SetScenarios(new string[] { "帰還装置を作動させた。"}); yield return new WaitForSeconds(2f); yield return StartCoroutine(questManager.GotoTown()); }
DangeonController.csのIEDangeonEventProcessコルーチンでIEInformReturnTownEventコルーチンを呼び出します。
クリックで展開
public IEnumerator IEDangeonEventProcess() { stageUIManager.SetActionButton(false); stageUIManager.SetArrowsButton(false); if (dangionMap.isOpenDangeonMap) { stageUIManager.SetCancelButton(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(); stageUIManager.isEventPosition = false; break; case 5: //階段を降りるイベント yield return dangeonEvent.IEDownFloorEvent(dangionMap, questManager,stageUIManager,this); break; case 6: //階段を上がるイベント yield return dangeonEvent.IEUpFloorEvent(dangionMap, questManager, stageUIManager,this); break; case 7://7はトラップイベントだが配置された位置に到達した時に実行されるのでここでは何もしない(というかここには処理が来ない) break; case 8: //スイッチで開く扉イベント yield return dangeonEvent.IEUpSwitchDoorEvent(); break; case 9: ////青いスイッチ(OFF)イベント yield return dangeonEvent.IEOFFBlueSwitchEvent(dangionMap,questManager,this); break; case 10: ////青いスイッチ(ON)イベント yield return dangeonEvent.IEONBlueSwitchEvent(); break; case 11: //ワープイベント yield return dangeonEvent.IEWarpEvent(dangionMap,questManager,this); UpdatePlayerPosition(); ActivePlayerPosRoom(); ActivePlayerPosEvent(); break; //------------------New--------- case 12: //帰還イベント yield return dangeonEvent.IEReturnEvent(questManager); break; //-----------------Newここまで------------ } if (shouldActiveActionButton) { stageUIManager.actionButton.SetActive(true); } else { stageUIManager.actionButton.SetActive(false); } stageUIManager.SetArrowsButton(true); if (dangionMap.isOpenDangeonMap) { stageUIManager.SetCancelButton(true); } yield return null; }
これで実行すると以下の動画のようになります。
今回は以上です。
【Unity】RPG制作 その22-トラップイベント、扉のスイッチイベント実装
今回は探索時のトラップイベントやスイッチで開く扉の処理を実装していきます。
まずはじめに、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: //下階段イベントを知らせる StartCoroutine(dangeonEvent.IEInformDownFloorEvent()); yield break; case 6: //上階段イベントを知らせる StartCoroutine(dangeonEvent.IEInformUpFloorEvent()); yield break; //---------------------New------------- case 7: //トラップイベントを実行する yield return StartCoroutine(dangeonEvent.IETrapEvent(5,questManager)); DeleteEvent(); yield break; case 8: //スイッチで開く扉イベントを知らせる StartCoroutine(dangeonEvent.IEInformSwitchDoorEvent()); yield break; case 9://青いスイッチ(OFF)イベント StartCoroutine(dangeonEvent.IEInformOffBlueSwitchEvent()); yield break; case 10://青いスイッチ(ON)イベント StartCoroutine(dangeonEvent.IEInformONBlueSwitchEvent()); yield break; //------------------Newここまで---------- } }
case7~10で実行されるイベントをdangeonEvent.csで実装します。
クリックで展開
public IEnumerator IETrapEvent(int damage,QuestManager questManager) //New { DialogTextManager.instance.SetScenarios(new string[] { PlayerManager.instance.pname + "は罠にかかった!"}); SoundManager.instance.PlaySE(19); yield return new WaitForSeconds(2f); DialogTextManager.instance.SetScenarios(new string[] { PlayerManager.instance.pname + "は" + damage +"のダメージを受けた!"}); PlayerManager.instance.hp -= damage; if(PlayerManager.instance.hp <= 0) { PlayerManager.instance.hp = 0; yield return questManager.PlayerDeath(); } yield return new WaitForSeconds(2f); } public IEnumerator IEInformSwitchDoorEvent() //New { DialogTextManager.instance.SetScenarios(new string[] { "次の階層への扉がある"}); yield return new WaitForSeconds(2f); } public IEnumerator IEInformOffBlueSwitchEvent() //New { DialogTextManager.instance.SetScenarios(new string[] { "青いスイッチ(OFFになっている)がある"}); yield return new WaitForSeconds(2f); } public IEnumerator IEInformOnBlueSwitchEvent() //New { DialogTextManager.instance.SetScenarios(new string[] { "青いスイッチ(ONになっている)がある"}); yield return new WaitForSeconds(2f); }
今度は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: //階段を降りるイベント yield return dangeonEvent.IEDownFloorEvent(dangionMap, questManager,stageUIManager,this); break; case 6: //階段を上がるイベント yield return dangeonEvent.IEUpFloorEvent(dangionMap, questManager, stageUIManager,this); break; //---------------New------------- case 7://7はトラップイベントだが配置された位置に到達した時に実行されるのでここでは何もしない(というかここには処理が来ない) break; case 8: //スイッチで開く扉イベント yield return dangeonEvent.IEUpSwitchDoorEvent(); break; case 9: ////青いスイッチ(OFF)イベント yield return dangeonEvent.IEOFFBlueSwitchEvent(); break; case 10: ////青いスイッチ(ON)イベント yield return dangeonEvent.IEONBlueSwitchEvent(); break; //---------------Newここまで------------- } if (!shouldActiveActionButton) { shouldActiveActionButton = true; } else if(shouldActiveActionButton) { stageUIManager.actionButton.SetActive(true); } stageUIManager.SetArrowsButton(true); yield return null; }
IEDangeonEventProcessコルーチンで追加した各々のイベントの処理のコルーチンをDangeonEvent.csで定義します。
クリックで展開
public IEnumerator IEUpSwitchDoorEvent() //New { DialogTextManager.instance.SetScenarios(new string[] { "扉は開きそうにもない。仕掛けを解く必要があるようだ。"}); yield return new WaitForSeconds(2f); } public IEnumerator IEOFFBlueSwitchEvent(DangionMap dangionMap, QuestManager questManager, DangionController dangionController) //New { SoundManager.instance.PlaySE(29); DialogTextManager.instance.SetScenarios(new string[] { PlayerManager.instance.pname + "はスイッチを押した"}); yield return new WaitForSeconds(2f); int floor = questManager.currentFloor - 1; int py = dangionController.playerPos.y; int px = dangionController.playerPos.x; dangionMap.posOfEvent[floor, py, px] = 10;//イベントの種類を青スイッチ(ON)にする bool pushAllBlueSwitch = true; for (int j = 0; j < dangionController.dangion_height; j++) { for (int i = 0; i < dangionController.dangion_width; i++) { if (dangionMap.posOfEvent[floor, j, i] == 9)//一つでもOFFの青スイッチがあったらフラグをfalseにする { pushAllBlueSwitch = false; } } } if (pushAllBlueSwitch) //OFFの青スイッチが一つもなければ { for (int j = 0; j < dangionController.dangion_height; j++) { for (int i = 0; i < dangionController.dangion_width; i++) { if (dangionMap.posOfEvent[floor, j, i] == 8)//スイッチで開く扉のイベントを探し出して { dangionMap.posOfEvent[floor, j, i] = 5; //イベントを下り階段に変更する dangionMap.DeleteEventIcon(i,j);//アイコンを削除 SoundManager.instance.PlaySE(30); DialogTextManager.instance.SetScenarios(new string[] { "扉が開いた"}); yield return new WaitForSeconds(2f); } } } } } public IEnumerator IEONBlueSwitchEvent() //New { DialogTextManager.instance.SetScenarios(new string[] { "既に押してある"}); yield return new WaitForSeconds(2f); }
スイッチで開く扉イベントは同一フロアにある青いスイッチをすべて押した時に下り階段にイベントに変わるようになっています。
実際にうまくイベントが動くかどうか試すために、新しくダンジョン第5層を作成します。DangeonMap.csのstructOfDangeonの3次元配列とposOfEventの3次元配列に5層のデータを追加します。
クリックで展開
public int[,,] structOfDangeon = new int[5,5,5]{ { { 4, 1, 5, 4, 1 }, {14,12, 9,14,12 }, {14, 0, 0, 0,12 }, {14, 0, 0, 0,12 }, { 3,13,13,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 }, }, { { 4,11, 1,-1,-1 }, {14, 0, 0, 1,-1 }, { 3, 0, 0, 0, 1 }, {-1, 3, 0, 0,12 }, {-1,-1, 3,13, 2 }, }, //------------New--------------- { { 4,10, 1,-1, 5 }, { 7,-1, 9,-1, 9 }, { 1,10, 0,11, 1 }, { 9,-1,14, 0,12 }, { 3,10,13,13, 2 }, }, //------------Newここまで----------- }; public int[,,] posOfEvent = new int[5,5, 5] { { { -1,-1,-1,-1, 5 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1,-1 }, { 6,-1,-1,-1,-1 }, }, { { -1,-1,-1,-1, 6 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1,-1 }, { 5,-1,-1,-1,-1 }, }, { { 5,-1,-1,-1,-1 }, { -1,-1,-1,-1, 1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1, 6 }, }, { { 6,-1,-1,-1,-1 }, { -1,-1,-1,-1, 1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1, 5 }, }, //------------New--------------- { { -1,-1,-1,-1, 9 }, { 8,-1,-1,-1, 1 }, { -1,-1, 6,-1,-1 }, { -1,-1,-1,-1,-1 }, { -1,-1,-1,-1, 9 }, }, //------------Newここまで--------------- }; public int [,,]isViewRoom = new int[5, 5, 5] { //0;見えない 1:見える { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, //------------New------------ { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, //------------Newここまで------------ }; public int[,,] isViewEvent = new int[5, 5, 5] { //0;見えない 1:見える { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, //------------New------------ { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, //------------Newここまで------------ };
structOfDangeonに5層のダンジョンの部屋構造のデータ、posOfEventに5層のイベント配置(上り階段1つと青スイッチ(OFF)2つ)、isViewRoomとisViewEventにもそれぞれ5層のデータを追加しました。
あと、新しいフロアをに入った時に一定確率でトラップイベントを生成するようにします。イベントのランダム生成はDangionMap.csのSetEventNowFloorAtRandam関数で行っているので、この関数の処理を変更します。
クリックで展開
public List<int> eventIDList = new List<int>() {0,1,2,3,4,7 }; //ランダムで生成させるイベントIDのリスト public void SetEventNowFloorAtRandam(int currentFloor,int minCountOfEvent, int maxCountOfEvent) { int normaOfSetEvent = 0; int countOfSetEvent = 0; normaOfSetEvent = UnityEngine.Random.Range(minCountOfEvent, maxCountOfEvent); while (countOfSetEvent < normaOfSetEvent) { int x = UnityEngine.Random.Range(0,dangionController.dangion_width); int y = UnityEngine.Random.Range(0,dangionController.dangion_height); if (posOfEvent[currentFloor - 1, y, x] == -1 && structOfDangeon[currentFloor - 1, y, x] != -1) { posOfEvent[currentFloor - 1, y, x] = eventIDList[UnityEngine.Random.Range(0,eventIDList.Count)];//eventIDのランダム配置 countOfSetEvent++; } } }
もともとposOfEventに0~4のランダムなIDを入れていたのを、新たにeventIDListを作成して、ListのIDの中からランダムに代入するように変更しました。
このまま実行するとトラップイベントが実行される前にダンジョンマップとボタンなどが表示されてしまうので、それを直します。QuestManagerに新たに処理を追加します。
クリックで展開
public bool nowEvent = false; //探索イベント中か? [SerializeField] UnityEvent OnCompleteMoveRoom2;//部屋を移動した時にバトル、イベントあるなしに関わらず呼び出す処理 New public IEnumerator MoveOnRoom() { if(OnCompleteMoveRoom == null) OnCompleteMoveRoom = new UnityEvent();//イベント・インスタンスの生成 SoundManager.instance.PlaySE(0); stageUI.HideButtons(); yield return StartCoroutine(Searching()); OnCompleteMoveRoom2.Invoke(); if (!nowBattle && !nowEvent) //New { OnCompleteMoveRoom.Invoke(); //イベント発行 (ダンジョンマップ再表示) } }
部屋の移動を完了した時に呼び出す処理を二つに分けました。OnCompleteMoveRoom2はバトル、イベントに突入していても呼び出す関数で、OnCompleteMoveRoomはバトル、イベントに突入しなかった時に呼び出す関数です。バトル、イベントに突入した場合はボタンとマップを表示したくないので、これらの表示関数はOnCompleteMoveRoom2に登録するようにします。
現状QuestManager.csのSerachingの後半でプレイヤーがイベントが配置されている位置に来た時の処理を描いているので、ここにトラップイベントの座標に来た時の処理を追加します。
クリックで展開
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); 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()); //コルーチン呼び出し 変更 } StartCoroutine(dangionController.InformDangeonEvent()); //プレイヤーがイベントの配置されている座標に到達したらダイアログに表示する if(dangionController.eventID != -1) //何かイベントが配置されていれば { stageUI.SetActionButton(true); //ActionButtonをActiveにする stageUI.isEventPosition = true; if(dangionController.eventID == 7)//トラップイベントの場合は { stageUI.SetActionButton(false);//ActionButtonをActiveにしない nowEvent = true; //イベント中のフラグをたてる } } }
トラップイベントの場合のみ処理を分岐させています。個々の処理は後々変更があると思います。
さらにトラップイベントが終わったあとにマップの表示と、ボタンの表示、nowEventフラグをfalseにします。
クリックで展開
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: //下階段イベントを知らせる StartCoroutine(dangeonEvent.IEInformDownFloorEvent()); yield break; case 6: //上階段イベントを知らせる StartCoroutine(dangeonEvent.IEInformUpFloorEvent()); yield break; case 7: //トラップイベントを実行する yield return StartCoroutine(dangeonEvent.IETrapEvent(5,questManager)); DeleteEvent(); //------------------New---------- stageUIManager.isEventPosition = false; dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); questManager.nowEvent = false; //------------------Newここまで---------- yield break; case 8: //スイッチで開く扉イベントを知らせる StartCoroutine(dangeonEvent.IEInformSwitchDoorEvent()); yield break; case 9://青いスイッチ(OFF)イベント StartCoroutine(dangeonEvent.IEInformOffBlueSwitchEvent()); yield break; case 10://青いスイッチ(ON)イベント StartCoroutine(dangeonEvent.IEInformOnBlueSwitchEvent()); yield break; } }
DangeonMap.csにイベントのアイコンを更新する関数を作成します。
クリックで展開
public void UpdateEventIcon(int posX, int posY) //New { if(posOfEvent[questManager.currentFloor -1,posY,posX] == -1) { eventIcons[posX, posY].GetComponent<Image>().color = new Color(1, 1, 1, 0); } else { eventIcons[posX, posY].GetComponent<Image>().sprite = dangionMapSystem.GetComponent<DangionData>().eventIcons[posOfEvent[questManager.currentFloor - 1, posX, posY]]; } }
UpdateEventIcon関数をスイッチで開く扉が開いた後と青いスイッチイベント(OFF)完了後に呼び出します。
クリックで展開
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: //階段を降りるイベント yield return dangeonEvent.IEDownFloorEvent(dangionMap, questManager,stageUIManager,this); break; case 6: //階段を上がるイベント yield return dangeonEvent.IEUpFloorEvent(dangionMap, questManager, stageUIManager,this); break; case 7://7はトラップイベントだが配置された位置に到達した時に実行されるのでここでは何もしない(というかここには処理が来ない) break; case 8: //スイッチで開く扉イベント yield return dangeonEvent.IEUpSwitchDoorEvent(); break; case 9: ////青いスイッチ(OFF)イベント yield return dangeonEvent.IEOFFBlueSwitchEvent(dangionMap,questManager,this); dangionMap.UpdateEventIcon(playerPos.x,playerPos.y); //New break; case 10: ////青いスイッチ(ON)イベント yield return dangeonEvent.IEONBlueSwitchEvent(); break; } if (!shouldActiveActionButton) { shouldActiveActionButton = true; } else if(shouldActiveActionButton) { stageUIManager.actionButton.SetActive(true); } stageUIManager.SetArrowsButton(true); yield return null; }
クリックで展開
public IEnumerator IEOFFBlueSwitchEvent(DangionMap dangionMap, QuestManager questManager, DangionController dangionController) //New { SoundManager.instance.PlaySE(29); DialogTextManager.instance.SetScenarios(new string[] { PlayerManager.instance.pname + "はスイッチを押した"}); yield return new WaitForSeconds(2f); int floor = questManager.currentFloor - 1; int py = dangionController.playerPos.y; int px = dangionController.playerPos.x; dangionMap.posOfEvent[floor, py, px] = 10;//イベントの種類を青スイッチ(ON)にする bool pushAllBlueSwitch = true; for (int j = 0; j < dangionController.dangion_height; j++) { for (int i = 0; i < dangionController.dangion_width; i++) { if (dangionMap.posOfEvent[floor, j, i] == 9)//一つでもOFFの青スイッチがあったらフラグをfalseにする { pushAllBlueSwitch = false; } } } if (pushAllBlueSwitch) //OFFの青スイッチが一つもなければ { for (int j = 0; j < dangionController.dangion_height; j++) { for (int i = 0; i < dangionController.dangion_width; i++) { if (dangionMap.posOfEvent[floor, j, i] == 8)//スイッチで開く扉のイベントを探し出して { dangionMap.posOfEvent[floor, j, i] = 5; //イベントを下り階段に変更する dangionMap.DeleteEventIcon(i,j);//アイコンを削除 SoundManager.instance.PlaySE(30); DialogTextManager.instance.SetScenarios(new string[] { "扉が開いた"}); yield return new WaitForSeconds(2f); dangionMap.UpdateEventIcon(i,j); } } } } }
これで実行すると以下の動画のようになります
次回はワープイベントを作成しようと思います。
【Unity】RPG制作 その21-到達していない部屋を非表示にする
前回の終わりで探索時のトラップを作成すると書きましたが、今回はその前に、到達していないダンジョンの部屋とその部屋に配置されているイベントを非表示にする処理を実装していきます。
はじめに、イベント及び部屋を表示するかどうかのデータを保持する配列をDangeonMap.csに宣言します。
クリックで展開
public int [,,]isViewRoom = new int[4, 5, 5] { //0;見えない 1:見える New { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, } }; public int[,,] isViewEvent = new int[4, 5, 5] { //0;見えない 1:見える New { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, }, { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, } }; public int[] isAlreadyEnterFloor = new int[20] { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //New
isAlreadyEnterFloor配列は、既に訪れたことがある部屋かどうかのFloorごとの状態を保持する配列です。
次に部屋とイベントの表示非表示の初期化処理の関数を作成します。
クリックで展開
public void InitViewEvent(int currentFloor) //New { if(isAlreadyEnterFloor[currentFloor - 1] == 0) { for (int j = 0; j < 5; j++) { for (int i = 0; i < 5; i++) { isViewEvent[currentFloor - 1, j, i] = 0; } } isAlreadyEnterFloor[currentFloor - 1] = 1; //ここでそのフロアに訪れたフラグを立てる。 } } public void InitViewRoom(int currentFloor) //New { if (isAlreadyEnterFloor[currentFloor - 1] == 0) { for (int j = 0; j < 5; j++) { for (int i = 0; i < 5; i++) { isViewRoom[currentFloor - 1, j, i] = 0; } } } isViewRoom[currentFloor - 1, dangionController.playerPos.y, dangionController.playerPos.x] = 1; //プレイヤーの現在位置の部屋のみ表示する }
これらの関数をDangeonMap.csのStart関数と、DangeonEvent.csのIEDownFloorEventコルーチンとIEUpFloorEventコルーチンで呼び出します。
クリックで展開
void Start() { this.gameObject.SetActive(false); dangionController = dangionMapSystem.GetComponent<DangionController>(); //新しく入るフロアの場合は部屋の表示非表示、イベントの初期化処理を行う if(isAlreadyEnterFloor[questManager.currentFloor] == 0) //New { InitViewRoom(questManager.currentFloor); //New InitViewEvent(questManager.currentFloor); //New InitEventNowFloor(questManager.currentFloor); SetEventNowFloorAtRandam(questManager.currentFloor, 3, 5); } SetDangion(questManager.currentFloor); SetEvent(questManager.currentFloor); }
クリックで展開
public IEnumerator IEDownFloorEvent(DangionMap dangionMap,QuestManager questManager,StageUIManager stageUIManager,DangionController dangionController) { stageUIManager.HideButtons(); dangionMap.HideDangeonMapForSearching(); dangionMap.DestroyMapInfo(); questManager.currentFloor++; DialogTextManager.instance.SetScenarios(new string[] { "階段を降りた。\n現在地 B" + questManager.currentFloor}); yield return new WaitForSeconds(2f); dangionController.DeployPlayerPositionAtRandom(); //-----------ここからNew------------------ int floor = questManager.currentFloor - 1; if (dangionMap.isAlreadyEnterFloor[floor] == 0) { //一度も入っていないFloorなら dangionMap.InitEventNowFloor(questManager.currentFloor); dangionMap.SetEventNowFloorAtRandam(questManager.currentFloor, 3, 5); dangionMap.InitViewRoom(questManager.currentFloor); dangionMap.InitViewEvent(questManager.currentFloor); } //-----------Newここまで------------------ dangionMap.SetDangion(questManager.currentFloor); dangionMap.SetEvent(questManager.currentFloor); dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); stageUIManager.UpdateUI(questManager.currentFloor);//New } public IEnumerator IEUpFloorEvent(DangionMap dangionMap, QuestManager questManager, StageUIManager stageUIManager, DangionController dangionController) { stageUIManager.HideButtons(); dangionMap.HideDangeonMapForSearching(); dangionMap.DestroyMapInfo(); questManager.currentFloor--; DialogTextManager.instance.SetScenarios(new string[] { "階段を上がった。\n現在地 B" + questManager.currentFloor}); yield return new WaitForSeconds(2f); dangionController.DeployPlayerPositionAtRandom(); //-----------ここからNew------------------ int floor = questManager.currentFloor - 1; if (dangionMap.isAlreadyEnterFloor[floor] == 0) { //一度も入っていないFloorなら dangionMap.InitEventNowFloor(questManager.currentFloor); dangionMap.SetEventNowFloorAtRandam(questManager.currentFloor, 3, 5); dangionMap.InitViewRoom(questManager.currentFloor); dangionMap.InitViewEvent(questManager.currentFloor); } //-----------Newここまで------------------ dangionMap.SetDangion(questManager.currentFloor); dangionMap.InitEventNowFloor(questManager.currentFloor); //New dangionMap.SetEventNowFloorAtRandam(questManager.currentFloor, 3, 5); //New dangionMap.SetEvent(questManager.currentFloor); dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); stageUIManager.UpdateUI(questManager.currentFloor);//New }
それから、現状プレイヤーが階段を上り下りした時に、プレイヤーの位置がランダムで決定されるようになっているのをやめて、階段を降りたときは次のフロアの上り階段に、階段を登ったときは次のフロアの下り階段に配置されるようにします。DangeonController.csに以下の関数を作成します。
クリックで展開
/// <summary> /// プレイヤーを登り階段に配置する関数 /// </summary> public void PlayerPositionPlaceInUpStairs() //New { for (int j = 0; j < 5; j++) { for (int i = 0; i < 5; i++) { if(dangionMap.posOfEvent[questManager.currentFloor-1,j,i] == 6) { playerPos.x = i; playerPos.y = j; } } } } /// <summary> /// プレイヤーを下り階段に配置する関数 /// </summary> public void PlayerPositionPlaceInDownStairs() //New { for (int j = 0; j < 5; j++) { for (int i = 0; i < 5; i++) { if (dangionMap.posOfEvent[questManager.currentFloor - 1, j, i] == 5) { playerPos.x = i; playerPos.y = j; } } } }
この関数をDangeonEvent.csのIEDownFloorEventコルーチンとIEUpFloorEventコルーチンで呼び出すようにします。
クリックで展開
public IEnumerator IEDownFloorEvent(DangionMap dangionMap,QuestManager questManager,StageUIManager stageUIManager,DangionController dangionController) { stageUIManager.HideButtons(); dangionMap.HideDangeonMapForSearching(); dangionMap.DestroyMapInfo(); questManager.currentFloor++; DialogTextManager.instance.SetScenarios(new string[] { "階段を降りた。\n現在地 B" + questManager.currentFloor}); yield return new WaitForSeconds(2f); dangionController.PlayerPositionPlaceInUpStairs(); //New int floor = questManager.currentFloor - 1; if (dangionMap.isAlreadyEnterFloor[floor] == 0) { //一度も入っていないFloorなら dangionMap.InitEventNowFloor(questManager.currentFloor); dangionMap.SetEventNowFloorAtRandam(questManager.currentFloor, 3, 5); dangionMap.InitViewRoom(questManager.currentFloor); dangionMap.InitViewEvent(questManager.currentFloor); } dangionMap.SetDangion(questManager.currentFloor); dangionMap.SetEvent(questManager.currentFloor); dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); stageUIManager.UpdateUI(questManager.currentFloor); } public IEnumerator IEUpFloorEvent(DangionMap dangionMap, QuestManager questManager, StageUIManager stageUIManager, DangionController dangionController) { stageUIManager.HideButtons(); dangionMap.HideDangeonMapForSearching(); dangionMap.DestroyMapInfo(); questManager.currentFloor--; DialogTextManager.instance.SetScenarios(new string[] { "階段を上がった。\n現在地 B" + questManager.currentFloor}); yield return new WaitForSeconds(2f); dangionController.PlayerPositionPlaceInDownStairs(); //New int floor = questManager.currentFloor - 1; if (dangionMap.isAlreadyEnterFloor[floor] == 0) { //一度も入っていないFloorなら dangionMap.InitEventNowFloor(questManager.currentFloor); dangionMap.SetEventNowFloorAtRandam(questManager.currentFloor, 3, 5); dangionMap.InitViewRoom(questManager.currentFloor); dangionMap.InitViewEvent(questManager.currentFloor); } dangionMap.SetDangion(questManager.currentFloor); dangionMap.InitEventNowFloor(questManager.currentFloor); dangionMap.SetEventNowFloorAtRandam(questManager.currentFloor, 3, 5); dangionMap.SetEvent(questManager.currentFloor); dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); stageUIManager.UpdateUI(questManager.currentFloor); }
あとは、移動ボタンを押した時に、移動先の部屋とイベントを表示するようにします。DangeonController.csに以下の関数を作成します。
クリックで展開
/// <summary> /// プレイヤー位置の部屋を表示状態にする関数 /// </summary> public void ActivePlayerPosRoom() { dangionMap.roomImage[playerPos.y, playerPos.x].SetActive(true); dangionMap.isViewRoom[questManager.currentFloor-1,playerPos.y,playerPos.x] = 1; } /// <summary> /// プレイヤー位置のイベントを表示状態にする関数 /// /// </summary> public void ActivePlayerPosEvent() { if(dangionMap.posOfEvent[questManager.currentFloor-1,playerPos.y,playerPos.x] == -1) { dangionMap.eventIcons[playerPos.y, playerPos.x].SetActive(true); } dangionMap.isViewEvent[questManager.currentFloor - 1, playerPos.y, playerPos.x] = 1; }
これらの関数を、questManagerのOnCompleteMoveRoomに登録します。
以上の処理を追加して実行すると以下の動画のようになります。
これでたどり着いていない部屋とその部屋のイベントを非表示にするようになりました。次回はトラップや扉を開くためのスイッチなどを実装していきます。
【Unity】RPG制作 その20-探索イベントのランダム配置
今回は探索イベントをランダムに配置する処理を実装していきます。
はじめに、今までDangeonMap.csのposOfEventに直接入力していたIDを階段の上り下りのイベント以外全て-1にしておきます。
クリックで展開
public int[,,] structOfDangeon = new int[4,5,5]{ //階層を一つ拡張 { { 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 }, }, { { 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[4,5, 5] { //Idを変更,階層を一つ拡張 { { -1,-1,-1,-1, 5 }, { -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 }, { 5,-1,-1,-1,-1 }, }, { { 5,-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, 5 }, }, };
次に探索イベント初期化する関数と、探索イベントランダムに配置する関数を作成します。
クリックで展開
public void InitEventNowFloor(int currentFloor) { for (int j = 0; j < 5; j++) { for (int i = 0; i < 5; i++) { if(posOfEvent[currentFloor - 1, j, i] != 5 && posOfEvent[currentFloor - 1, j, i] != 6) posOfEvent[currentFloor - 1, j, i] = -1; } } } public void SetEventNowFloorAtRandam(int currentFloor,int minCountOfEvent, int maxCountOfEvent) { int normaOfSetEvent = 0; int countOfSetEvent = 0; normaOfSetEvent = UnityEngine.Random.Range(minCountOfEvent, maxCountOfEvent); while (countOfSetEvent < normaOfSetEvent) { int x = UnityEngine.Random.Range(0,dangionController.dangion_width); int y = UnityEngine.Random.Range(0,dangionController.dangion_height); if (posOfEvent[currentFloor - 1, y, x] == -1 && structOfDangeon[currentFloor - 1, y, x] != -1) { posOfEvent[currentFloor - 1, y, x] = UnityEngine.Random.Range(0, dangionController.NUMBER_OF_EVENT_TYPE);//0~4のID配置 countOfSetEvent++; } } }
作った関数をSetEventをする前に呼び出します。
クリックで展開
void Start() { this.gameObject.SetActive(false); dangionController = dangionMapSystem.GetComponent<DangionController>(); SetDangion(questManager.currentFloor); InitEventNowFloor(questManager.currentFloor);//New SetEventNowFloorAtRandam(questManager.currentFloor,3,5); //New SetEvent(questManager.currentFloor); }
クリックで展開
public IEnumerator IEDownFloorEvent(DangionMap dangionMap,QuestManager questManager,StageUIManager stageUIManager,DangionController dangionController) { stageUIManager.HideButtons(); dangionMap.HideDangeonMapForSearching(); dangionMap.DestroyMapInfo(); questManager.currentFloor++; DialogTextManager.instance.SetScenarios(new string[] { "階段を降りた。\n現在地 B" + questManager.currentFloor}); yield return new WaitForSeconds(2f); dangionController.DeployPlayerPositionAtRandom(); dangionMap.SetDangion(questManager.currentFloor); dangionMap.InitEventNowFloor(questManager.currentFloor); //New dangionMap.SetEventNowFloorAtRandam(questManager.currentFloor, 3, 5); //New dangionMap.SetEvent(questManager.currentFloor); dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); } public IEnumerator IEUpFloorEvent(DangionMap dangionMap, QuestManager questManager, StageUIManager stageUIManager, DangionController dangionController) { stageUIManager.HideButtons(); dangionMap.HideDangeonMapForSearching(); dangionMap.DestroyMapInfo(); questManager.currentFloor--; DialogTextManager.instance.SetScenarios(new string[] { "階段を上がった。\n現在地 B" + questManager.currentFloor}); yield return new WaitForSeconds(2f); dangionController.DeployPlayerPositionAtRandom(); dangionMap.SetDangion(questManager.currentFloor); dangionMap.InitEventNowFloor(questManager.currentFloor); //New dangionMap.SetEventNowFloorAtRandam(questManager.currentFloor, 3, 5); //New dangionMap.SetEvent(questManager.currentFloor); dangionMap.ShowDangeonMapForSearching(); stageUIManager.ShowButtonsForSearching(); }
これでEventIDが0~4の探索イベントが1フロアにつき3~5個生成されるようになりました。
次回はダンジョンの進行を阻むギミックを作っていきたいと思います。
【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コルーチンで呼び出すようにします。
これで上下の階層に移動することができるようになりました。
次回はイベントをランダムで配置できるようにしていきます。