Fps drops to 30 each time an item is added

I’m using the gamedevtv rpg inventory and the game I’m trying to create has a feature that adds an item every 2-5 secs and my game has 50 inventory slots. Game looks glitchy since fps drops to 30 each time an item is added. I’m pretty sure this is because of the Redraw() function. is there a way to optimize this? please help, my game is almost done :frowning:

I also tried to cut the inventory slots to 20, same issue.

tried replicating the issue using the inventory tutorial. (a spike each time an item is added)

and this is from my game

The issue has to do with deleting and re-instancing the inventory slots every time InventoryChanged is called.
If you never change the number of slots, then you can refactor to cause the InventoryUI to instruct the InventorySlotUI to refresh their images instead of deleting all previous entries and starting with new ones.

1 Like

I’m really sorry @Brian_Trotter, I’m still a noob in programming, I don’t know how to refactor this. I know I have to delete destroying of children and instantiating new ones but I don’t know how to do this “InventoryUI to instruct the InventorySlotUI to refresh their images”
please help again.

here’s my InventoryUI.cs

using UnityEngine;
using GameDevTV.Inventories;
using System.Collections.Generic;

namespace GameDevTV.UI.Inventories
{
    /// <summary>
    /// To be placed on the root of the inventory UI. Handles spawning all the
    /// inventory slot prefabs.
    /// </summary>
    public class InventoryUI : MonoBehaviour
    {
        // CONFIG DATA
        [SerializeField] InventorySlotUI InventoryItemPrefab = null;

        // CACHE
        Inventory playerInventory;

        // LIFECYCLE METHODS

        private void Awake()
        {
            playerInventory = Inventory.GetPlayerInventory();
            playerInventory.inventoryUpdated += Redraw;
        }

        // PRIVATE

        private Category categoryFilter;
        //private EquipLocation locationFilter;
        // For all categories except Equipment, your butttons should call this method
        public void SetCategoryFilter(Category category)
        {
            categoryFilter = category;
            Redraw();
        }
        //For Armour, your button should call this method.
        //public void SetLocation(EquipLocation location)
        //{
        //    categoryFilter = ItemCategory.Armour;
        //    locationFilter = location;
        //    Redraw();
        //}

        IEnumerable<int> GetFilteredItems()
        {
            List<int> result = new List<int>();
            List<int> nulls = new List<int>();
            for (int i = 0; i < playerInventory.GetSize(); i++)
            {
                InventoryItem item = playerInventory.GetItemInSlot(i);
                if (item != null)
                {
                    if (categoryFilter == Category.None)
                    {
                        result.Add(i);
                    }
                    //else if (categoryFilter == Category.Armour &&
                    //         item is EquipableItem equipableItem)
                    //{
                    //    if (equipableItem.GetAllowedEquipLocation() == locationFilter) result.Add(i);
                    //}
                    else if (item.GetCategory() == categoryFilter) result.Add(i);
                }
                else
                {
                    nulls.Add(i);
                }
            }
            result.AddRange(nulls);
            return result;
        }

        private void Redraw()
        {
            foreach (Transform child in transform)
            {
                Destroy(child.gameObject);
            }

            foreach (int slot in GetFilteredItems())
            {
                var itemUI = Instantiate(InventoryItemPrefab, transform);
                itemUI.Setup(playerInventory, slot);
            }
        }
    }
}

You’re not using the course InventoryUI, you’re using a version I wrote for filtering by type for another student. Unfortunately, this filtering system does not mix with not destroying and re-instantiating the inventory slots, because the number of inventory slots that needs to be drawn changes in every change of the Inventory… Are you actually using the filter? It’s likely the filter that is the driving force in the lag spike.

This is the original code from the Inventory course:

        private void Redraw()
        {
            foreach (Transform child in transform)
            {
                Destroy(child.gameObject);
            }

            for (int i = 0; i < playerInventory.GetSize(); i++)
            {
                var itemUI = Instantiate(InventoryItemPrefab, transform);
                itemUI.Setup(playerInventory, i);
            }
        }

Refactoring to avoid destroying the InventorySlotUI works like this:

        private int inventorySize = -1;
        private void Redraw()
        {
            if (inventorySize == playerInventory.GetSize())
            {
                for (int i = 0; i < inventorySize; i++)
                {
                    transform.GetChild(i).GetComponent<InventorySlotUI>().Setup(playerInventory, i);
                }

                return;
            }
            inventorySize = playerInventory.GetSize();
            foreach (Transform child in transform)
            {
                Destroy(child.gameObject);
            }

            for (int i = 0; i < playerInventory.GetSize(); i++)
            {
                var itemUI = Instantiate(InventoryItemPrefab, transform);
                itemUI.Setup(playerInventory, i);
            }
        }
1 Like

I was about to give up and delete the whole inventory.
I will try this out, Thank you so much once again Brian.

it feels good to see 0 lag spikes on the profiler. yep, I was using the inventory filter but I think I have to sacrifice that feature to attain 0 lag.

Issue resolved :sweat_smile: Thank you so much!! @Brian_Trotter

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms