UI Rendering

From minute 3:45 in this lecture, the Instructor Sam points out that regarding the UI in Unity, the last child in the hierarchy gets rendered on top. So I don’t really get the difference between these two rectification, if any, as both solves the issue:


A clarification would be desirable

The 2nd setup is the one that we are after.
When the ActionSlot is drawn, first, the InventoryItem (which is the frame/background) will be drawn, then the Image which will be drawn on top of the frame/background. If you expand the Image, you’ll find a counter, which if there is a stack will draw a small number in the corner, this will be drawn over the image.
Finally, the CooldownOverlay will be drawn (assuming that it’s visible).

In the case of the first pane, the Cooldown overlay would be drawn 1st, then the InventoryItem Frame/background (covering the cooldown overlay), then the image, and finally the number.

I’m sorry, but I made the wrong comparison here. My bad…
Well, that’s the right one:


So again both do the same job, or is there a specific reason we stashed the InventoryItem inside a container and placed as the first children? This is what’s causing confusion

That might have to do with the Drag system.
When you drag an item,under the hood, the whole Image is dragged. It is then reparented when you release the drag. If there is an overlay over the image, but after the same parent, then the image will be added to the transform after the overlay. Using the container scheme with the Overlay image separate, the Image’s parent won’t be the Cooldown’s parent, so it won’t get reparented over the cooldown image.

I have observed the behaviour, but when I drag and drop the inventory item, the children stay in place. It’s not that we are re-parenting the image inside the parent item, but the whole inventory item itself, so that its state is captured and restored when we add it again. It is true that when we insert one object into another, the added object is added to the end of the list of children of the new parent, but that is not the case here. Correct me if I’m wrong here.

I think if we’re adding new elements during runtime and we want to ensure the Cooldown Overlay always stays on top, the Separate Parent Method then would be a concern, right?

The Image is really just a place holder, the actual Inventory Item is in the Inventory, Equipment, or ActionStore component.
If you click and drag on an empty slot, nothing happens because the InventorySlotUI/ActionSlotUI reports that there is no underlying InventoryItem and the DragItem script says “oh, nevermind then” and nothing happens.
If you click and drag from a slot with an Inventory Item in it, the Image (not the Inventory Item itself, just the Image with the icon) is reparented to the Canvas so that it can be moved and dragged. When it’s released, the Image component is reparented to it’s original parent. This is the part that causes issues with the 2nd construction above (Image and CooldownOverlay at the same level on InventoryItem). With this setup, when the Image is returned to the Inventory Item GameObject, it’s 2nd on the list after the CooldownOverlay. With it set up as a child of the Container=>InventoryItem, the Image is returned to the Inventory Item GameObject, and the Overlay, being a child of the ActionSlot, but being after the Container, remains in place overtop of the image.

Using the 2nd construction, yes, you would have to reorder the Cooldown Overlay and the Inventory Item after the drag operation. The only problem with this is that not all containers have a Cooldown Overlay Image, so we would have to do extra checking to ensure that there were 2 children of InventoryItem rathern than 1 before swapping them.

Using the 1st construction, no such additional coding is needed.

I see, the parent is simply parented in the parent canvas for the sake of the order layers, I assume, in the OnBeginDrag() method in the DragItem.cs:

I’m having difficult times relating to this problem as I can’t recreate it. I don’t need to swap them.
I have added a debug statement in the same method and when I drag the item from the inventory, the image is printed:
InventoryItem (UnityEngine.RectTransform): Image (UnityEngine.RectTransform)

When I drag it from the ActionSlot, both the image and the cooldown overlay are printed:
InventoryItem (UnityEngine.RectTransform): Image (UnityEngine.RectTransform)
InventoryItem (UnityEngine.RectTransform): Cooldown Overlay (Image) (UnityEngine.RectTransform)

And this behaviour persists throughout the game.

void IBeginDragHandler.OnBeginDrag(PointerEventData eventData)
{
    startPosition = transform.position;
    originalParent = transform.parent;

    // Delete - Debugging Purposes
    foreach (Transform child in transform)
        print(transform + ": " + child);

    // Else won't get the drop event.
    GetComponent<CanvasGroup>().blocksRaycasts = false;
    transform.SetParent(parentCanvas.transform, true);
}

My apologies, I misrembered the exact structure of the ActionSlotUI. That’s on me for not heading to the project itself for reminding (ironic, because I’ve had a copy of the project open working on a tutorial for the last week!).
The InventoryItem contains the Image that shows the Icon of the item
The disabled image below it (and the Text under it) represents the quantity when stacked.

The actual configuration that was at issue was having the InventoryItem and Cooldown Overlay at the same level under a transform.


I modified the ActionSlotUI to put the InventoryItem and CooldownOverlay at the same level (which you can see in the ActionSlot(1) through ActionSlot(4) configurations.
First, I dragged the potion to the 1st slot (ActionSlot), which behaved normally, as it was simply the receiver of the drag (no reparenting takes place on the destination).
Then, i dragged the potion from the 1st slot to the 2nd slot (ActionSlot (1)). Now if you look at that 1st slot (ActionSlot), you’ll see that the CooldownImage is 1st before the InventoryItem.

Placing the InventoryItem in a Container object was Sam’s solution to this issue, but as it turns out, there are often many paths to the same goal.

While trying to disprove our solution, (with the help of my poorly explaining the setup), you came across an alternate solution to the reparenting problem. Since the InventoryItem is what is being reparented, setting the Cooldown Overlay as a child object of the InventoryItem removes the bug.

In short, great job with this line of inqury!

No worries, I documented the whole inventory system to see what was going on behind the scenes as it wasn’t explained in the inventory course, well just partially, and we were told to think of it as an asset, but how could I.

As mentioned earlier, the only problem with this solution (without being on the same level under a transform) is that the InventoryItem in the ActionSlot gets something dropped during runtime. In minute 3:17 we see him deviate from this solution and opt for the Separate Parent Method, which could be the motive here, but I could not recognize this at first and then started this inquiry.

A tutorial for a game is an elementary building block for user-friendliness. When completed, I’m pretty sure most of us are looking forward to seeing the final result.

Thank you for your time

Outstanding. I wish more students would dig in and truly understand the inner workings of the Inventory system. The better you understand the inner workings, the more you can customize it to your own needs (and the easier time you’ll have integrating it into games besides the RPG project).

1 Like

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

Privacy & Terms