When a player is attacked I want to display the damage above their heads.
What would be the best way to go about this?
I realized i can have a canvas for each player, so whenever they lose health I can put a new text element in their canvas saying “-10hp”. But is this the most practical way?
The deprecated way is still the fastest- which is to make a blank GameObject, slap a really short coroutine generation script on it with an OnGUI() for displaying a number and a self-destruction timer. Make a prefab out of it and you can instantiate it over and over all day no problems. It takes literally all of 2 minutes to make and it works very well, but, you know, I’m going to get maimed on here for mentioning it as an option. shrugs
The majority of those steps can still be the same in bypassing the OnGUI stuff- but the prefab will be a bit more complex because it’ll have to be instantiated within the canvas by a damage-text generator and you’ll need to have more components (at least a Text component) on it to manipulate the displayed values. It should be pretty straight-forward, really.
It would have to convert from world space to screen space. The same is true if using a canvas.
I have no moral objections to using OnGUI, but the big problem I find is that it doesn’t play well with the new Canvas system — I can find no reliable way to control the layering (OnGUI always seems to draw on top).
If you are going to use a canvas, don’t make a canvas for each player — have one global canvas that you stuff all these elements into.
But from your original question, it sounds like you don’t need to display arbitrary text; you need to display “-10hp” (and perhaps a few variations thereof). In that case, you should consider just making images of those, and displaying them as sprites. Then they can fit into the 3D world right above your player, very easy to do and nicely layers.
Ok, this is odd.
If I have one canvas in world space and I can place a text element in it and move it however I want, but if I do the same during gameplay no text is shown?
I later figured out that the only way is to have an existing text object inside a wold space canvas and clone it every time I need a floating text box.
I wrote a script that will position it above the player, rotate it towards camera as a billboard and move it up while fading away.
If you really want to make this an efficient system. Instead of instantiating and destroying these objects, make an object pool at runtime, and simple enable and disable them. The act of instantiation and destruction is normally higher than turning them on and off. There’s a good example of this being done http://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/object-pooling, but that’s only if you want to be insanely OCD about efficiency. It really depends on whether it’s actually making a noticeable difference on your target platform.
@Nigey That’s a great idea, but considering this is done few times a second max and I’m targeting desktop platform the benefits are just not worth the development time.
I might add this after the game is finished and I want to polish it a bit…
But thanks for mentioning object-pooling, I think a part of my game would really benefit from that.
Actually, after experimenting a bit, I rescind my previous recommendation to not create a Canvas for each object.
On the contrary, a Canvas set to world space, and embedded within an object in the scene, makes a great place to draw stuff. It will let you take full advantage of all the nifty new UI stuff, including things like radial fill. But it will also blend into the scene and layer properly with everything else that’s going on.
Though I haven’t tried it, I would expect you could apply the billboard script if you want these stats to always face the camera.
As for performance… I doubt it’s an issue. I would have a stats canvas be part of the prefab for every damageable game object, but probably deactivate it when it’s not needed. Then, when a battle’s going on and you’ve got a few dozen of these things drawing their stuff, is it a problem? …I really doubt it. A canvas is just another way of transforming polygons into screen space, just like all the 3D meshes you’ve already got all over the place. There’s no reason to think they have any higher overhead than any other objects in the scene.
As I understand it, the guy who did NGUI was the contributer to the new 4.6 UI system (? someone confirm). It’s designed to be a lot more performance happy…