{"id":14960540,"url":"https://github.com/joanstinson/unityuioptimizationtool","last_synced_at":"2025-07-04T23:41:22.320Z","repository":{"id":62863655,"uuid":"562227165","full_name":"JoanStinson/UnityUIOptimizationTool","owner":"JoanStinson","description":"A Unity Editor tool that automatically optimizes selected UI game objects (including Prefabs) to save you time.","archived":false,"fork":false,"pushed_at":"2022-11-26T15:16:50.000Z","size":979,"stargazers_count":148,"open_issues_count":0,"forks_count":17,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-07T01:53:06.542Z","etag":null,"topics":["csharp","unity-optimization","unity-prefabs","unity-ui","unity3d","unity3d-editor","unity3d-plugin"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JoanStinson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-11-05T17:32:29.000Z","updated_at":"2025-04-03T04:03:07.000Z","dependencies_parsed_at":"2022-11-08T05:02:52.683Z","dependency_job_id":null,"html_url":"https://github.com/JoanStinson/UnityUIOptimizationTool","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoanStinson%2FUnityUIOptimizationTool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoanStinson%2FUnityUIOptimizationTool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoanStinson%2FUnityUIOptimizationTool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoanStinson%2FUnityUIOptimizationTool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JoanStinson","download_url":"https://codeload.github.com/JoanStinson/UnityUIOptimizationTool/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252038141,"owners_count":21684631,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","unity-optimization","unity-prefabs","unity-ui","unity3d","unity3d-editor","unity3d-plugin"],"created_at":"2024-09-24T13:22:29.086Z","updated_at":"2025-05-02T12:31:20.436Z","avatar_url":"https://github.com/JoanStinson.png","language":"C#","readme":"# Unity UI Optimization Tool\nA Unity Editor tool that automatically optimizes selected UI game objects (including Prefabs) to save you time.\n\n\u003cp align=\"center\"\u003e\n  \u003ca\u003e\n    \u003cimg alt=\"Made With Unity\" src=\"https://img.shields.io/badge/made%20with-Unity-57b9d3.svg?logo=Unity\"\u003e\n  \u003c/a\u003e\n  \u003ca\u003e\n    \u003cimg alt=\"License\" src=\"https://img.shields.io/github/license/JoanStinson/UnityUIOptimizationTool?logo=github\"\u003e\n  \u003c/a\u003e\n  \u003ca\u003e\n    \u003cimg alt=\"Last Commit\" src=\"https://img.shields.io/github/last-commit/JoanStinson/UnityUIOptimizationTool?logo=Mapbox\u0026color=orange\"\u003e\n  \u003c/a\u003e\n  \u003ca\u003e\n    \u003cimg alt=\"Repo Size\" src=\"https://img.shields.io/github/repo-size/JoanStinson/UnityUIOptimizationTool?logo=VirtualBox\"\u003e\n  \u003c/a\u003e\n  \u003ca\u003e\n    \u003cimg alt=\"Downloads\" src=\"https://img.shields.io/github/downloads/JoanStinson/UnityUIOptimizationTool/total?color=brightgreen\"\u003e\n  \u003c/a\u003e\n  \u003ca\u003e\n    \u003cimg alt=\"Last Release\" src=\"https://img.shields.io/github/v/release/JoanStinson/UnityUIOptimizationTool?include_prereleases\u0026logo=Dropbox\u0026color=yellow\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/preview.gif\"\u003e\n\u003c/p\u003e\n\n## 🖥️ How It Works\nFor starters, import the package located in the [Releases](https://github.com/JoanStinson/UnityUIOptimizationTool/releases) section into your project.\n\nNow then, inside the Unity Editor, select any number of \u003ci\u003egame objects\u003c/i\u003e anywhere: in the scene's \u003ci\u003eHierarchy\u003c/i\u003e, in the \u003ci\u003eProject\u003c/i\u003e window or in \u003ci\u003ePrefab Edit Mode\u003c/i\u003e.\n\nNext, go to \u003ci\u003eTools \u003e JGM \u003e Optimize Selected UI GameObjects\u003c/i\u003e and press it.\n\nIt will automatically optimize the selected \u003ci\u003egame objects\u003c/i\u003e (including \u003ci\u003ePrefabs\u003c/i\u003e) with the supported techniques.\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/tool usage.png\"\u003e\n\u003c/p\u003e\n\n## 🛠️ Unity UI Optimization Techniques\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Using more Canvases\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Using more Canvases\n   Every time a single UI element inside a Canvas changes (e.g. change 1 Text or Image), the whole Canvas has to generate the meshes and draw them all\nover again (very costly).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Separating objects between static and dynamic Canvases\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Separating objects between static and dynamic Canvases\n   * \u003cb\u003eStatic Canvas\u003c/b\u003e: contains UI elements that are \u003cb\u003enever\u003c/b\u003e going to \u003cb\u003echange\u003c/b\u003e; good examples of these are background images, labels, and so on.\n   * \u003cb\u003eIncidental Dynamic Canvas\u003c/b\u003e: contains UI elements that only \u003cb\u003echange in response\u003c/b\u003e to something, such as a UI button press or hover action.\n   * \u003cb\u003eContinuous Dynamic Canvas\u003c/b\u003e: contains UI elements that \u003cb\u003echange regularly\u003c/b\u003e, such as animated elements.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Disabling Raycast Target for non-interactive elements\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Disabling Raycast Target for non-interactive elements\n   For all \u003cb\u003e\u003ci\u003eImage\u003c/i\u003e\u003c/b\u003e components that are not part of a \u003cb\u003e\u003ci\u003eButton\u003c/i\u003e\u003c/b\u003e, disable the \u003cb\u003e\u003ci\u003eRaycast Target\u003c/i\u003e\u003c/b\u003e (basically disable it in all images except for buttons).\n   \u003cbr\u003e\u003cbr\u003e\n   Each time there is a UI input (click, tap, scroll, etc.) Unity's \u003ci\u003eGraphicsRaycaster\u003c/i\u003e iterates over all the \u003ci\u003eRaycast Targets\u003c/i\u003e in the scene, so the less we have the more processing we save.\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/disable raycast target.PNG\"\u003e\n   \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Hiding UI elements by disabling the parent Canvas component\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Hiding UI elements by disabling the parent Canvas component\n   To avoid the \u003ci\u003eCanvas\u003c/i\u003e regeneration, it's good habit to split the UI into different \u003ci\u003eCanvases\u003c/i\u003e, and instead of disabling a \u003ci\u003eLayoutGroup\u003c/i\u003e, disable an entire \u003ci\u003eCanvas\u003c/i\u003e.\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/hide canvas.PNG\"\u003e\n   \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Avoiding Animator components\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Avoiding Animator components\n   Unity's Animator components are meant for 3D avatar animations primarily. Using it for UI elements causes extra processing.\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/animator.PNG\"\u003e\n   \u003c/p\u003e\n   Instead, the best approach is to use a custom tweening tool such as DOTween.\u003cbr\u003e\u003cbr\u003e\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/dotween.PNG\"\u003e\n   \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Explicitly defining the event camera for World Space Canvases\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Explicitly defining the event camera for World Space Canvases\n   Always set the Event \u003ci\u003eCamera\u003c/i\u003e in a \u003ci\u003eWorld Space Canvas\u003c/i\u003e as if there is no \u003ci\u003eCamera\u003c/i\u003e assigned, it will call \u003ci\u003eFindObjectWithTag(\"Main Camera\")\u003c/i\u003e on every single frame! ☠️\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/world space canvas.PNG\"\u003e\n   \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Don't use alpha to hide UI elements\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Don't use alpha to hide UI elements\n   Even though the \u003ci\u003eImage\u003c/i\u003e's color property is set to \u003ci\u003ealpha\u003c/i\u003e 0, it will still cause a \u003ci\u003edraw call\u003c/i\u003e.\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/alpha.PNG\"\u003e\n   \u003c/p\u003e\n   Instead, disable the \u003ci\u003egame object\u003c/i\u003e itself, or set the \u003ci\u003ealpha\u003c/i\u003e of a \u003ci\u003eCanvas Group\u003c/i\u003e to 0. This will prevent any \u003ci\u003edraw calls\u003c/i\u003e from this object and its childs (0 \u003ci\u003edraw calls\u003c/i\u003e).\u003cbr\u003e\u003cbr\u003e\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/splash.PNG\"\u003e\n   \u003c/p\u003e\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/canvas group.PNG\"\u003e\n   \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Make sure to use a RectMask2D\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Make sure to use a RectMask2D\n   Like this, any element that is not inside the \u003ci\u003eScroll Rect\u003c/i\u003e, will not be drawn saving plenty of \u003ci\u003edraw calls\u003c/i\u003e.\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/rectmask.PNG\"\u003e\n   \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Disable Pixel Perfect for ScrollRects\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Disable Pixel Perfect for ScrollRects\n   \u003ci\u003ePixel Perfect\u003c/i\u003e makes UI elements appear sharper, but since in a \u003ci\u003eScroll Rect\u003c/i\u003e there's going to be movement, we won't notice it and we'll save a lot of processing.\n   \u003cbr\u003e\u003cbr\u003e\n   The \u003ci\u003eScroll Rect\u003c/i\u003e should be on a separate \u003ci\u003eCanvas\u003c/i\u003e with this setting off and other UI elements appearing in the same screen, would be in another \u003ci\u003eCanvas\u003c/i\u003e with this setting on.\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/pixel perfect.PNG\"\u003e\n   \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Manually stop ScrollRect motion\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Manually stop ScrollRect motion\n   We can use \u003ci\u003eScrollRect.StopMovement()\u003c/i\u003e to stop the motion once the \u003ci\u003eScrollRect.velocity\u003c/i\u003e is below a certain threshold to reduce regeneration frequency.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Using empty UIText elements for full-screen interaction\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Using empty UIText elements for full-screen interaction\n   For a \u003ci\u003eButton\u003c/i\u003e that's going to be interactable full-screen, for the \u003ci\u003eButton's Target Graphic\u003c/i\u003e, don't use an \u003ci\u003eImage\u003c/i\u003e that fills the whole screen and has a \u003ci\u003ecolor alpha\u003c/i\u003e set to 0 (as transparency breaks batching processes).\n   \u003cbr\u003e\u003cbr\u003e\n   Instead, for the \u003ci\u003eButton's Target Graphic\u003c/i\u003e, use a \u003ci\u003eText\u003c/i\u003e with no \u003ci\u003eFont\u003c/i\u003e or \u003ci\u003eText\u003c/i\u003e defined.\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/empty ui text for all screen.PNG\"\u003e\n   \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Reduce Game Objects inside Prefabs\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Reduce Game Objects inside Prefabs\n   Wherever possible, try to reduce the number of \u003ci\u003egame objects\u003c/i\u003e inside of a \u003ci\u003ePrefab\u003c/i\u003e, maybe in some occasions it's possible to merge 3 \u003ci\u003egame objects\u003c/i\u003e with \u003ci\u003eImages\u003c/i\u003e into 1 single \u003ci\u003egame object\u003c/i\u003e with 1 \u003ci\u003eImage\u003c/i\u003e.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Avoid Layout Groups when possible\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Avoid Layout Groups when possible\n   Whenever possible, try to avoid using \u003ci\u003eLayout Groups\u003c/i\u003e, specially nested \u003ci\u003eLayout Groups\u003c/i\u003e, as it's very costly performance wise.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Adjust texture compression formats\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Adjust texture compression formats\n   Always adjust texture compression formats for your UI Sprite assets, to reduce memory footprint. Available compression types can be found [here](https://docs.unity3d.com/Manual/class-TextureImporterOverride.html).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Use Sprite Atlases always\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Use Sprite Atlases always\n   Use [Sprite Atlases](https://docs.unity3d.com/Manual/class-SpriteAtlas.html) for grouping single Sprites into one big texture to reduce the number of \u003ci\u003edraw calls\u003c/i\u003e.\n   \u003cp align=\"center\"\u003e\n      \u003cimg src=\"https://github.com/JoanStinson/UnityUIOptimizationTool/blob/main/Images/sprite atlas.PNG\"\u003e\n   \u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\u003cb\u003e🛠️ Take order into account to prevent Batch Breaks\u003c/b\u003e\u003c/summary\u003e\n  \n   ### Take order into account to prevent Batch Breaks\n   Order in UI hierarchies matters. If you have in a hierarchy this order: \n   * SpriteA1\n   * SpriteB1\n   * SpriteA2\n   * SpriteB2\n   * SpriteA3\n   * SpriteB3 \n   \n   (meaning 'A' Sprites are from a specific Sprite Atlas and 'B' Sprite are from another one) it will issue 6 \u003ci\u003edraw calls\u003c/i\u003e because the batches are breaking as all Sprites from one Atlas are not consecutively in line. To prevent this Batch Break, order them as in: \n   * SpriteA1\n   * SpriteA2\n   * SpriteA3\n   * SpriteB1\n   * SpriteB2\n   * SpriteB3\n   \n   As a result, this will only issue 2 \u003ci\u003edraw calls\u003c/i\u003e.\n\u003c/details\u003e\n\n## 🧰 Tool Supported Techniques\n✅ \u003cb\u003eDisabling Raycast Target for non-interactive elements\u003c/b\u003e\u003cbr\u003e\n✅ \u003cb\u003eAvoiding Animator components\u003c/b\u003e\u003cbr\u003e\n✅ \u003cb\u003eMake sure to use a RectMask2D\u003c/b\u003e\u003cbr\u003e\n✅ \u003cb\u003eDisable Pixel Perfect for ScrollRects\u003c/b\u003e\n    \n## 📚 Bibliography\n* [Unite '17 Seoul - Tips and Tricks for Optimising Unity UI](https://www.youtube.com/watch?v=eH-PdFKgctE)\n* [Unite Europe 2017 - Squeezing Unity: Tips for Raising Performance](https://youtu.be/_wxitgdx-UI?t=1426)\n* [Unity Game Optimization](https://www.amazon.com/Unity-Game-Optimization-Enhance-performance/dp/1838556516)\n* [Optimizing Unity UI](https://learn.unity.com/tutorial/optimizing-unity-ui)\n* [Optimization Tips for Unity UI](https://unity.com/how-to/unity-ui-optimization-tips#avoid-expensive-ui-elements)\n* [Interactive Guide: Cross-Platform UI](https://assetstore.unity.com/packages/templates/tutorials/interactive-guide-cross-platform-ui-208063#description)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoanstinson%2Funityuioptimizationtool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoanstinson%2Funityuioptimizationtool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoanstinson%2Funityuioptimizationtool/lists"}