- Home /
Some questions on Unity best practices
I've been dabbling with Unity for about a year now, and am putting together my first game. I have proof-of-concept projects completed, my pipeline for Unity-ZBrush-3DSMax-Photoshop all worked out and tested... basically after a year I am ready to take all I've learned and actually get this game completed. I'm turning to the community for a little guidance on some best practices to make sure I can get the most out of the Unity engine. Any help would be greatly appreciated. I realize the following points are pretty general in their nature, but I'm really just looking for advice on whether I could be doing things in a more practical (or efficient) way.
First, I like to load some of my textures via a WWW request. It works great, but I'm a little concerned with how I store them. I generally create an array of Texture2D's and another array of booleans that keep track of whether that particular texture has been loaded already. Is this a terrible way of doing things? My arrays are generally one or two dimensions, with up to 10 elements in each.
I found an FPS script on here somewhere (code below) and added it to my game so I can easily view frame rates on my droid device. The odd thing is that this number is never anywhere near the FPS that the Unity Editor displays in the stats window... the stats window always shows an FPS that is about double what the script displays. From my experience with games, it seems as though the script is more accurate than the stats window, but I'm curious as to why this happens and how I can ensure that I am getting accurate FPS info in my game.
Code for FPS :
using UnityEngine;
using System.Collections;
public class HUDFPS : MonoBehaviour {
public float updateInterval = 1.0F;
public float fps = 0f;
private float accum = 0; // FPS accumulated over the interval
private int frames = 0; // Frames drawn over the interval
private float timeleft; // Left time for current interval
void Start() {
timeleft = updateInterval;
}
void OnGUI() {
GUI.Label (new Rect(Screen.width - 110, 10, 100, 20), "FPS: "+fps, GetComponent<StyleGUI>().mainDataStyle);
}
void Update() {
timeleft -= Time.deltaTime;
accum += Time.timeScale/Time.deltaTime;
++frames;
// Interval ended - update GUI text and start new interval
if( timeleft <= 0.0 ) {
// display two fractional digits (f2 format)
fps = accum/frames;
fps = (float)Mathf.RoundToInt(fps * 10) / 10;
}
}
}
Unity's GUI system seems a bit strange, but I've read that there's a big GUI update coming with the release of 4. Until then, I'm curious about the best practice for using GUIStyles and GUISkins. Which is less resource heavy? I prefer using a public GUIStyle on my scripts and adjusting them individually in the Inspector. I've also dabbled with creating a GUISkin, initiating a "copy" of that skin, and adjusting font sizes, colors, etc. from that point on, but the GUISkin just seems like it would be much more resource heavy. I know there are a lot of tutorials out there on the GUI system, but I have yet to find one that explains the best way of going about it and why it's the best way.
I read in some forum posts that rather than using transform.do_something in your update functions, it is best to set a transform variable to the objects transform in the start function, and then use that variable in the update function. For example :
void Start() {
_transform = transform;
}
void Update() {
_transform.do_something;
}
I can see (from my inexperienced perspective) benefits for both. Storing the variable would improve response of the Update function itself, but then the variable has to be stored in memory the entire time the game is running, whether that _transform variable is getting called or not. The odd thing is that in all of my searching I haven't come across many coding examples that use this, which makes me wonder whether it really is a best practice or not. Any input on this would be greatly appreciated, before I end up with 100 Update functions that are all using a _transform variable when they shouldn't be.
Lastly, I would love to be able to load game objects via a WWW request the same way I do textures, but from what I've read this can only be done with Unity Pro. I have every intention of purchasing Pro in the future, but was just curious if there is a way to do it with the free version. If not, I'll wait.
My apologies for numerous points in this post, but I figured it'd be better than clouding up Answers with several separate questions. I would really appreciate any advice/tips on this and anything else anyone has to offer. I am not looking for anyone to do the work for me by any means, just reaching out to the community of more seasoned Unity programmers for some direction on maximizing my games performance... at least as far as these points are concerned.
I am sure you will get a few answers to this question - though as UA is a $$anonymous$$nowledge Base it would perhaps have been better to ask more than one question with a meaningful title - it's also hard for someone to answer if they only know part of the solution as it would be hard for you to tick their answer as accepted.
Answer by whydoidoit · Sep 23, 2012 at 01:50 AM
FPS
Your FPS calculator looks odd to me!
I would have thought that accum should be incremented by Time.deltaTime/Time.timeScale and then your fps calculation would be the more obvious frames/accum.
GUI
You don't say what platform you are going to be building for - this does make a difference. Unity 4.? will contain the new GUI system, it looks very nice but Unity 4.0 will not have it and who knows when it will be released - soon I hope.
In the meantime if you are developing for mobile devices do not, under any circumstances use OnGUI. Buy NGUI or EZGUI and use that instead.
Texture Loading
Use a dictionary to keep an association between your textures URL and the loaded Texture2D.
static Dictionary<string, Texture2D> textureCache = new Dictionary<string, Texture2D>();
...
Texture2D textureToUse;
if(!textureCache.TryGetValue(url, out textureToUse))
{
textureToUse = //Load texture from WWW here;
textureCache[url] = textureToUse;
}
Keep your textures square/power of 2 sizes to save lots of memory. Compress them after loading if you want to.
Caching things
It makes a massive performance difference to cache things like transform. Do it. If you don't see code using it then its just quickly knocked out stuff, the author isn't aware of the penalty - or it isn't being used often enough to make a difference. Caching transform etc takes 4 bytes for each one.
Also be very aware that setting and getting the .position and .rotation of an object is expensive - it has to walk all of the parents to work out what the local value should be. Either cache positions and rotations if you can or even better, use the localXXXX versions. So if a routine does _transform.position twice - stick it in a local variable, if a script totally owns the position of something then cache it in a variable in Start or Awake and only ever write it. As I mentioned before, using localPosition is better still because writing the value will not incur a penalty either.
Loading objects by WWW*
You can use @Eric5h5's ObjReader to load models at run time without the need for Pro. It is easier to use Asset Bundles to enable more complex sets of objects to be loaded if you buy Pro.
FPS
Thank you for that, I'm honestly just happy right now to know whether it was the script or the stats window... now I know which number has to match which (the fps script needs to be adjusted to match the stats window) so via the docs and your answer I should be able to get it to display the correct FPS.
GUI
In the 4.? lies the reason behind not buying NGUI already... I was going to try the new GUI system in 4.0 (thinking it would be in 4.0) and decide whether to purchase it then, but I definitely don't want to wait for version 4.? to come out lol.
Textures
If I'm understanding your code correctly, then the TryGetValue is essentially replacing all the overhead of the booleans and even the possiblity of caching the same texture twice when it's not necessary to do so. I am definitely going to try and get it to work with my system, I'm just wrapping my head around whether I can get it to work with my progress bar script... pretty sure I can though.
Caching things
The second part of your answer has me a bit hung up. I'm storing the Transform in a variable when instantiated, but it's also good practice to store the position as a Vector3 and the rotation as Quaternion? So basically _rot of my _transform example is faster than _transform.rotation? Sorry if I'm way off here, but I really want to understand your answer.
WWW
Thank you for the reference. I'll definitely give it a try and see if it does the trick, if not I'm good waiting until I can afford Pro.
Textures
Yes using a generic dictionary like that is an O(1) operation (it isn't dependent on the number of items that are loaded, it is always around the same speed - fast). Bools and an array is probably also an O(1) operation if you are using a numeric index to get into the array - it's O(n) if you are searching the array and that is bad - gets much slower as you increase the number of textures.
Dictionaries are nice and clean and always very fast - you should use them where you need an association and you don't have a single ordinal integer to find it in an array.
You need to put: `using System.Collections.Generic` in the source file to use generic dictionaries.
Caching things
You can cache the position locally in a routine if you are going to do transform.position or .rotation more than once. The performance hit is only for objects that are the children of another object and the penalty is relative to the number of parents (the nesting level).
But yes _rot is hugely faster than transform.rotation if working on an object with more than one parent. It can be hard to cache such things at a script level though - like I said, you'd need the script to absolutely control the position of something - no physics etc - so you might just content yourself with caching it in a routine (especially coroutines which are more likely to own the position while executing).
So
either don't move things that have parents much - top level items have no penalty and can be absolutely placed without a problem.
cache .positions of things with parents inside routines that use them
if possible use local positions because these never have a penalty
I should add that there is a big difference between a Transform and a Quaternion.
You can always cache a Transform because it is a class - you're caching a reference to it and it's faster to use that than to use the transform property of Component.
When you cache a Quaternion or a Vector3 you are caching a copy, because they are structs (value types) which is why the script would have to own the position. Because if the item moves your copy will not change, so it would have to be the truth about where the object should be placed.
Basically you should cache a .position or a .rotation while you know it won't change behind the scenes. For example it can't be changed by something else while a single function is running - so that is always safe. Using this elsewhere is a big design decision and can lead to problems - but it is quick.
I don't see anything wrong with his FPS counter ;) It should give you the same result.
Time.deltaTime is the time of the last frame. Therefore one over Time.deltaTime represents the current FPS. Time.timeScale over Time.deltaTime represents the current FPS that is independent from the current timescale.
He just accumulates this FPS number to smooth it out a bit so he has to divide it by the number of frames he accumulated.
In your approach you acumulate the timescale independent deltaTime value and do the one over delta time when you calculate the FPS number. You have to multiply by the frames accumulated since the deltatime value is too big and therefore you get frames / accum, but it will give you the exact same result ;)
edit
Btw, the stats window's FPS counter works differently. It doesn't show the actual FPS. I'm still not sure what they do, but it's not the real FPS value. You can trust your own FPS more i guess ;) At least i have written an OpenGL wrapper long time ago. It kind of injects a toggleable overlay which also calculates the FPS. It matches the one i calculate myself in Unity, so don't bother with the stats-window-FPS ;)
Your answer
![](https://koobas.hobune.stream/wayback/20220613081347im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Optimizing Code 0 Answers
Best way to format characters/models in game? 1 Answer
How to drag my armory from GUI to Terrain? 1 Answer
Showing Time With GUI.Label 1 Answer
GUI works flawlessly in editor, but will not show in standalone build. 1 Answer