There is such a class

public class Item : MonoBehaviour { [Header("Ссылка на префаб")] public string PrefabReference; // ссылка на префаб [Header("Текст для описания")] public string Description; // текст описания [Header("Миниатюра которая показывается в описание")] public Sprite MiniatureSprite; // миниатюра void OnMouseDown() { GameObject inventoryGM = GameObject.Find("InventoryContent"); Inventory inv = inventoryGM.GetComponent<Inventory> (); inv.AddItem (this); Destroy (gameObject); } } 

and function of adding to array

 public List<Item> inventory; public int arrayLenght = 21; .... void Start() { inventory = new List<Item>(); //инициализируем массив inventoryObject = this.gameObject;//получаем ссылку на объект container = Instantiate(Resources.Load ("Prefabs/Container", typeof(GameObject))) as GameObject;//заносим контейнер } .... public bool AddItem(Item item)// добавление айтема { if (inventory.Count < arrayLenght) { inventory.Add (item); GameObject img = Instantiate (container); img.transform.SetParent (inventoryObject.transform.GetChild (0).transform.GetChild(inventory.IndexOf (item)).transform, false); img.GetComponent<Image> ().sprite = item.MiniatureSprite; img.GetComponent<InvDrag> ().item = item; img.GetComponent<InvDrag> ().inv = this; return true; } else { return false; } } 

And that's what's in the array after adding items, if I remove an object in OnMouseDown, then everything is fine

Array after filling in items


Inventory class

 public class Inventory : MonoBehaviour { public Item[,] inventory; public int arrayLenght = 21; void Start () { inventory = new Item[(arrayLenght/7), 7]; } public void Check() { for (int i=0; i<inventory.GetLength(0); i++) { for (int l = 0; l < inventory.GetLength (1); l++) { Debug.Log (inventory[i,l] + " Y: " + i +" X: " + l); /* if (inventory [i, l].ID != 0) { Debug.Log ("NotNull " + inventory[i,l].ID + " Y: " + i + " X: " + l); } */ } } } /// <summary> /// Добавляет item в конец массива /// </summary> /// <returns>Возвращает верное логическое значение если удалось добавить item в массив</returns> /// <param name="item">Сам item</param> public bool AddItem(Item item) { for (int i = 0; i < inventory.GetLength (0); i++) { for (int l = 0; l < inventory.GetLength (1); l++) { if (inventory[i,l] == null) { Pos2D StartPos = new Pos2D (i, l); if (InspectionCells(item, StartPos)) { Item itAdd = item.Clone (); for (int j = 0; j<item.HeightCell; j++) { for (int k = 0; k<item.WidthCell; k++) { Debug.Log ((j + StartPos.Y) + " " + (k + StartPos.X) + " " + item.ID); inventory [j+StartPos.Y, k+StartPos.X] = itAdd; } } return true; } } } } return false; } /// <summary> /// Проверка ячеек в нужном диапозоне /// </summary> /// <returns>Возвращает верное логическое значение если ячейки пусты</returns> /// <param name="item">Сам item</param> /// <param name="StartPosition">Координаты ячейки с которой будем начинать проверку</param> public bool InspectionCells(Item item, Pos2D StartPosition) { int res = 0; bool flagFor = false; for (int i = 0; !flagFor && i < item.HeightCell; i++) { for (int l = 0; l < item.WidthCell; l++) { if ((i+StartPosition.Y) >= inventory.GetLength(0)) { flagFor = true; break; } else if ((l+StartPosition.X) >= inventory.GetLength(1)) { flagFor = true; break; } else { if (inventory [i + StartPosition.Y, l + StartPosition.X] == null) { res++; } else { flagFor = true; break; } } } } if (res == (item.HeightCell * item.WidthCell)) { return true; } else { return false; } } /// <summary> /// Получение позицию item'a в массиве по йд /// </summary> /// <returns>Возвращает позицию item'a</returns> /// <param name="item">Item для проверки</param> public Pos2D IndexOf(Item item) { Pos2D returnPos = new Pos2D(0,0); for (int i=0; i<inventory.GetLength(0); i++) { for (int l=0; l<inventory.GetLength(1); l++) { if (inventory[i,l].ID == item.ID) { returnPos.Y = i; returnPos.X = l; } } } return returnPos; } } 

Item class

  public class Item : MonoBehaviour { public int Count; public string PrefabReference; public int HeightCell; public int WidthCell; public int ID; public Item Clone() { var item = new Item (); item.Count = this.Count; item.PrefabReference = this.PrefabReference; item.HeightCell = this.HeightCell; item.WidthCell = this.WidthCell; item.ID = this.ID; return item; } void OnMouseDown() { Inventory inv = GameObject.Find ("InventoryContent").GetComponent<Inventory> (); Item item = GetComponent<Item> (); if (inv.AddItem (item)) { Destroy (gameObject); } } 

After adding an item AddItem() , I check for the presence of an item in Check() , and as a result I get such records in the log

Before adding item

 Y: 0 X: 0 Y: 0 X: 1 Y: 0 X: 2 ......... ......... Y: 2 X: 6 

And after adding an item

 null Y: 0 X: 0 Y: 0 X: 1 Y: 0 X: 2 ......... ......... Y: 2 X: 6 
  • inv.AddItem (this); It seems to add not this object, but this component. Most likely you need to write inv.AddItem (gameObject); - Alexey Shimansky

1 answer 1

You delete the game object on which the script hangs. This:

 inv.AddItem (this); Destroy (gameObject); 

- this is the same as this:

 inv.AddItem (this); Destroy (this.gameObject); 

- this.gameObject is a link to the GameObject instance that owns the executable script. Here you need to understand that you are passing to the array is not a component, but a link to it. And Destroy (gameObject) deletes exactly the game object - along with the component pointed to by the link. Therefore, in the Inventory array there is a reference to a non-existent instance of the Item component. So the result is quite logical :)

Here it is necessary to understand the difference between significant and reference types.


Alternatively, you can describe the cloning method, i.e. transfer of values ​​from one instance to another. For example:

 public Item Clone() { var item = new Item(); item.PrefabReference = this.PrefabReference; item.Description = this.Description; item.MiniatureSprite = this.MiniatureSprite; return item; } 

Then you will need to make minimal changes to your code:

 public bool AddItem(Item item)// добавление айтема { if (inventory.Count < arrayLenght) { inventory.Add (item.Clone()); 

Naturally, you need to pass all the necessary values, including the values ​​of the fields / properties that you could not give in your example.

  • I updated the record, added full classes to avoid unnecessary questions, now the problem has become that the element in the array is displayed after the addition as null , but at the same time I can easily get its values ​​like йд итд.. - Andrei
  • The problem was solved simply instead of `var item = new Item ();` I registered var item = Resources.Load<Item> (this.PrefabReference); thereby unloading the object from prefabs - Andrei Nov.