1
\$\begingroup\$

I am trying to create a grid based inventory and so far everything is going well except for one thing.

The inventory consists of Grids that are built of Cells, Grids can have custom size (like 5x3, 3x3). Every Cell is always 1x1 and can hold Items which can be of different sizes (like Grids).

I am handling the interactions in inventory using HandleCursor function which I run every frame to check if user is highlighting items/cells or moving stuff around.

As you can see in the code below I'm using a lot of fors to do that and I'am wondering if I could optimize it somehow so it isn't this hard on the CPU (right now highlighting a grid/item makes my inventory script create an overhead of 0.27-0.31ms.

Is there any better alternative than checking if Rect of each Cell contains my cursor?

        void HandleHighlighting()
        {
            HandleHighlightingCells();

            HandleHighlightingItems();

            HandleHighlightingPickedItem();
        }

[old] Highlighting all cells in all grids:

        void HandleHighlightingCells()
        {
            for (int i = 0; i < Grids.Count; i++)
            {
                InventoryGrid grid = Grids[i];

                if (grid.GetRect().Contains(Input.mousePosition))
                {
                    for (int x = 0; x < grid.width; x++)
                    {
                        for (int y = 0; y < grid.height; y++)
                        {
                            InventoryCell cell = grid.cells[x, y];
                            if (cell.GetRect().Contains(Input.mousePosition))
                            {
                                if (highlightedCell && highlightedCell != cell)
                                {
                                    highlightedCell.Highlight(EItemHighlightMode.NONE);
                                }

                                highlightedCell = cell;
                                highlightedCell.Highlight(EItemHighlightMode.BASE);
                            }
                            else
                            {
                                if (cell == highlightedCell)
                                {
                                    highlightedCell = null;
                                }

                                cell.Highlight(EItemHighlightMode.NONE);
                            }
                        }
                    }
                }
                else
                {
                    for (int x = 0; x < grid.width; x++)
                    {
                        for (int y = 0; y < grid.height; y++)
                        {
                            InventoryCell cell = grid.cells[x, y];

                            if (highlightedCell && highlightedCell != cell)
                            {
                                if (highlightedCell.grid == grid)
                                {
                                    highlightedCell = null;
                                }


                            }

                            cell.Highlight(EItemHighlightMode.NONE);
                        }
                    }
                }
            }
        }

Highlighting items in inventory:

        void HandleHighlightingItems()
        {
            if (highlightedCell && highlightedCell.heldItem)
            {
                InventoryItem item = highlightedCell.heldItem;

                if (highlightedItem && highlightedItem != item)
                {
                    for (int i = 0; i < highlightedItem.occupiedCells.Length; i++)
                    {
                        highlightedItem.occupiedCells[i].Highlight(EItemHighlightMode.NONE);
                    }
                }

                highlightedItem = item;

                for (int i = 0; i < item.occupiedCells.Length; i++)
                {
                    item.occupiedCells[i].Highlight(EItemHighlightMode.BASE);
                }
            }
            else
            {
                if (highlightedItem)
                {
                    for (int i = 0; i < highlightedItem.occupiedCells.Length; i++)
                    {
                        highlightedItem.occupiedCells[i].Highlight(EItemHighlightMode.NONE);
                    }

                    highlightedItem = null;
                }
            }
        }

Highlighting picked items:

        void HandleHighlightingPickedItem()
        {
            if (pickedItem)
            {
                if (highlightedCell)
                {
                    InventoryGrid grid = highlightedCell.grid;
                    InventoryCell[] cellsToHighlight = new InventoryCell[pickedItem.width * pickedItem.height];
                    InventoryItem firstItem = null;

                    bool valid = true;

                    int index = 0;
                    for (int x = 0; x < pickedItem.width; x++)
                    {
                        for (int y = 0; y < pickedItem.height; y++)
                        {
                            if (highlightedCell.x + x < grid.width && highlightedCell.y + y < grid.height)
                            {
                                InventoryCell cell = grid.cells[highlightedCell.x + x, highlightedCell.y + y];
                                cellsToHighlight[index] = cell;

                                if (highlightedItem)
                                {
                                    if (cell.heldItem != highlightedItem)
                                    {
                                        if (cell.heldItem)
                                        {
                                            valid = false;
                                        }
                                    }
                                }
                                else
                                {
                                    if (cell.heldItem)
                                    {
                                        if (!firstItem)
                                        {
                                            firstItem = cell.heldItem;
                                        }
                                        else
                                        {
                                            if (cell.heldItem != firstItem)
                                            {
                                                valid = false;
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                valid = false;
                            }

                            index++;
                        }
                    }

                    for (int i = 0; i < cellsToHighlight.Length; i++)
                    {
                        if (cellsToHighlight[i])
                        {
                            if (valid)
                            {
                                cellsToHighlight[i].Highlight(EItemHighlightMode.VALID);
                            }
                            else
                            {
                                cellsToHighlight[i].Highlight(EItemHighlightMode.INVALID);
                            }
                        }
                    }
                }
            }
        }

This is how my highlighting looks like after implementing juvians suggestion:

        void HandleHighlightingCells()
        {
            Vector2 mousePos = Input.mousePosition;
            bool anyHighlighted = false;

            for (int i = 0; i < Grids.Count; i++)
            {
                InventoryGrid grid = Grids[i];

                if (grid.GetRect().Contains(mousePos))
                {
                    Vector2 uiPos = Vector2.zero;
                    RectTransformUtility.ScreenPointToLocalPointInRectangle(grid.cellsRoot.GetComponent<RectTransform>(), Input.mousePosition, GameManager.singleton.inventoryCanvas.worldCamera, out uiPos);

                    int cellX = Mathf.FloorToInt(uiPos.x / 64);
                    int cellY = Mathf.FloorToInt(-uiPos.y / 64);

                    if(cellX < grid.width && cellY < grid.height)
                    {
                        cellX = Mathf.Clamp(cellX, 0, grid.width - 1);
                        cellY = Mathf.Clamp(cellY, 0, grid.height - 1);

                        InventoryCell cell = grid.cells[cellX, cellY];

                        if (highlightedCell && highlightedCell != cell)
                        {
                            highlightedCell.Highlight(EItemHighlightMode.NONE);
                        }

                        highlightedCell = cell;
                        highlightedCell.Highlight(EItemHighlightMode.BASE);

                        anyHighlighted = true;
                    }
                }
            }

            if(!anyHighlighted)
            {
                if(highlightedCell)
                {
                    highlightedCell.Highlight(EItemHighlightMode.NONE);
                    highlightedCell = null;
                }
            }
        }
\$\endgroup\$
  • 1
    \$\begingroup\$ This is a lot of nesting... \$\endgroup\$ – t3chb0t Dec 12 '17 at 11:54
  • \$\begingroup\$ I'll try to split it up into functions to make it easier to read \$\endgroup\$ – Fiffe Dec 12 '17 at 11:56
  • \$\begingroup\$ @t3chb0t I hope this is better \$\endgroup\$ – Fiffe Dec 12 '17 at 12:03
  • 1
    \$\begingroup\$ Not bad. You already did half of the optimization job ;-) \$\endgroup\$ – t3chb0t Dec 12 '17 at 12:09
  • 2
    \$\begingroup\$ is the loop of going over all cells to check which one has the mouse in it necessary? if cells have all the same size should be able to know which cell it is by mouse coordinates \$\endgroup\$ – juvian Dec 12 '17 at 17:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.