Get 25% off your next order from the Unity Asset Store: YW86GYBU8S.
Forum begins after the advertisement:
[Part 10] Weapon upgrading ArgumentOutOfRangeException issue
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › [Part 10] Weapon upgrading ArgumentOutOfRangeException issue
- This topic has 3 replies, 3 voices, and was last updated 1 week ago by
Josiah Loh.
-
AuthorPosts
-
October 20, 2025 at 3:46 pm #18953::
I have noticed that after adding in
if(!chosenWeaponUpgrade.weaponData.NextLevelPrefab) {break;}there is errors like the description and name of the upgrade not showing, the wrong icon etc. whenever this happens, i get this error in my console log, “ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.” anyone have any idea on how to fix this?
October 20, 2025 at 3:49 pm #18954::Hey Tanish Arun! It sounds like you’re running into an issue with accessing elements in a collection, likely an array or list, after adding that condition. The
ArgumentOutOfRangeExceptiontypically occurs when you try to access an index that doesn’t exist in the collection.Here are a few steps you can take to troubleshoot and potentially fix the issue:
-
Check the Collection Size: Before accessing any element in your collection (like an array or list), make sure to check that the index you’re trying to access is within the valid range. For example:
if (index >= 0 && index < yourCollection.Count) { // Access yourCollection[index] } else { // Handle the error or set a default value } -
Debug the Condition: Since you added the condition
if(!chosenWeaponUpgrade.weaponData.NextLevelPrefab), ensure that this condition is not causing your code to skip necessary initialization or assignment of values. You might want to log or debug the state ofchosenWeaponUpgradeand its properties before this check. -
Review the Logic Flow: Make sure that the logic flow of your code is still valid after adding the new condition. If the upgrade's description, name, or icon relies on
NextLevelPrefab, and that prefab is not set, you might need to provide fallback values or handle that case explicitly. -
Check for Null References: If
NextLevelPrefabis null, ensure that you have appropriate checks in place to handle that scenario. If your code assumes that certain properties are always set, you might need to add additional checks or default values. -
Look at Related Code: If the error persists, look at the code that runs after the condition you added. There might be other parts of your code that assume certain conditions are met (like the existence of an upgrade) that are no longer valid.
If you can share a bit more of the relevant code, I might be able to provide more specific guidance! Good luck!
October 20, 2025 at 4:01 pm #18955October 20, 2025 at 4:02 pm #18956::Sorry here,
using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI; public class InventoryManager : MonoBehaviour { public List<WeaponController> weaponSlots = new List<WeaponController>(6); public int[] weaponLevels = new int[6]; public List<Image> weaponUISlots = new List<Image>(6); public List<PassiveItem> passiveItemSlots = new List<PassiveItem>(6); public int[] passiveItemLevels = new int[6]; public List<Image> passiveItemUISlots = new List<Image>(6); [System.Serializable] public class WeaponUpgrade { public int weaponUpgradeIndex; public GameObject initialWeapon; public WeaponScriptableObject weaponData; } [System.Serializable] public class PassiveItemUpgrade { public int passiveItemUpgradeIndex; public GameObject initialPassiveItem; public PassiveItemScriptableObject passiveItemData; } [System.Serializable] public class UpgradeUI { public TMP_Text upgradeNameDisplay; public TMP_Text upgradeDescriptionDisplay; public Image upgradeIcon; public Button upgradeButton; } public List<WeaponUpgrade> weaponUpgradeOptions = new List<WeaponUpgrade>(); //List of upgrade options for weapons public List<PassiveItemUpgrade> passiveItemUpgradeOptions = new List<PassiveItemUpgrade>(); //List of upgrade options for passive items public List<UpgradeUI> upgradeUIOptions = new List<UpgradeUI>(); //List of ui for upgrade options present in the scene PlayerStats player; void Start() { player = GetComponent<PlayerStats>(); } public void AddWeapon(int slotIndex, WeaponController weapon) //Add a weapon to a specific slot { weaponSlots[slotIndex] = weapon; weaponLevels[slotIndex] = weapon.weaponData.Level; weaponUISlots[slotIndex].enabled = true; //Enable the image component weaponUISlots[slotIndex].sprite = weapon.weaponData.Icon; if (GameManager.instance != null && GameManager.instance.choosingUpgrade) { GameManager.instance.EndLevelUp(); } } public void AddPassiveItem(int slotIndex, PassiveItem passiveItem) //Add a passive item to a specific slot { passiveItemSlots[slotIndex] = passiveItem; passiveItemLevels[slotIndex] = passiveItem.passiveItemData.Level; passiveItemUISlots[slotIndex].enabled = true; //Enable the image component passiveItemUISlots[slotIndex].sprite = passiveItem.passiveItemData.Icon; if (GameManager.instance != null && GameManager.instance.choosingUpgrade) { GameManager.instance.EndLevelUp(); } } public void LevelUpWeapon(int slotIndex, int upgradeIndex) { if (weaponSlots.Count > slotIndex) { WeaponController weapon = weaponSlots[slotIndex]; if(!weapon.weaponData.NextLevelPrefab) //Checks if there is a next level { Debug.LogError("NO NEXT LEVEL FOR " + weapon.name); return; } GameObject upgradedWeapon = Instantiate(weapon.weaponData.NextLevelPrefab, transform.position, Quaternion.identity); upgradedWeapon.transform.SetParent(transform); //Set the weapon to be a child of the player AddWeapon(slotIndex, upgradedWeapon.GetComponent<WeaponController>()); Destroy(weapon.gameObject); weaponLevels[slotIndex] = upgradedWeapon.GetComponent<WeaponController>().weaponData.Level; //To make sure we have the correct weapon level weaponUpgradeOptions[upgradeIndex].weaponData = upgradedWeapon.GetComponent<WeaponController>().weaponData; } if (GameManager.instance != null && GameManager.instance.choosingUpgrade) { GameManager.instance.EndLevelUp(); } } public void LevelUpPassiveItem(int slotIndex, int upgradeIndex) { if (passiveItemSlots.Count > slotIndex) { PassiveItem passiveItem = passiveItemSlots[slotIndex]; if (!passiveItem.passiveItemData.NextLevelPrefab) //Checks if there is a next level { Debug.LogError("NO NEXT LEVEL FOR " + passiveItem.name); return; } GameObject upgradedPassiveItem = Instantiate(passiveItem.passiveItemData.NextLevelPrefab, transform.position, Quaternion.identity); upgradedPassiveItem.transform.SetParent(transform); //Set the passive item to be a child of the player AddPassiveItem(slotIndex, upgradedPassiveItem.GetComponent<PassiveItem>()); Destroy(passiveItem.gameObject); passiveItemLevels[slotIndex] = upgradedPassiveItem.GetComponent<PassiveItem>().passiveItemData.Level; //To make sure we have the correct passive item level passiveItemUpgradeOptions[upgradeIndex].passiveItemData = upgradedPassiveItem.GetComponent<PassiveItem>().passiveItemData; } if (GameManager.instance != null && GameManager.instance.choosingUpgrade) { GameManager.instance.EndLevelUp(); } } void ApplyUpgradeOptions() { foreach (var upgradeOption in upgradeUIOptions) { int upgradeType = Random.Range(1, 3); //Choose between weapon and passive items if (upgradeType == 1) { WeaponUpgrade chosenWeaponUpgrade = weaponUpgradeOptions[Random.Range(0, weaponUpgradeOptions.Count)]; if (chosenWeaponUpgrade != null) { bool newWeapon = false; for (int i = 0; i < weaponSlots.Count; i++) { if (weaponSlots[i] != null && weaponSlots[i].weaponData == chosenWeaponUpgrade.weaponData) { newWeapon = false; if (!newWeapon) { if(!chosenWeaponUpgrade.weaponData.NextLevelPrefab) { break; } upgradeOption.upgradeButton.onClick.AddListener(() => LevelUpWeapon(i, chosenWeaponUpgrade.weaponUpgradeIndex)); //Apply button functionality //Set the description and description to be that of the next level upgradeOption.upgradeDescriptionDisplay.text = chosenWeaponUpgrade.weaponData.NextLevelPrefab.GetComponent<WeaponController>().weaponData.Description; upgradeOption.upgradeNameDisplay.text = chosenWeaponUpgrade.weaponData.NextLevelPrefab.GetComponent<WeaponController>().weaponData.Name; } break; } else { newWeapon = true; } } if (newWeapon) //Spawn a new weapon { upgradeOption.upgradeButton.onClick.AddListener(() => player.SpawnWeapon(chosenWeaponUpgrade.initialWeapon)); //Apply button functionality upgradeOption.upgradeDescriptionDisplay.text = chosenWeaponUpgrade.weaponData.Description; //Apply initial description upgradeOption.upgradeNameDisplay.text = chosenWeaponUpgrade.weaponData.Name; //Apply initial name } upgradeOption.upgradeIcon.sprite = chosenWeaponUpgrade.weaponData.Icon; } } else if (upgradeType == 2) { PassiveItemUpgrade chosenPassiveItemUpgrade = passiveItemUpgradeOptions[Random.Range(0, passiveItemUpgradeOptions.Count)]; if (chosenPassiveItemUpgrade != null) { bool newPassiveItem = false; for (int i = 0; i < passiveItemSlots.Count; i++) { if (passiveItemSlots[i] != null && passiveItemSlots[i].passiveItemData == chosenPassiveItemUpgrade.passiveItemData) { newPassiveItem = false; if (!newPassiveItem) { if (!chosenPassiveItemUpgrade.passiveItemData.NextLevelPrefab) { break; } upgradeOption.upgradeButton.onClick.AddListener(() => LevelUpPassiveItem(i, chosenPassiveItemUpgrade.passiveItemUpgradeIndex)); //Apply button functionality //Set the description and description to be that of the next level upgradeOption.upgradeDescriptionDisplay.text = chosenPassiveItemUpgrade.passiveItemData.NextLevelPrefab.GetComponent<PassiveItem>().passiveItemData.Description; upgradeOption.upgradeNameDisplay.text = chosenPassiveItemUpgrade.passiveItemData.NextLevelPrefab.GetComponent<PassiveItem>().passiveItemData.Name; } break; } else { newPassiveItem = true; } } if (newPassiveItem) //Spawn a new passive item { upgradeOption.upgradeButton.onClick.AddListener(() => player.SpawnPassiveItem(chosenPassiveItemUpgrade.initialPassiveItem)); //Apply button functionality upgradeOption.upgradeDescriptionDisplay.text = chosenPassiveItemUpgrade.passiveItemData.Description; //Apply initial description upgradeOption.upgradeNameDisplay.text = chosenPassiveItemUpgrade.passiveItemData.Name; //Apply initial name } upgradeOption.upgradeIcon.sprite = chosenPassiveItemUpgrade.passiveItemData.Icon; } } } } void RemoveUpgradeOptions() { foreach (var upgradeOption in upgradeUIOptions) { upgradeOption.upgradeButton.onClick.RemoveAllListeners(); } } public void RemoveAndApplyUpgrades() { RemoveUpgradeOptions(); ApplyUpgradeOptions(); } }October 20, 2025 at 4:10 pm #18957::The code you’ve provided looks like a complete implementation of an InventoryManager for a Vampire Survivors-like game. It handles weapon and passive item upgrades, UI interactions, and upgrade selection. The code seems well-structured and follows the reference implementation closely, with some additional features like tracking upgrade indices and more detailed upgrade logic.
Would you like me to highlight any specific aspects of the code or do you have a specific question about its implementation?
October 20, 2025 at 4:11 pm #18958::I am fr about to give up can lie, i been at this stuff for over 2 hours, im too tired for this
October 22, 2025 at 9:26 am #18964::Hi Tanish, the error is caused because the of how the upgrades are assigned to the upgrade UI as I had mentioned in the email. The
chosenWeaponUpgradeandchosenPassiveItemUpgradehave the same behaviour that when an upgrade is randomly chosen to be assigned to a upgrade UI slot, that upgrade will be removed from its respective list. Therefore, if the number of UI slots exceed the number of upgrades or that the list is empty, the UI assigning code will be randomly picking upgrades from an empty list. This causes the random picking function to look likeRandom.Range(0, 0), causing theArgumentOutOfRangeExceptionerror.The solution would then be to add a checker to check if the lists are empty like this:
// For weapon upgrades (upgradeType == 1) if (availableWeaponUpgrades.Count == 0) continue; WeaponUpgrade chosenWeaponUpgrade = availableWeaponUpgrades[Random.Range(0, availableWeaponUpgrades.Count)];// For passive item upgrades (upgradeType == 2) if (availablePassiveItemUpgrades.Count == 0) continue; PassiveItemUpgrade chosenPassiveItemUpgrade = availablePassiveItemUpgrades[Random.Range(0, availablePassiveItemUpgrades.Count)];If the lists are empty, the function will be skipped, making an empty slot.
-
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below:
Get 25% off your next order from the Unity Asset Store: YW86GYBU8S.