Search Unity

Resolved Strange custom class issue

Discussion in 'Scripting' started by Limofeus, Jun 30, 2020.

  1. Limofeus

    Limofeus

    Joined:
    Feb 12, 2019
    Posts:
    33
    Hello, i am trying to create inventory and i made custom class for items in it
    Code (CSharp):
    1.  
    2. [System.Serializable]
    3. public class Item
    4. {
    5.     public int Index;
    6.     public int Id;
    7.     public string Name;
    8.     public string Description;
    9.     public string SpriteName;
    10.     public string PrefabName;
    11.     public string CustomScript;
    12. }
    there is a bunch of parameters as you can see, but when i try to create item slots with different values it all comes static and all slots have the same parameters

    I dont know what is causing this issue, will appreciate any help
    there is Inventory Manager script, do not pay attention to Loadout stuff, its just for testing
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class InventoryManager : MonoBehaviour
    6. {
    7.     public bool Opened;
    8.     public static GameObject InventoryManagerLink;
    9.     public GameObject SlotPrefab;
    10.     public GameObject LoadoutSlotPrefab;
    11.     public GameObject Inventory;
    12.     public GameObject LoadoutList;
    13.     public Animator InventoryTabAnimator;
    14.     public Animator CharacterTabAnimator;
    15.     public static List<Item> Items = new List<Item>();
    16.     public static List<Loadout> Loadouts = new List<Loadout>();
    17.     public int SelectedLoadout = 0;
    18.  
    19.     private void Start()
    20.     {
    21.         InventoryManagerLink = this.gameObject;
    22.         UpdateInventory();
    23.         OpenCloseInventory();
    24.     }
    25.  
    26.     public void UpdateInventory()
    27.     {
    28.         foreach(Transform child in Inventory.transform)
    29.         {
    30.             Destroy(child.gameObject);
    31.         }
    32.         for(int i = 0; i < Items.Count; i++)
    33.         {
    34.             Debug.Log(i);
    35.             Items[i].Index = i;
    36.             GameObject InstantiatedSlot = Instantiate(SlotPrefab, Inventory.transform);
    37.             InstantiatedSlot.GetComponent<ItemSlot>().UpdateParameters(Items[i]);
    38.         }
    39.     }
    40.     public void AddItem(Item item)
    41.     {
    42.         Items.Add(item);
    43.         UpdateInventory();
    44.     }
    45.     public void UpdateLoadoutList()
    46.     {
    47.         foreach(Transform child in LoadoutList.transform)
    48.         {
    49.             Destroy(child.gameObject);
    50.         }
    51.         for(int i = 0; i < Loadouts.Count; i++)
    52.         {
    53.             Loadouts[i].Index = i;
    54.             GameObject InstantiatedLoadoutSlot = Instantiate(LoadoutSlotPrefab, LoadoutList.transform);
    55.  
    56.         }
    57.     }
    58.     public void AddLoadoutSlot(Loadout loadout)
    59.     {
    60.         Loadouts.Add(loadout);
    61.     }
    62.     public void OpenCloseInventory()
    63.     {
    64.         InventoryTabAnimator.SetBool("Opened", Opened);
    65.         CharacterTabAnimator.SetBool("Opened", Opened);
    66.         Cursor.visible = Opened;
    67.         if (!Opened)
    68.             Cursor.lockState = CursorLockMode.Locked;
    69.         else
    70.             Cursor.lockState = CursorLockMode.None;
    71.     }
    72.     private void Update()
    73.     {
    74.         if (Input.GetKeyDown(KeyCode.Tab))
    75.         {
    76.             Opened = !Opened;
    77.             OpenCloseInventory();
    78.         }
    79.         if (Input.GetAxis("Mouse ScrollWheel") > 0f) // forward
    80.         {
    81.             Debug.Log(SelectedLoadout);
    82.             if (SelectedLoadout - 1 >= 0)
    83.                 SelectedLoadout--;
    84.         }
    85.         else if (Input.GetAxis("Mouse ScrollWheel") < 0f) // backwards
    86.         {
    87.             Debug.Log(SelectedLoadout);
    88.             if (SelectedLoadout + 1 < Loadouts.Count)
    89.                 SelectedLoadout++;
    90.         }
    91.     }
    92. }
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    You haven't shown where .AddItem gets called, which is almost certainly where the problem is.

    If you were to do this:
    Code (csharp):
    1. Item x = new Item();
    2. for (int i=0;i<9;i++) {
    3. someInventoryManager.AddItem(x);
    4. }
    Then you would get exactly this result: 9 inventory items added, but in memory they're all referring to the same item, which is what x still refers to. I'm assuming the code you actually have that calls AddItem is basically this, except probably more roundabout and obfuscated.

    If you'd like to make your inventory system durable to being called this way, then make AddItem create a copy of the parameter it's given before you add it to your list. The downside is that whatever is calling AddItem will no longer be able to access that object to see if anything's changing about it.
     
  3. Limofeus

    Limofeus

    Joined:
    Feb 12, 2019
    Posts:
    33
    THANKS! It solved my problem.
    AddItem was called from that script where it creates new item only once in start function
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Pikupitem : MonoBehaviour
    6. {
    7.     public InventoryManager InventoryManager;
    8.     public string ItemName;
    9.     public string Description;
    10.     public string PrefabName;
    11.     Item item = new Item();
    12.     private void Start()
    13.     {
    14.         item.Name = ItemName;
    15.         item.Description = Description;
    16.         item.PrefabName = PrefabName;
    17.     }
    18.     private void Update()
    19.     {
    20.         if (Input.GetKeyDown(KeyCode.E))
    21.         {
    22.             InventoryManager.AddItem(item);
    23.         }
    24.         if (Input.GetKeyDown(KeyCode.Q))
    25.         {
    26.             InventoryManager.UpdateInventory();
    27.         }
    28.     }
    29. }
    I changet it so new item creates each time you press key and it solved the issue
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Pikupitem : MonoBehaviour
    6. {
    7.     public InventoryManager InventoryManager;
    8.     public string ItemName;
    9.     public string Description;
    10.     public string PrefabName;
    11.     private void Update()
    12.     {
    13.         if (Input.GetKeyDown(KeyCode.E))
    14.         {
    15.             Item item = new Item();
    16.             item.Name = ItemName;
    17.             item.Description = Description;
    18.             item.PrefabName = PrefabName;
    19.             InventoryManager.AddItem(item);
    20.         }
    21.         if (Input.GetKeyDown(KeyCode.Q))
    22.         {
    23.             InventoryManager.UpdateInventory();
    24.         }
    25.     }
    26. }
    Really thanks a lot!
     
    Joe-Censored and PraetorBlue like this.