Sea otter in a circleSea Otter Games

#5 - UI Toolkit in world space

By Hugo on 2023-12-31
Game Development
Unity
Tutorial
UI

When making games, you will most likely need to create UI elements in world space. World space is the coordinate system in which your character, NPCs, enemies and everything exists: the global coordinate system. It is opposed to the local coordinate system of an object which depends on its parents and eventually to the first parent’s global coordinates.

UI is usually positioned using the coordinate system of the screen. This means that the origin will be a corner of your screen and the coordinates will exist within the bounds of your screen resolution.

Let's say you wish to put a healthbar over units in a Real-Time Strategy game. These bars have to move as if they were hovering above the head of the unit. That's what we call “world space UI”: a piece of UI displayed in the same space as game elements.

"A screenshot of the game starcraft 2 featuring a terran base where you can see healthbars above units."
In Starcraft 2, all units and building have a healthbar above them. This healthbar uses global coordinates.

Being so useful, I quickly needed my UI Toolkit (UITK) elements to exist within world space. However, there is no support (yet ???) for world space in UITK. But everything is doable with a bit of imagination and the right API 😊. Hopefully, the UIElements package implements a method to convert UI coordinates (which is referred to as “Panel”) to global ones.

1[SerializeField] protected UIDocument document; 2protected VisualElement root; 3 4void Start() { 5 root = document.rootVisualElement; 6} 7 8protected void SetPosition(Vector2 worldPosition) 9{ 10 Vector2 screenPoint = RuntimePanelUtils.CameraTransformWorldToPanel(root.panel, worldPosition, Camera.main); 11 root.transform.position = screenPoint; 12}

Moreover, if working with tilemaps, you can chain the conversion to go from tile coordinates to panel coordinates.

1[SerializeField] protected UIDocument document; 2protected VisualElement root; 3 4void Start() { 5 root = document.rootVisualElement; 6} 7 8protected void SetPosition(Vector3Int tileCoordinates) 9{ 10 Tilemap tilemap = TilemapManager.Instance.myTilemap; 11 Vector2 worldPosition = tilemap.CellToWorld(cell.GetVector3Coordinates()); 12 Vector2 screenPoint = RuntimePanelUtils.CameraTransformWorldToPanel(root.panel, worldPosition, Camera.main); 13 root.transform.position = screenPoint; 14}

A video of my game where a UI element moves from one tile center to another.
And just like that your UI elements can be placed according to your tiles!
(Noticed the weird pattern in my tilemap? We might talk about it in a future article 😏. Stay tuned!)

Thank you for reading to the end and a happy new year 🎉! I hope to see you in the next post. 🦦

© Copyright 2024 - 🦦 Sea Otter Games