Unity tips and tricks every new game developer should know
Unity is a powerful cross-platform game engine developed by Unity Technologies. It gives users the ability to create games and other experiences like augmented reality, virtual reality and simulations in both 2D and 3D. The engine offers a primary scripting API in C#, for both the Unity editor in the form of plugins, and games (runtime scripts). With Unity, you can easily create 3D games and applications for mobile, desktop, the web, and consoles. It packs a ton of features together and is flexible enough to make almost any game you can imagine. Unity 3D comes loaded with a ton of professional tools for both programmers and artists.
In this article we will try to summarize (from my own and other people experience) some of Unity tips and tricks that every one entering the game development field should consider.
Never move assets of your Unity projects outside of Unity Editor
Unity stores a lot of metadata with its assets. This might be references to other files in the same project or import settings for a texture or model file. For example, a prefab referencing a material, or a material referencing a texture.
Note that in Unity references to other files do not depend upon path names. This allows you to reorganize your files whenever you want without the risk of Unity losing track of the connections between objects.
Because of that you can’t just drag files from project to project or folder to folder using any external tool outside Unity. You must use the Unity project view to move assets, otherwise references to them will be broken, and items in your project are likely to stop working.
Also, if you want to copy files from one project to another, use Assets→Export Package and Assets→Import Package to ensure that all metadata and all references will still be working properly.
Transforms
- When parenting Transforms, it is useful to set the parent’s location to <0,0,0> before adding the child. This means that the local coordinates for the child will be the same as global coordinates making it easier to be sure you have the child in the right position.
- Changing the Scale of the parent affects the position of child transforms. For example scaling the parent to (0,0,0) will position all children at (0,0,0) relative to the parent.
- You can change the colors of the Transform axes (and other UI elements) from the preferences (Menu: Unity > Preferences and then select the Colors & keys panel).
Particle System
In order to scale a Particle System, you need to modify the properties in the System’s Particle Emitter, Animator and Renderer because Particle Systems are not affected by the Transform’s Scale.
Rigidbodies
- The size of a GameObject’s mesh is more important than the mass of the Rigidbody. If you find that your Rigidbody is not behaving exactly how you expect (it doesn’t collide correctly, moves slowly or floats) try to adjust the scale of your mesh asset because objects of different sizes should be modeled to accurate scale.
- The relative Mass of two Rigidbodies determines how they react when they collide with each other.
- Making one Rigidbody have greater Mass than another does not make it fall faster in free fall. Use Drag for that purpose.
- If you are directly manipulating the Transform component of your object but still want physics, attach a Rigidbody and make it Kinematic.
Performance and optimization Tips
Unity Optimization refers to the process of making your game run better. Usually the main reason for optimization is to make the gameplay smoother, or to make the game more available to a wider audience so the game runs better on lower end devices.
1- Lighting
- Pixel lights can make your game look great but don’t go too nuts with them. However, using the Quality settings to adjust the number of pixel lights rendered for each quality level is a great way to provide ample performance/quality ratio in your game.
- Spotlights are more expensive than point lights which are more expensive than directional lights. A good way to light a scene is to first get the effect you want correct, then try to reduce the lights while keeping the desired effect.
- If a mesh is out of range of a point or spotlight and the light is set to attenuate, the mesh will not be affected by the light thus saving performance. Note that a mesh will only respond to the eight brightest lights affecting that mesh.
2- Meshes
- Reducing the number of gameObjects that Unity needs to render can boost the performance dramatically. So, in your 3D application, try to combine the nearby objects into a single object that has a single material whenever possible (this might require combining textures into one big texture atlas as well).
- Use only one material per mesh, because each material that is rendered is treated like a separate mesh getting rendered.
3- Textures
- Keep the size of textures as small as possible while still looking nice. There is no need to edit the size of textures in your image editor. You can edit the size that Unity imports the image on in each image’s Settings.
- Don’t use low quality image files. Trying to use jpeg files with low quality or low-color png or gif files will not result in a smaller player size. Unity compresses all textures when publishing the game automatically, so keep the source texture files as original high-resolution files. This will minimize quality degradation due to multiple compression and decompression.
4- Physics
- Each rigidbody takes computation, so use them with care.
- Complicated collisions take more computation than simpler ones. A large pile of rigidbodies with sphere colliders should be more complicated to process than if those spheres were laying far from each other on a terrain.
5- Canvas
Optimize Unity UI with common method by splitting UI elements to separate canvases by update frequency. Elements that are updated regularly, like Timers, under a single canvas and static elements under another one. This fixes the issue of having to update every single UI element in every frame.
6- Unity Text vs TextMesh Pro
Unity Text Component (UI) & Unity 3D Text (Text Mesh component) have bad performance, so, optimize Text with TextMesh Pro instead of default Unity Texts.
7- Static Text vs. Texture
Your asset can have a texture that must contain static text (e.g., Road Signs). You can use TextMesh Pro to create a text over the texture, but this can be a bad idea, since UI elements that move and resize in 3D space as the player moves cause performance load. In this case static text can be replaced with transparent textures.
8- Use Enums for comparisons when possible, instead of strings.
When starting out you may easily overlook Enums for more common data types like ints and strings. Enums can be very useful as they allow you to specify a list of items by name and have them treated as different int values.
When it comes to strings specifically, comparing them is slow as each character is compared. This slowness matters most when its being done in a Update method, as it would be performed every frame. Here is an example :
public class Weapon
{
public string name;
public string type;
}
Weapon pia = new Weapon();
pia.name = "PIA";
pia.type = "Automatic";void Update()
{
...
if (pia.type == "Automatic")
{
// Do something.
}
...
}
That isn’t a single comparison. Its 9 comparisons in the Update() method.
Now we will see how could a Enum do it better :
public enum WeaponType: { Automatic, SemiAutomatic, BurstFire };public class Weapon
{
public string name;
public WeaponType type;
}Weapon pia = new Weapon();
pia.name = "PIA";
pia.type = WeaponType.Automatic;void Update()
{
...
if (pia.type == WeaponType.Automatic)
{
// Do something.
}
...
}
In this case WeaponType.Automatic basically has an int value of “0”, and as such the comparison is just a single quick compare.
9- Don’t use GetComponent() in Update methods
As a beginner, you can easily fall into this bad habit, so you are unlikely to notice the performance costs of this. GetComponent() is a search routine and as with most searches, they take time, so as a general rule, any time you call GetComponent() in your code you should be asking yourself:
- Am I going to access this component more then one time ?
- Am I likely going to access this component in other methods ?
- Does this component exist when this script is first initialized ?
If you are going to access it more than once in a single method, store it to a variable. Then use that variable. If you are going to access this variable from other methods, then saving that to a global variable in the script is your best choice.
You should also check when that component exists, and save a reference to it as early as possible, and the best time to do that is during the Start() or Awake() methods. Then you can just access that reference from any other method (Update() method for example).
That’s all for this article, maybe I will update it with other tips and tricks in the future.
See also :