Mixing UI and game nodes

Godot Version



Long time web dev new to both Godot and game dev. I am just trying to prototype some UI ideas for a game and hitting some roadblocks. My game is 2D top-down style, and I have a character that can walk around the world and open crates.

My node tree is like this so far:

  |-Various Control nodes

I am trying to implement a crate inventory panel that pops up next to the crate when the player collides with it. The problem I am running into has to do with the actual placement of the Control node that displays the crate contents.

If I make the ItemList node a child of the crate, placement is easy since it is inherited. But since I am using a zoomed in camera, the item list also gets zoomed in. I can fix this by placing the ItemList within a new CanvasLayer but then it breaks positioning. I can attempt to fix this by getting the global position of the crate and using it to set the offset of the CanvasLayer, but it doesn’t seem to be the correct value (It falls short, I may need to multiply it by the zoom level?). I would also like the ItemList to remain stationary relative to the crate as the character moves, but since it is now in a new CanvasLayer, it is stationary relative to the entire window. The other problem with adding the ItemList as a child of the crate node is that the ItemList is not interactive. I can’t click or select any of the items.

My other approach was to add the ItemList to the main UI node, outside of the World node. This fixes the issue with it not being interactive, but I still have the problem where the placement becomes difficult due to the zoom.

Is something like what I am describing even possible in Godot? Is my approach all wrong?

I would eventually like to be able to make different inventory panels aware of each other with collision (imagine opening two crates near each other, having one panel open first and then the second slide out of the way instead of overlapping).

I just found out about get_viewport_transform() so if I multiply that with the global_position it fixes the placement problem I was having.