I’m prototyping shit at the moment, and since I’m wanting to blog more this year I figure I’d post some tutorials if I do anything that seems useful. Fair warning, I’m trying to get out of the habit of trying to write clever reusable code. I feel like it’s a trap I fall into a lot, and it’s more important to get shit done and realise that you’d never want to reuse that code anyway.
Today I’m gonna show how to easily position player names on a 2D canvas in Unity UI.
It looks like this, and can obviously be things like health bars and stuff too.
List Of Objects
You need a list of objects that want to show text. You can do this however you want. My list is a list of players, so I’m going to stick a static list on my player class.
Then add/remove from the just in OnEnable/OnDisable.
Now our list of players are available in Player.All.
So, do this:
- Create a Canvas (GameObject > UI > Canvas)
- Add a new Panel, name it PlayerNames (Right click Canvas, UI > Panel )
- Make the panel full screen (Click, shift click and alt click on this button)
- Change the pivot on the PlayerNames panel to be 0 and 0 (will explain this later)
- Add a child Text to the panel, called Name.
So what you have now is
PlayerNames is the panel that is going to contain and control the names.
Name is the template for the name.
So all we need to do now is create a script on PlayerNames. I called it PlayerNames.
So first of all we need an array to store all our “Name”s.
Then in Start, we’ll copy the Name text component.
Note that here we’ve copied the Text game object 9 times. We do this because we don’t want to be creating and destroying them every frame (because Unity hates that shit).
So in our Update function, lets do this. We get the list of players, ordered by the distance from the camera, closest first.
I’ve commented the rest inline, it’s pretty self explanatory.
So as mentioned in the comments, the localPosition of our child RectTransforms are relative to the pivot position of the parent. The long and short of that is that if the pivot position is 0, 0 then we’re just doing the pixel position from the top left.
If the pivot point is 0.5, 0.5, then you’re doing the pixel position from the center of the parent panel (in this case, the same size as the screen).
You don’t particularly need to know that shit, it’s just useful to know when trying to get rectTransforms to do what you want.
If you’ve got a critical eye, you might notice that it’s got the very slight shakes.
Rounding down helps
But there’s still something weird.
What you’re seeing is a common thing with using the Update function. The problem is that our Update function is running before the Camera moves. So we’re a frame behind every time.
So open Edit > Project Settings > Script Execution Order
Then add your script under the Default Time. This means that this script’s Update will be called after every other Update in the project.
If your text is still kind of wobbly, you might need to think more about your script order.
So there you go. Health bars are kind of just as easy, just replace the Text component with a custom component (although using Unity’s built in UI > Slider component works easily enough).
There are a few more math challenges if you’re scaling your canvas, but it should just be multiplication.
Something to note also is that this will show player names even if you can’t see them, like if they’re the other side of a wall. you’ll probably want to do a ray test or something from the camera to the world point where the player name is going to be if that’s a problem.