Unity does not enter a permanent variable in the array

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 the function of adding to the 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 here's what's in the array after adding aitems, if I remove the object deletion in OnMouseDown, then everything is fine

Array after filling itemes


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 the element AddItem(), I check for the presence of the element in Check(), and as a result, I get the following entries in the log

Before adding the {[9] element]}

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

And after adding the {[9] element]}

null Y: 0 X: 0
Y: 0 X: 1
Y: 0 X: 2
.........
.........
Y: 2 X: 6
Author: Андрей, 2016-11-25

1 answers

You delete the game object that the script is hanging on. This:

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

-- this is the same as this:

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

-- this.gameObject - this is a reference to the instance GameObject that the script is running belongs to. Here you need to understand that you are not passing a component to the array, but a reference to it. And Destroy (gameObject) deletes exactly the game object-along with the component that the reference points to. Therefore, the Inventory array contains a reference to a non-existent instance of the Item component. So that the result is quite natural :)

Here you need to understand the difference between meaningful and reference types.


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

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());

Of course, you need to pass all the necessary values, including the values of fields/properties that you might not have give in your example.

 0
Author: eastwing, 2016-11-29 00:06:42