問題
Unityに関する質問です。
アイテム管理クラスを動かすためにアイテムを取得した時に
以下の実行時エラーが発生してしまい、改善の仕方が
分からないので質問します。
発生している問題・エラーメッセージ
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <6073cf49ed704e958b8a66d540dea948>:0) Platformer.Mechanics.SimpleInventory.Update () (at Assets/Scripts/Mechanics/SimpleInventory.cs:45)
該当のソースコード
C#
1using System.Collections.Generic; 2using UnityEngine; 3using UnityEngine.UI; 4using Platformer.Mechanics; 5 6namespace Platformer.Mechanics 7{ 8 public class SimpleInventory : MonoBehaviour 9 { 10 11 [SerializeField] 12 GameObject iconPrefab = null; 13 [SerializeField] 14 Transform iconParent = null; 15 [SerializeField] 16 InventoryItem[] items = null; 17 18 // アイテムを持ってるかどうかのフラグ 19 bool[] itemFlags = new bool[10000]; 20 21 // アイテムのアイコンを管理するためのディクショナリ 22 Dictionary<int, GameObject> icons = new Dictionary<int, GameObject>(); 23 24 //アイテムを名前で管理するリスト 25 List<string> itemManager = new List<string>(); 26 27 CircleController cir; 28 public static bool itemAddEvent = false; 29 public static bool itemUseEvent = false; 30 31 void Start() 32 { 33 for (int i = 0; i < items.Length; i++) 34 { 35 itemFlags[i] = false; 36 } 37 //itemFlags = new bool[items.Length]; 38 cir = GameObject.FindWithTag("Circle").GetComponent<CircleController>(); 39 } 40 41 void Update() 42 { 43 if (itemAddEvent || itemUseEvent) 44 { 45 Debug.Log("アイテムを取得:"+itemManager[0]); //45行目 46 cir.setItem(itemManager); 47 } 48 if (CircleController.endSet) 49 { 50 itemAddEvent = false; 51 itemUseEvent = false; 52 } 53 } 54 55 /// <summary> 56 /// アイテムを持ってるかどうかを確認するメソッド 57 /// </summary> 58 /// <param name="itemName"></param> 59 /// <returns></returns> 60 public bool GetItemFlag(string itemName) 61 { 62 int index = GetItemIndexFromName(itemName); 63 64 return itemFlags[index]; 65 } 66 67 public void SetItem(string itemName, bool isOn) 68 { 69 int index = GetItemIndexFromName(itemName); 70 71 if (!itemFlags[index] && isOn) 72 { 73 // アイテム未所持の状態で新しく入手したとき 74 // 新しいアイコンを生成し、インベントリのキャンバスの子に設定 75 GameObject icon = Instantiate(iconPrefab, iconParent); 76 icon.AddComponent<Image>(); 77 78 // アイコンの画像を設定 79 icon.GetComponent<Image>().sprite = items[index].itemSprite; 80 81 icons.Add(index, icon); 82 83 itemManager.Add(items[index].itemName); 84 itemAddEvent = true; 85 } 86 else if (itemFlags[index] && !isOn) 87 { 88 // アイテム所持中に削除するとき 89 GameObject icon = icons[index]; 90 91 // アイテムのアイコンを削除 92 Destroy(icon); 93 94 // アイコンのディクショナリから対象のアイテムを削除 95 icons.Remove(index); 96 97 itemManager.RemoveAt(index); 98 itemUseEvent = true; 99 } 100 101 itemFlags[index] = isOn; 102 } 103 104 /// <summary> 105 /// items内に指定のアイテム名があるかを確認する 106 /// </summary> 107 /// <param name="itemName"></param> 108 /// <returns></returns> 109 int GetItemIndexFromName(string itemName) 110 { 111 for (int i = 0; i < items.Length; i++) 112 { 113 if (items[i].itemName == itemName) 114 { 115 return i; 116 } 117 } 118 119 Debug.LogWarning("指定されたアイテム名が間違っているか存在しません"); 120 return 0; 121 } 122 123 } 124 125 /// <summary> 126 /// インベントリに登録できるアイテムを定義するためのクラス 127 /// </summary> 128 [System.Serializable] 129 public class InventoryItem 130 { 131 public string itemName = ""; 132 public Sprite itemSprite = null; 133 } 134}
C#
1 /// <summary> 2 /// アイテム取得時や使用時に呼び出される 3 /// </summary> 4 /// <param name="items"></param> 5 public void setItem(List<string> items) 6 { 7 if (SimpleInventory.itemAddEvent) 8 { 9 for (int i = 0; i < items.Count; i++) 10 { 11 useItems.Add(items[i]); 12 } 13 } 14 if (SimpleInventory.itemUseEvent) 15 { 16 useItems.Clear(); 17 for (int i = 0; i < items.Count; i++) 18 { 19 useItems.Add(items[i]); 20 } 21 if (items.Count == 0) 22 getItem = false; 23 } 24 endSet = true; 25 Debug.Log("アイテムを取得:"+items.Count); //なんでCountが0? 26 if (!(items.Count == 0)) 27 { 28 getItem = true; 29 } 30 items.Clear(); 31 }
詳細内容
ゲーム画面内でアイテムを取得した時に
外部クラスからSetItemメソッドが呼び出されます。
アイテム取得時はif文の上を通るので、else if側は関係ない構文です。
SetItemに渡される引数 ("Return",true)
下の方にあるInventoryItemクラスに定義されているのは以下です。
要素0
itemName → Return
itemSprite → アイテムのアイコン画像
itemAddEventがtrueの時にUpdateメソッドで
外部のメソッドに取得したアイテムの名前を渡しますが、
実行時エラーの内容だとitemManagerリスト内に
正常にアイテム名が入っていないという認識でいいでしょうか?
Addでアイテム名を入れていると思っていますが・・・。
補足情報(FW/ツールのバージョンなど)
Unity 2021.3.2f1 Personal