- Home /
HUD with a lot of elements, efficient way?
Hi! I'm midway trhough the production of a game that features a minimap. Minimap right now works with onGUI, and draws a high number of small icons and colored rectangles. After research, I got to know that both OnGUI and GUItextures are just that inefficient. What's the proper way to accomplish the rendering of such a feature?
Answer by Fattie · Aug 12, 2013 at 01:35 PM
Simply use 2DToolkit.
Click once to add a second camera. Simply sit the camera "off screen".
(You don't say even slightly what sort of game you're doing. But say it's a race game. So you have a track, cars, etc etc. Simply, way off to the right (say) of your stage, have this other camera - perhaps an ortho camera - and have all your UI material there.)
On that second camera, just have whatever you want - the map, speedometer, gauges, text messages, whatever.
This is the unbelievably simple way to do everything.
Just forget about OnGUI.
BTW note that this is an absolutely basic technique in video games, you will use it all the time and everywhere. It's just "the normal way" you do onscreen maps, etc etc, in a typical game engine.
There are many helpful QA about the issue on here,
http://answers.unity3d.com/questions/361259/two-active-scenes.html
As you and Fornoreason1000 said, probably the best way is to just have another set of gameobjects and another camera. However that way it's insanely hard to give the components a size and position in pixels, which is something I need to do. Any trick around that? Just to clarify, the game is sort of a tile-based dungeon crawler, and the main guilty of the performance loss is a $$anonymous$$imap and its 100~ iterations of GUI.drawtexture
Hi $$anonymous$$oleg ..
"However that way it's insanely hard to give the components a size and position in pixels"
I have good news -- you are totally wrong :)
Just use 2DToolkit. Everything works exactly in pixels. It's that simple.
It's a very basic aspect of Unity production.
If you think about it, a vast number of games are "pixel perfect" and it's very easy to do in unity. Just search on here for answers about it.
Really, pretty much every Unity game you have ever played - indeed pretty much every game - when there's a "heads up display" or "map" or anything, it's simply done with a separate camera.
It's just how it's done. I encourage you to proceed that way.
"100~ iterations of GUI.drawtexture" yeah this is totally wrong just forget that
Again, regarding 3D / pixel perfectness - just grab 2DToolkit and you're done. You click the "pixel perfect" button and that's it.
Insanely Hard? not really... lets suppose 2d toolkit didn't exist... you are aware of the camera class function to convert to Screen space?
if not here: http://docs.unity3d.com/Documentation/ScriptReference/Camera.ScreenToWorldPoint.html
100 iterations? your doing this each frame?... i would pre render the part of the image + 1 tile around the edge that is visible then add and remove tiles as the player walks. but even that's pretty hefty.
2d toolkit is your best friend here
Well that's a neat function! I'm not using 2dtoolkit yet, as I'm trying to use just vanilla unity stuff until I'm a bit more experienced. However with a secondary orthographic camera and the screentoworldpoint function, I feel like it can work out. Thanks both of you for the help, and... yeah, 100~ iterations in OnGUI is something crazy, never going to do that again! :D
Answer by TonyLi · Aug 12, 2013 at 01:30 PM
OnGUI isn't inefficient, but you can use it inefficiently.
First, every OnGUI method has significant overhead to set up, even if the method is empty. So the first rule is to use only one OnGUI. Put your OnGUI in a separate component that you enable only when the GUI is visible.
Second, put all your icons in a single texture atlas and use GUI.DrawTexture. Set the texture type to GUI.
Third, as @Fornoreason1000 mentions, don't do any processing in OnGUI (or any method that gets called every frame). Precompute and store all calculations. (However, surprisingly, this might not be as big a factor as the overhead for simply calling OnGUI, so make sure you only have one OnGUI.)
Similarly, don't use GUILayout to compute GUI control positions. It will double the time it takes to draw the GUI. Precompute absolute positions.
And only assign GUI.skin once, at the beginning of OnGUI, if you're using a custom skin. Likewise, don't create new GUIStyles every time OnGUI is called. If you have to create a new style, create it once and store it.
Also, don't call Debug.Log in any per-frame methods. It will really slow things down.
If you follow these tips, you should hopefully find that Unity's GUI is actually pretty good. And this comes from a loyal user of NGUI. :-)
Thanks for the tips, which I'll take into account from now on every time I use OnGUI. However, I already use only a single OnGUI method, every texture used (there're only three different ones) has it's type set as GUI, and I use GUI.drawTexture. Still, I get a drawcall for each one of them, so for this case, I'll have to find some other way around, and ditch OnGUI for once.
Answer by Fornoreason1000 · Aug 12, 2013 at 09:59 AM
Personally I achieved it by generating meshed planes and other shapes that only update when you change their elements. e.g color change, mesh size, new selection. the only thing that updates constantly is the buffer that draws them. which isn't too costly. it isn't the proper way...
this style makes it easy to handle unwanted windows and other elements because each element of your GUI is a game object on a isolated layer(s). The only weakness is creating a Mouse Event handler will slow this style back to a crawl, so I didn't add the mouse at all and it can be time consuming to create it from scratch.
there are some "rules" though: - Don't create objects or GUI in Update, PostRender, LateUpdate or anything per frame related. Mesh generating as you can imagine is quite slow and isn't needed each frame. - Set all you GUI objects onto a layer so that your character can't visually see them in your world. - Text is Displayed with 3DText. - Make a camera that only renders your GUIlayer(s) and avoid destroying it on load. Orthographic is optional
Your answer
Follow this Question
Related Questions
Reduce Draw call for Multiple GUI Textures with same Texture 1 Answer
Game Over 2D GUI position 0 Answers
Change Texture onHover GUI.Button 1 Answer
Unity 2d mobile android GUI texture button 1 Answer
Eliminate GUITexture Excess? 1 Answer