Unity Tip

Bite-Sized Tips and Tricks for Unity

#UnityTip

Each Canvas acts as a renderable collection of UI elements in a scene. You'll likely benefit by using more than one in your scene as a single UI change forces the entire Canvas mesh to be regenerated. Keep this in mind when designing your Canvas layouts.

UI
#1

Canvas > Panel > UI Elements is a typical nested structure for Unity UI. Examples of UI Elements include Button, Text, Image, Slider, etc. You can even nest a Panel within a Panel, don't be scared.

UI
#2

There are three Render Mode settings for a Canvas. Screen Space – Overlay (2D perspectiveless HUD, rendered above all scene objects), Screen Space – Camera (2D perspective HUD, rendered with variable scene depth), and World Space (3D perspective, with variable scene depth).

UI
#3

The RectTransform is the base component of all UI elements. You set its anchors to control resizing based on its relationship to its parent. You set its Pivot Point to control its 2D position (x, y), which also acts as the position from which scaling and rotating occur.

ui
#4

All UI elements are comprised of Text and Image components in one form or another, that’s it. You can have an Image component be represented by a solid fill color as opposed to an actual Sprite too, it’s no big deal.

ui
#5

All interactive UI elements extend the Selectable class. This class provides an interactable toggle, transition settings (over, down, pressed, etc), and navigation settings (“tab order” for PC keyboards, console controllers, etc).

ui
#6

Use a CanvasGroup component to fade out a collection of UI elements (panel and its children) as one entity. This component also allows you to enable/disable all interactive children at once. CanvasGroup is your friend.

ui
#7

Unity renders UI elements in your Hierarchy view from top to bottom. This means the bottom most UI element in the Hierarchy view is rendered last, and thus above of all other UI elements on screen.

ui
#8

A ToggleGroup component is useful for mimicking “Radio Buttons”. It is best practice to put the ToggleGroup component on the parent of the Toggle instances, though not required... why did I tell you that last part?

ui
#9

When importing PSD files, make sure to update its Texture Type setting to Sprite (2D & UI) if you intend to use the asset for 2D or UI. This is a gotcha that can be frustrating if not set properly.

general
#10

For custom UI interaction events, have a custom component script implement from UnityEngine.EventSystems.XXX where XXX is a Unity built-in interface. Example interfaces include IPointerEnterHandler, IDragHandler, ISelectHandler, etc. and allow the execution of custom code within the interface’s implemented method.

scripting
#11

The Navigation setting on an interactive UI element is used to determine “tab order” which changes the focus of UI elements in controller, keyboard, etc based user interaction models. The Visualize button shows the focus flow in the Scene view.

ui
#12

You can use the EventTrigger component on a Selectable UI element (Button, Slider, etc) to expose additional event types in the Inspector. This is useful if you want to make a UI or scene change dynamically based on user input other than OnClick.

ui
#13

For masking, simply have a Panel (PanelA) nested inside another Panel (PanelB) where PanelA is larger than PanelB. Then simply select PanelB and add a Mask component. This enables PanelA’s content to show through. Remember, the masked area is based on the Source Image property of PanelB's Image component.

ui
#14

For a Mask, the mask area is based on the attached image component. Transparency in the image cuts out the visible area of its children. You can uncheck Show Mask Graphic to hide the graphic itself but still provide the mask area, nice.

ui
#15

For masked scrolling, simply add a ScrollRect component to a parent Panel containing a Mask component. Then set the Content property of the ScrollRect to the child panel whose bounds exceed those of the parent panel. Scrolly time.

ui
#16

For Auto Layouts, simply add a GridLayoutGroup, HorizontalLayoutGroup, or VerticalLayoutGroup component to a Panel and then all children will automatically align. You will likely want to edit this automatic alignment and you can do so with the Start Corner, Start Axis, or Child Alignment properties. The parent controls the “cell size” of the children as well.

ui
#17

A Button can have a GridLayoutGroup, HorizontalLayoutGroup, or VerticalLayoutGroup component to automatically layout its children. This is useful if a single button has numerous visual elements within it. In addition, the children can have a LayoutElement component to set min, max, and preferred sizes that override or inform the layout group to handle the child in a specific way. Go make cooler buttons.

ui
#18

A Button with a HorizontalLayoutGroup component and padding can ensure the button resizes according to the size of its children and no bigger. A LayoutElement component with no flexible width is necessary for this to work.

ui
#19

Set a UI element’s LayoutElement flexible width or flexible height properties to decimal values to allow the parent layout group of each to organize them by “weight” or “percent”. This percentage based layout works until all children only have room to be their preferred width or preferred height. This is super useful and similar to Android’s layout_weight or the Web’s percentage based layouts.

ui
#20

You can use an empty GameObject with a RectTransform instead of a Panel to group UI elements. This is handy if you want a “lighter Panel” that doesn’t require a visual representation itself.

ui
#21

Add a CanvasScaler component to a Canvas to better control resolution variations. It is a good idea, and most common, to set the Screen Match Mode to Width or Height with a value of .5. The Expand and Shrink options are best for background graphics that simply cover the entire screen area (smaller use case, but depends on your game/app).

ui
#22

When dynamically adding UI elements to a scrollable content Panel, a ContentSizeFitter component is of great help. It will make the scrollable area size “snap” to the combined area of the internal UI elements. For this to work, 1) the children UI elements each need a LayoutElement with set preferred sizes (width, height, or both) and 2) the panel with the ContentSizeFitter needs its layout group’s Child Force Expand (width, height, or both) setting(s) disabled.

ui
#23

For each texture, you can set platform overrides. This is useful for changing the graphic size and compression of image assets on a per-platform level.

general
#24

Unity doesn’t have a built-in pixel-density solution, so sad face. However, you can poll the device or machine using the Screen class to get the resolution, pixel density (dpi), and more. An approach could be 1) get the Screen info 2) calculate a “best fit” (similar to Android’s ldpi, mdpi, hdpi, etc), and 3) ensure all graphic assets are utilized from the “best fit” Resources folder.

general
#25

To create your own preloader scene, just make the first scene virtually empty (except for what you need to visually represent preloading) and when this preloader scene is loaded, call LoadLevelAsync() or LoadLevelAdditiveAsync() and then query progress and draw the preloader visuals.

general
#26

It is best practice to use generic lists as opposed to ArrayList. The Unify Wiki has a great breakdown of when to use one over the other, why, and alternatives.

scripting
#27

Set up a looping coroutine in the Start() method of a component instead of using the Update() method if updates for a Component don’t need the game/app frame rate (.2f coroutine will run 5 times a second vs 60fps)

scripting
#28

If you have a scrollable view that holds a large amount of UI element instances (ex. list items), you’ll likely want to optimize. Conceptually, if you have a max of 10 instances out of 100 visible at any one time; creating all 100 is a waste. Instead, use the Object Pool pattern. This way you only instantiate 10 or so instances and based on scrolling position, you’ll recycle and update each view with the correct data. Android and iOS use this approach to optimize the performance of scrolling long lists.

scripting
#29

A Prefab with an attached custom component (ideally by the same name) can hold references to itself, and/or its children, and/or other connected components. This allows a single GetComponent<MyComponent>() call to gain reference to the Prefab instance's connected components or GameObjects whose properties change/update at runtime. This is a very useful approach for succinctly "building" or "inflating" Prefab instances at runtime based on dynamic data.

scripting
#30

It is best practice to use a Sprite Sheet (aka Atlas) for your graphics assets in 2D (and 3D) games/apps as opposed to having a one-to-one relationship between a texture and an image file. The core advantage of this approach is performance related. Basically, the device on which your game/app is running can minimize draw calls by UV mapping part(s) of a texture (your Sprite Sheet) multiple times to a geometry. The alternative is a draw call per texture per geometry.

2d
#31

It is a common practice to use an empty GameObject as a “folder” within a scene. This helps you better organize and structure your game in a visual way. A specific approach is to position an empty GameObject at (0, 0, 0) which is then filled with various manager classes, utility classes, and a top-level eventing system. This is a useful approach, especially for persisting components across scene loads.

3d
#32

When in the Scene view, have you ever wanted to make one GameObject point or “look at” another GameObject? To pull this off, simply hover the GameObject in focus with your Rotate Tool selected and then hold ctrl/cmd + shift as you drag the Rotate Gizmo. While dragging, the GameObject you’re rotating will “look at” the GameObject you hover. Things are looking up.

3D
#33

There are times when positioning a GameObject that you want its position to snap to the surface of another GameObject. This is common when wanting to drag an object across a floor for example. You can use Surface Snapping to achieve this. Simply hold down ctrl/cmd + shift prior to selecting and manipulating a GameObject’s position. As you drag, the target surface to snap to updates as you hover different GameObjects.

3D
#34

If you need help aligning GameObject with vertex precision or to a grid, you need to use Vertex Snapping. To pull this off, select the Translate Tool, hold down the v key, hover the desired vertex of the GameObject in focus, then click and drag. As you drag your GameObject, its position snaps to the hovered vertex of another GameObject. Snappy.

3D
#35

If you want to interpolate values over time in a succinct way, you can use Unity’s built-in Lerp (linear interpolation) methods. Numerous classes have this method or a variation of it. Some common examples are Color.Lerp, Vector2.Lerp, Vector3.Lerp, Mathf.LerpAngle, and Vector3.Slerp. Mmmm… Slerp.

scripting
#36

If you repeatedly find yourself editing values only to realize you were in PlayMode when doing so (and thus losing all your edits), raise your hand… actually don’t raise it. Instead use Edit > Preferences > Colors > Playmode Tint to have Unity automatically color-tint the editor interface so you’re visually reminded that you’re in PlayMode. Damn handy.

general
#37

To improve precision while moving a GameObject in a scene, you can hold down ctrl/cmd while dragging its Translate Gizmo. This enables the position of the GameObject you’re moving to snap in incremental units. Go to Edit > Snap Settings to customize.

3D
#38

Slo-mo your thing? One approach to a slow motion effect is to leverage Time.time in conjunction with Time.timeScale. For instance, you could Lerp or Tween the Time.timeScale value over a period of time to transition toward a “pause” or “freeze” state.

scripting
#39

Having the pixelated-app-icon blues? Fix 'em in two easy steps. First, select all the icon images at once from within the Project. Second, select Editor GUI and Legacy GUI from the Texture Type drop down in the Inspector. Done. You can learn more detail about why this happens over on Unity Answers.

2D
#40

In cases where you are doing a lot of operations on a field or property, you can instead use a local variable cache to get a 3x performance improvement. Get the details in Jackson Dunstan's C# Performance: Properties vs. Fields vs. Locals article.

scripting
#41

When using 3D physics with complex models it is often best to use Compound Colliders instead of a Mesh Collider. A complex mesh collider will likely have many more vertices than a combination of primitive colliders (BoxCollider, SphereCollider, or CapsuleCollider). Fewer vertices = fewer calculations = better performance.

3D
#42

Shortcuts are your friend. Use shift + spacebar after focusing your cursor in a specific window to toggle fullscreen. This is very useful when focused on the Scene view and toggling PlayMode.

general
#43

Having lights in your scene is computationally expensive. "But lighting looks so good," you say. Welcome to Lightmapping, the extremely efficient way to make scene objects look as if they are affected by lights without having lights in your scene.

general
#44

Want to restrict a GameObject's position to a specific boundary, say the width and height of the screen? Use Mathf.Clamp as the enforcer. Keep in mind he has many relatives such as WrapMode.ClampForever, InputField.ClampPos, Vector3.ClampMagnitude, and more.

scripting
#45

Do you keep getting errors in the Console and not know what they mean? Welcome to the C# Error Messages list. There is a list for UnityScript too, but I'm not going to link to it. Seriously, bite the bullet and learn C# instead, you'll be glad you did.

scripting
#46

So you like Lightmapping now (Tip #44) but you're not a fan of the "non-static objects" restriction right? You're S.O.L. Just kidding, check out your new best friend Light Probes.

general
#47

Want to do simple and accurate collision detection in Unity? Want to see how to do it in 25 seconds? Then the Unity Collision Detection in 25 Seconds article is for you.

general
#48

Having trouble expanding and collapsing large nested groups in the hierarchy? Use alt + left-arrow to collapse and alt + right-arrow to expand.

general
#49

Having unwanted hiccups in your game? Check out Wendelin Reich's C# Memory Management for Developers or Unity's Understanding Automatic Memory Management breakdown to learn how to manage memory and tame the Garbage Collector.

scripting
#50

If you use the public access modifier on MonoBehaviour fields just so you can edit them through the editor... STOP. Look into adopting the [SerializeField] attribute instead.

scripting
#51

If you use coroutines, then you should check @AngryAnt's short article Optimising coroutine yielding in C# to make sure you're not performing unneeded memory allocation. It's a simple fix if you're doing it wrong.

scripting
#52

Do you ever wish it was easier to identify overlapping objects in the Scene view? Simply click an object, then click the Icon Dropdown just to the left of the name in the Inspector. You didn't know this was a button uh? From here you can label it with a color or texture for better identification and organization within the Scene view. This tip is brought to you by Iestyn Lloyd's Tweet.

general
#53

When you cast objects, do you use prefix casting or as-casting? There are subtle benefits and potential performance gains depending on your choice. @jashan has the lowdown for you over at Unity Answers.

scripting
#54

If you are like me and have been using Photoshop virtually everyday for too many years to count, then you know how much of a habit the spacebar Hand Tool shortcut is. Unity has this tool too, but you click the further away and pinky-awkward Q key. Make things right in the world with Edit > Preferences > Keys > Tools/View.

general
#55

If you ever make Color edits from within the Inspector, take note of the eye dropper to the right of the color box. You can sample any on screen color with it, not just colors within the Unity editor. Now you can sample the colors from your Reddit EarthPorn with ease.

general
#56

It may seem weird at first, but it is totally normal to have multiple Cameras in a scene. By leveraging a camera's Clear Flags and Culling Mask properties you can ensure certain cameras only render certain layers. A common example is to have one camera render only UI and another render only your game/app. You can get creative too, put your thinking cap on.

general
#57

Ever heard of icon fonts? They are a super useful and popular approach to achieving scaleable and color independent icons in web development. Unity supports them too with some minor tweaking. Chris Sung has the lowdown in his Unity3D UI Typography: Font Awesome post. Please don't default to Font Awesome, buy or make your own.

UI
#58

As suggested by @AngryAnt in a Tweet with @trinketben, you can use a [Comment] attribute to provide visible in-editor notes about an Inspector property. In fact there are a lot of attributes that are useful. @liortal53 has a nice breakdown.

scripting
#59

Ever had the need to capture a screenshot during gameplay or while developing? Application.CaptureScreenshot is your friend.

scripting
#60

If MonoDevelop is a pain in the ass, then try Visual Studio or Sublime Text 3. @wpg_denny has a great article titled Using Sublime with Unity to get you up and running on Windows or Mac.

scripting
#61

Though it is often an ill-advised approach from a performance perspective, Reflection can be a very useful tool. During authoring time for example, Reflection can be used to log all the properties of a poorly documented class instance to better understand its interface. Brannon has a solid example of this on Stack Overflow, but don't forget to add your using System and using System.Reflection statements when using the snippet.

scripting
#62

When working with physics in Unity, don't forget to leverage layers and the collision matrix for an easy optimization win. Ricardo Aguiar has more in his Physics Best Practices article.

general
#63

Since iOS and Android can kill any app at will (to free up limited resources), it is wise to use OnApplicationPause when your game/app loses focus. This enables you a chance to save data that needs to persist between game/app sessions.

scripting
#64

JavaScript for the web (not Unity Script) has a console.log() method that can handle a variable amount of arguments. This is extremely handy as it replaces cumbersome typing with a comma separated list of variable length to print to the console. Lucky you, Teemu Ikonen has already created the Console.Log() script for C#.

scripting
#65

If you create a lot of strings at runtime, you may be able to benefit by storing said strings in a fixed array as opposed to creating new ones all the time. Don’t risk tempting the ever hungry Garbage Collector to cause frame rate jitter. Check @catlikecoding Frames Per Second tutorial for an example.

scripting
#66

If you do mobile Android dev and you need to store persistent data, then you need to check Supersegfault’s game dev blog. Specifically his Unity on Android Save Data Pitfall post so you're aware of the differences between internal and external storage.

scripting
#67

Ever felt that Unity classes were missing obviously helpful methods? Do something about it using Extension Methods. Josh Sutphin (aka @invicticide) details the implementation in Adding to Unity's Built-in Classes Using Extension Methods.

scripting
#68

When targeting iOS, is your framerate capped to 30fps? Use Application.targetFrameRate to get that 60fps. This can be used when targeting any platform btw. Be aware that different platforms, in addition to your game/app, can impact the target fps.

scripting
#69

Do you want to implement a cross platform approach for storing persistent data? Look no further than the post How to Save and Load Your Players' Progress in Unity by @ericdaily. Take note of the iOS requirement regarding "MONO_REFLECTION_SERIALIZER" in the comments.

scripting
#70

Do you ever wish PlayerPrefs.SetBool and PlayerPrefs.GetBool methods existed? If so, then check out this Unity forum thread to see how you can use PlayerPrefs.SetInt and PlayerPrefs.GetInt in combination with the ternary operator to create a succinct extension method that gets you what you want.

scripting
#71

When authoring for iOS and Android, do you wish PlayerSettings.bundleVersion was accessible at runtime? Thankfully @akaSurreal suggests a nice approach to accomplish this (and more) using Unity's BuildPipeline class. Check it out in this Unity forum thread.

scripting
#72

Ever need to read from and/or write to a file during runtime in your game or app? Thankfully, there are a set of classes in .NET to help you out. Additionally, Jackson Dunstan has some performance tips in his File I/O Performance Tips article. Dunstan, you're the man!

scripting
#73

Ever want to have finer control over a GameObject's component order in the Unity Editor? Luckily @kode80 has your back with this tweet. Download the tools on github.

scripting
#74

C# has built-in events, but Unity created the UnityEvent class anyway. To be fair, I'm sure they had their reasons. At the very least, they likely did so for cross-language compatibility and editor integration. Regardless, you should be aware of the performance implications. As always Jackson Dunstan has your back in Event Performance: C# vs. UnityEvent.

scripting
#75

When publishing to Android, do you wish you had finer control over Android's Navigation and Status Bar display styles? Well you're in luck because @zeh wrote ApplicationChrome.cs. Check out implementation details in his Unity tidbits post.

scripting
#76

Have you ever had the desire to visualize raycasts or helper lines while authoring in Unity? If so, check out Debug.DrawRay and Debug.DrawLine.

scripting
#77

Modeling by Numbers - An Introduction to Procedural Geometry by @jayelinda does a great job teaching how to create a Mesh at runtime. Procedural geometry opens up a lot of doors in terms of flexibility and model variation at runtime. Check it out.

scripting
#78

If you need or want the freedom to change the component order on your GameObject's with greater ease, then I also suggest (Tip #74) looking into XT Reorder by @xeleh.

scripting
#79

Are you creating an app with Unity that isn't supposed to be full screen? You can show the status bar easily on iOS, but Android's status and navigation bars are a different story. Thankfully, @yury_habets has the solution on GitHub with UnityShowAndroidStatusBar.

scripting
#80

When your game/app starts up do you need to guarantee that some scripts load before others? If so, make sure to check out the Script Execution Order Settings via Edit > Project Settings > Script Execution Order. This is handy for example when you want to ensure a few manager classes load first.

scripting
#81

Are you a big fan of animation? Same here. If you slave away editing keyframes though, you need to look into using a tweening engine. Not all animation styles will benefit, but you should know about them regardless. @Prime31's' ZestKit rocks!

scripting
#82

Want 10 Steps to get 10x Performance when scripting in Unity? Checkout out @SorenTrautner's' bit in Tools, Tricks and Technologies for Reaching Stutter Free 60 FPS in INSIDE.

scripting
#83

Making a 2D or 2.5D game? Want a badass camera system? Look no further than Pro Camera 2D by @lpfonseca.

2D
#84

If you are modifying one or more meshes at runtime, you're likely to get a performance increase by using double buffering. Check the Unity Mobile Optimizations page for a simple example.

3D
#85

Do you sometimes end up with too many fields in your MonoBehaviors? You may benefit from using a ScriptableObject as a reusable data table. @superpig has the lowdown in Overthrowing the MonoBehaviour Tyranny in a Glorious Scriptable Object Revolution.

scripting
#86

It would be cool if there was a simple way to bookmark and reset the Scene View to a previous viewing angle right? Thought so too, checkout Scene Shot Bookmarks, an open source custom editor solution.

scripting
#87

Do you ever have long running processing in your game/app that causes GameObjects or UI movement to be janky? You really need to check out Thread Ninja - Multithread Coroutine to keep motion smooth while doing heavy processing tasks.

scripting
#88

Use Unity UI? Ever place your UI off-screen? Make sure you actually disable your Canvases as Unity doesn't automatically cull UIs that are off-screen as you'd expect.

ui
#89

Do you use Animators on your UI? DON'T! Use a Tweening Engine instead. Check Ian Dundore of Unity's Squeezing Unity: Tips for raising performance talk for the low-down.

ui
#90

When troubleshooting an issue with a GameObject wouldn't it be cool if the Inspector revealed non-public properties for all its script components? Unity already has you covered. Simply click the Inspector's tab menu and toggle from Normal to Debug mode. Piece of cake.

general
#91

@rich_lloyd reminds us to check the Frame Debugger to help mitigate unwanted draw calls so you can increase your frame rate. Easy win.

general
#92

Ever wish you could easily manipulate 3D models right in the Unity editor? @ProBuilder3D has you more than covered with ProBuilder Advanced. There's a free version too. Just buy it, it's more than worth it.

3D
#93

Want to improve your speed, precision, and quality during level construction? Of course. Get ProGrids 2 and take scene construction to a whole new level. See what I did there?

3D
#94

Ever have the desire to spawn many 3D models to form a larger 3D model shape? Think fireworks like dragons. In Brackeys How many Rigidbodies can Unity support? YouTube video they show you how. OK, I'll tell you, simply spawn a 3D model at each vertex of another 3D model. Cool.

3D
#95

If you want to have a shadow render on a surface without the surface material itself showing then @_kzr's ShadowDrawer shader is for you.

scripting
#96

When working with 3D or 2D Physics in Unity, it's easy to forget that you can override the Default Physic Material. You can make the change via Edit > Project Settings > Physics (or Physics 2D) within the Physics Manager.

general
#97

When rolling a circle (Circle Collider 2D) or sphere (Sphere Collider) on a slanted surface, does the physics simulation seem slow and unrealistic? If so, you'll likely find a super simple fix by increasing RigidBody.maxAngularVelocity on the GameObject in question. I love simple fixes.

general
#98

You a fan of projectile motion? Same here. Check @Varaquilex's Projectile Motion Tutorial for Arrows and Missiles in Unity3D article to learn a bunch of great tips on how to pull off projectile motion yourself.

three-d
#99

Do you like that isometric camera look? It's super easy to make happen. First ensure your Camera's' Transform position, rotation, and scale are zero'd out. Then simply set the Rotation X to 30 and Rotation Y to 45. Lastly change the camera Projection setting from Perspective to Orthographic. Boom done.

three-d
#100

@LiamSorta reinforces a simple and impactful strategy for potentially massive performance gains. You know you want perf wins, yes you do. Long story short, not all your code needs to run at the FPS Update() interval. Check his Tweet for details.

scripting
#101

Want a streamable world in one click? Of course you do. Check out this Generating 2D and 3D Streamable Worlds in Unity article to learn how a custom editor script + Sectr by @ProcWorlds work in harmony.

scripting
#102

Ever create a new Script in the Editor via Add Component > New Script only to delete Unity's default Awake and Start definitions? You know you can customize the default Script Unity creates for you right?

scripting
#103