Search Unity

constructor is not working c# unity as expected

Discussion in 'Scripting' started by Acazied, Jul 22, 2019.

  1. Acazied

    Acazied

    Joined:
    Mar 2, 2016
    Posts:
    23
    i have an object of ItemInInventory with two constructors . One to set the item values and the other one to remove them .
    Code (CSharp):
    1. public class ItemInInventory : MonoBehaviour
    2. {
    3.     public int id ;
    4.     public new string name;
    5.     public string description;
    6.     public string type;
    7.     public Sprite icon;
    8.     public GameObject itemObj;
    9.     public bool stackable;
    10.     public int IndexInInventory ;
    11.      private int totalQuantity;
    12.     void Start()
    13.     {
    14.         IndexInInventory = transform.GetSiblingIndex();
    15.     }
    16.  
    17.    
    18.  
    19.     public int TotalQuantity {
    20.         get
    21.         {
    22.             return totalQuantity;
    23.         }
    24.         set
    25.         {
    26.             if (stackable)  totalQuantity= value;
    27.         }
    28.     }
    29.     public void updateSlotUI()
    30.     {
    31.         print(transform);
    32.        // this.transform.GetChild(0).GetChild(0).GetComponent<Image>().sprite = this.icon;
    33.     }
    34.     public ItemInInventory(int id, string name, string description, string type,Sprite icon, GameObject itemObj, bool stackable , int totalQuantity, int IndexInInventory)
    35.     {
    36.        
    37.         this.id = id;
    38.         this.name = name;
    39.         this.description = description;
    40.         this.type = type;
    41.         this.icon = icon;
    42.         this.itemObj = itemObj;
    43.         this.stackable = stackable;
    44.         this.totalQuantity = totalQuantity;
    45.         this.IndexInInventory = IndexInInventory;
    46.     }
    47.     public ItemInInventory()
    48.     {
    49.         this.id = -1;
    50.         this.name = null;
    51.         this.description = null;
    52.         this.type = null;
    53.         this.icon = null;
    54.         this.itemObj = null;
    55.         this.totalQuantity = 0;
    56.        this.IndexInInventory = -1;
    57.     }
    58.     //public static bool operator ==(ItemInInventory a, ItemInInventory b) { return a.Equals(b); }
    59.     //public static bool operator !=(ItemInInventory a, ItemInInventory b) { return !a.Equals(b); }
    60.  
    61. }

    And in my Inventory Script i have a function AddItem which adds a specific item with that the constructor with parameters as shown in the picture

    but unfortunatly itemSlots stays null and when i check itemSlot in the inventoryUI its null too ...


    However if i do it like that which is very Ugly it works but i prefer to use Constructors


    can anyone help me ?
     
  2. Acazied

    Acazied

    Joined:
    Mar 2, 2016
    Posts:
    23
    sorry couldnt upload images due to spam filter ...
     
  3. Acazied

    Acazied

    Joined:
    Mar 2, 2016
    Posts:
    23
    images related to the thread
     

    Attached Files:

  4. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    772
    (Un?)fortunately,
    MonoBehaviors
    cannot be instantiated using the
    new
    keyword; you have to use Unity's
    Instantiate()
    or
    AddComponent()
    methods, meaning constructors cannot be used.

    Though, looking at your script here, it seems the only reason it is inheriting
    MonoBehaviour
    is to assign the item's index in the inventory from the
    Start()
    method. Instead, you can assign this value for each
    ItemInInventory
    from your
    Inventory
    script, removing the need of
    ItemInInventory
    inheriting
    MonoBehaviour
    , and allowing you to use constructors as usual.

    In the screenshot of your
    Inventory
    script, it looks like you're already doing this as well, so just remove the
    Start()
    method and do not inherit from
    MonoBehaviour
    in your
    ItemInInventory
    script.
     
    Last edited: Jul 22, 2019
    SparrowsNest and Ryiah like this.
  5. Acazied

    Acazied

    Joined:
    Mar 2, 2016
    Posts:
    23
    i understand now .. so it was a problem with monobehaviors. SO how can i Instatiate() or AddComponent() ? i mean i have an empty inventorySlot with null values and id = -1 if i want to add item and since i cant use a constructor what can i do instead ?
    and the script is inheriting from MonoBehaviors not because im using Start() but because the script is attached to a Ui Element . If im doing something wrong or something that can be re done im listening :)
     
  6. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    772
    I would try to avoid this; you should separate your game logic from your UI as much as possible, otherwise it becomes a pain to manage and can easily break when making changes.

    Instead, you can have your UI elements read and display copies of the information for each
    ItemInInventory
    .
    Event systems are one way you can achieve this. Have your
    Inventory
    script invoke an event whenever a change occurs to the items inside of it, then any other scripts that need to care about this change (like your UI) can listen for this event and perform an action when it's invoked.

    Rough example:
    Code (CSharp):
    1. //System namespace required for Action events.
    2. using System;
    3.  
    4. public class Inventory : MonoBehavior {
    5.    //The list of items in the inventory.
    6.    private List<ItemInInventory> items;
    7.  
    8.    //Whenever the inventory changes, this event will be invoked and we will
    9.    //pass in the updated list of items the inventory now currently has.
    10.    public event Action<List<ItemInInventory>> OnInventoryChanged;
    11.  
    12.    void Awake() {
    13.       items = new List<ItemInInventory>();
    14.    }
    15.  
    16.    public void AddItem(ItemInInventory newItem) {
    17.       items.Add(newItem);
    18.  
    19.       //Invoke our event when adding a new inventory item.
    20.       //The same should be done when updating/deleting items.
    21.       OnInventoryChanged?.Invoke(items);
    22.    }
    23.  
    24.    //Imagine UpdateItem and DeleteItem methods...
    Code (CSharp):
    1. public class InventoryUI : MonoBehavior {
    2.    //The inventory reference whose items we want to display.
    3.    public Inventory inventory;
    4.  
    5.    void OnEnable() {
    6.       //Here, we assign the inventory's event to a method that will re-display all its items every time the inventory changes.
    7.       inventory.OnInventoryChanged += RefreshUI;
    8.    }
    9.  
    10.    void OnDisable() {
    11.       //Here, we unassign the inventory's event when this script is disabled or destroyed.
    12.       //To prevent memory leaks, all event assignments must have an unassignment as well.
    13.       inventory.OnInventoryChanged -= RefreshUI;
    14.    }
    15.  
    16.    private void RefreshUI(List<ItemInInventory> items) {
    17.       foreach(ItemInInventory item in items) {
    18.          //Read the data from each inventory item and display it on the UI.
    19.       }
    20.    }
    Something like this should allow you to remove the need to inherent
    MonoBehavior
    in your
    ItemInInventory
    script.
     
    Last edited: Jul 22, 2019
    Acazied and Lysander like this.
  7. Acazied

    Acazied

    Joined:
    Mar 2, 2016
    Posts:
    23
    Thank you very much for your answer i will take a look at this approach ( im not very familiar with unity Events and i will take it into consideration )