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

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #18953
    Tanish Arun
    Level 10
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    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?

    #18954
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    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 ArgumentOutOfRangeException typically 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:

    1. 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
      }
    2. 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 of chosenWeaponUpgrade and its properties before this check.

    3. 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.

    4. Check for Null References: If NextLevelPrefab is 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.

    5. 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!

    #18955
    Tanish Arun
    Level 10
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    heres my code

    #18956
    Tanish Arun
    Level 10
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    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();
        }
    }
    #18957
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    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?

    #18958
    Tanish Arun
    Level 10
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    I am fr about to give up can lie, i been at this stuff for over 2 hours, im too tired for this

    #18964
    Josiah Loh
    Level 2
    Moderator
    Helpful?
    Up
    0
    ::

    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 chosenWeaponUpgrade and chosenPassiveItemUpgrade have 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 like Random.Range(0, 0), causing the ArgumentOutOfRangeException error.

    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.

Viewing 7 posts - 1 through 7 (of 7 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: