Over the years of working with Unity I've picked up tips and tricks on how to better improve my workflow. Included in this list are my personal favorites, I'm also including a few I've found recently to be quite useful. I've split these up into groupings based on various aspects of Unity game development.
- Create a custom layout for specific workflows. I typically work with a wide layout with the project panel left in one column mode. If you prefer panels and windows in a specific layout, save it then you can switch between layouts easily to speed up your workflow. Learn how to create layouts in this lesson:https://cgcookie.com/lesson/using-layouts/.
- If you need to compare two game objects with the inspector panel, duplicate the inspector panel, select your object, then lock that panel. You can then select your second object and see them side by side with two inspector panels.
- You can apply a tint to the editor when in play mode. This is useful as changes made in play mode will not be saved, so having an obvious red tint visible when in play mode ensures you are aware.
- Components have a gear icon in the top right. Use that to move them up, copy values and remove them from a game object
- Getting annoyed by the large canvas blocking your view in the scene? Hide the UI layer by clicking on the "eye" icon in the top right.
- Use avatar masks to combine multiple animations based on body parts. This reduces the need for multiple custom animations such as those specific to upper body and lower body. For instance, you can run while performing separate upper body animations without needed a running state of each of those.
- You can use Inverse Kinematics to mimic gripping or holding mechanics such as holding a steering wheel, gripping various weapons, etc.
- Uncheck "Has Exit Time" for any animation transitions that need to happen instantly when a parameter is used. Exit time determines that an animation clip must finish playing before transitioning. This is a commonly overlooked thing that people forget about and wonder why their animations are delayed or not working as intended.
- You can mirror animations for different orientations. A left turning animation can be mirrored for a right turning animation. Test this out to ensure it looks as intended. Note this will not reverse an animation and this only works on humanoid animations
- You can reverse animation clips by adding a negative value for the speed. This works with generic and humanoid animations, e.g walk forward can be used for walking backward as well.
- Use the Range Attribute to add sliders to numerical values. If you're working on a team this is especially useful since anyone who sets the values cannot add in a lower or higher value than you expect to use. It also makes things easier to look at.
- It's often better to have multiple smaller scripts that perform specific tasks than one giant script that is a pain to modify. Think about the default Unity components like Rigidbody, AudioSource, Colliders, etc. These all perform specific tasks and can work with each other, but a rigidbody will not play audio clips, nor should it know how to. Note this isn't always the case, but when feasible keep things modular.
- Organize your scripts so they are easy to read. I like to keep public variables at the top with private variables at the bottom. Do the same with methods so they are easy to understand without having a deep understanding of the script. I like to organize my script in a way that makes it seem like a "timeline" of functionality.
- Tool tips and headers are a great way to inform others what a specific variable/group refers to.
- Use the Gizmos and Handles classes to test various game mechanics such as drawing a wire sphere to denote the range of an explosive in game or view radius of an enemy character:
- Save code snippets and full scripts that you find useful locally on your computer. I keep a folder on my computer specifically for useful pieces of code I may use in multiple projects that may be easy to forget. Same is true for complete scripts that are a pain to rebuild from scratch.
- When possible cache components and store them in a variable in the Start or Awake method. Using GetComponent in the Update is not necessary.
- When writing out loops/if statements/etc press tab twice to quickly autocomplete opening and closing parenthesis and brackets. e.g write out "if" followed by two tabs and see the code auto complete to a full if statement.
- Use texture atlases when possible. This goes along with performance, but it also makes it easier for file organization if multiple assets share similar texture maps and materials. Below is an example of a texture atlas used in the Tower Defense Flow for multiple props and game objects all within one larger texture map
- Whenever possible bake lighting in your scenes. Lighting can be a big performance drain if it's set to realtime. If you don't need to have realtime lighting for everything, then set them (game objects) to static and bake. You can also utilize a mixture of realtime and baked lighting. Learn more about lightmap baking in this course:
- If you need to use a mesh collider (compound colliders are more performant) it is recommended that you build a low poly version of the same mesh to use as the mesh collider. This not only provides a higher quality mesh collider but it can also be better for performance. You can also use Convex which helps, but this may not provide desirable results thus creating one yourself helps.
- When you're done using Debug.Log messages, remove or comment them out. Same is true for any other debugging messages and/or "drawing" debugging methods.
- The "stats" window can be inaccurate for determining proper frames per second. It's recommended you create your own FPS counter and utilize the profiler for more accurate performance stats. I typically use the stats window for determining set pass calls, but for more in-depth performance testing either custom tools or the built in Profiler
- Use the lowest resolution texture maps possible to reduce size and increase performance.
- If you expect to use multiple objects over and over use an object pooling system to reuse objects without destroying them. Instantiating and destroying multiple objects very quickly can be a drain on performance and not very efficient.
- Use empty game objects within your scene to group together like items. An example would be grouping all your buildings/trees/terrain into a group called "Environment". This not only makes it easier to find objects, but also makes it easier to disable/enable groups of objects.
- On a similar note, use empty game objects as parent objects for things like meshes. When possible avoid placing scripts or components on meshes directly. Using an empty parent makes it easy to modify the mesh without having to recreate/add the components. It also allows you to control the position/rotation of mesh objects while keeping the parent consistent.
- Create a standard folder structure in your project panel. Below is an image of how I typically arrange my folders. Names are up to you, but try to be consistent.
- Avoid ambiguous naming of files. Name things what they are. If you have a trash can prop, name it "TrashCan_Prop". Anyone should be able to browse through your scene hierarchy or project panel and have a good understanding of what the object should be based on the name alone.
- Unity Services are a great way to manage your projects, namely the Collaborateand Cloud Build services. I use Collaborate to save versions of my project which I can then give access to other members on the team. Cloud Build is a great way to build our game for multiple platforms then automatically email links to the finished builds to team members.