Mosaic - Asset Zoos
Visualise an Unreal content library as a spatial treemap in-level with accompanying stats. Each asset folder (nested or otherwise) is packed roughly into a coloured square for visibility, and once built, moves the camera to show you the space.
This tool is great for visually and spatially analysing assets (including static meshes, materials, textures and blueprints), and is useful across various disciplines. Usecases include:
- Creating actor palates, zoos or gyms,
- Assisting in automated or manual in scene performance or lighting tests,
- Assessing art cohesion for assets in scene,
- Locating orphaned assets for removal, consolidation or future use,
For more detailed workflows or use cases, see Examples.
Features
View-modes:
All view-modes visualise a given content folder/s as an in-level treemap: static meshes as themselves, materials on spheres, and textures on planes scaled to their pixel size.
Blueprints are supported, but will likely lead to visual problems in the layout process in most cases. This is due to bounding volumes on blueprints being un-knowable until spawned in.
- Asset Zoo - Blindly lays out every given asset in a folder tree.
- Orphan Zoo - Filters for assets that have no strong dependencies and are “safe” to delete.
- Spawn all zoos - Provides you with all views in the tool. Will later be expanded upon.
All view modes have a comprehensive settings dialog, allowing further fine-tuning per view.
- Clear zoos - Cleans up zoos spawned in the scene. Regenerating a zoo does this automatically.
Browse to asset tools:
Unreal has a single “Browse to asset” feature when selecting and right clicking on an asset in a scene. What this doesn’t do is allow browsing to a meshes’ assigned materials or textures. Traditionally this is done through the properties pane, but it’s a slow process, and doesn’t allow for browsing to multiple materials and textures in one go.
Several tools to allow you to select any number of scene assets and to browse to their used materials and textures:
- Materials - Browses to all materials used by the selected Static Mesh(es)
- Textures - Browses to all textures (used by the materials) used by the selected Static Mesh(es)
- Referencers - Browses to all things that use the static mesh such as Levels or Blueprints.
- Everything - A more comprehensive Browse to, that locates every material and texture used by the selected Static Mesh(es), including the mesh itself.
Project only modes restrict the search scope to /Game, preventing engine primitives or plugin content from also being searched for. Useful for project clean-up, and not selecting the engine primitives when selecting a zoo’s material or texture previews.
Requirements
- Unreal Engine 5.6, 5.7 or 5.8
- Built and verified against all three. Windows only - the label fonts are registered through a Windows API, and on macOS or Linux the tools run but fall back to Unreal’s own font.
- The Python Editor Script Plugin
- Automatically available in most UE5 versions.
Installation
From Fab, the Epic Games Launcher does it for you. Install Mosaic to an engine version and it lands as an engine plugin, not a project one:
Epic Games/UE_5.8/Engine/Plugins/Fab/
Mosaic/
Mosaic.uplugin
That means it is available to every project on that engine version, and there is nothing to copy per project. Restart the editor if it was already open.
By hand, if you would rather keep it with one project, drop the Mosaic folder into that project’s Plugins/ directory instead:
YourProject/
Content/
Plugins/
Mosaic/
Mosaic.uplugin
Either way there is nothing for you to build. Every tool in Mosaic is Python; the plugin carries one small editor module, which Fab ships already compiled.
Mosaic writes the handful of assets it generates into /Game/Mosaic when its own folder is read-only, which an engine install under Program Files normally is. Nothing is written outside your project.
Examples
Everything lives on a right-click. With nothing selected, right-click in the viewport for the view-modes; with something selected, the same menu carries the browse-to tools.
Right-click in scene > Mosaic - Asset Zoos > Asset Zoo
For best results, spawn view-modes in empty or near empty levels. This eliminates the risk of polluting active levels with zoos, and performance penalties from spawning in additional actors in a scene. Nothing a view-mode spawns is ever saved into your map, so closing the level throws the picture away.
A few things worth knowing before you start:
- point it at a folder, not the whole project, unless you mean it - you will be asked to confirm anything over 4,096 assets
- the editor stops responding while a big picture builds, because Unreal runs Python on the game thread. The progress bar can cancel it
- re-running a view-mode replaces its own picture and leaves other pictures alone, so two views can sit side by side and be compared
Walkthroughs
Short step-by-step workflows, written from the point of view of the person doing the job.
Building a lighting or performance gymLighting artist · Tech artist1 August 2026Turning a content folder into a permanent Unreal test level for lighting, profiling and scale reference.
Clearing dead assets out of a projectTech artist · Producer1 August 2026Auditing an Unreal project for unused content with Mosaic’s Orphan Zoo, and deleting it without breaking anything.
Finding every texture a mesh pulls inTech artist · Environment artist1 August 2026Tracing an Unreal asset through its materials to every texture it costs you, without clicking through the properties panel.
Judging art cohesion across a packEnvironment artist · Art director1 August 2026Laying a bought or delivered asset pack out flat in Unreal to see whether it sits alongside the rest of your game.
Settings
Launching a view-mode opens the settings dialog first. Generate (bottom right) saves your choices and runs; Cancel (bottom left) runs nothing. The top section is shared by every view-mode, and the section under it belongs to whichever one you launched.
Settings are saved in Config/MosaicSettings.json inside the plugin, and the dialog is the only thing that writes to it. If the plugin folder is read-only, settings fall back to <project>/Saved/Mosaic/.
Core
| Setting | Does |
|---|---|
| Packing algorithm | How assets are arranged inside each folder’s tile. Rows is the default: aligned, tightest on most folders, fast. Rows (simple) is aligned, loosest and fastest. Skyline is scattered and moderate on both. MaxRects is scattered and tight on wildly mixed sizes, but the slowest by a wide margin — 17 seconds on 4,700 assets |
| Transient actors | On by default, meaning the picture is never saved into your map. Turn it off to deliberately build a permanent gallery level |
| Warn above | Asks before drawing more than this many assets, since a big picture locks the editor while it builds. 0 never asks |
| Colour swatch | What the folder sheets are coloured with, shown in its own colours in the dialog. Arkode is the default and is four dark greys; Colourful is 12 hues; Muted is the same 12 as pale washes; Greyscale is 6 greys; Outline is flat white, a placeholder until edge materials arrive |
| Label font weight | Which weight of Montserrat the labels are drawn in, Thin through Black, or Unreal’s own font. Bold is the default |
| Text scale and padding | Size and spacing of the labels on each tile |
| Excluded folders / keywords | Folders and name fragments to leave out of every view-mode |
View-modes
| Setting | View-mode | Does |
|---|---|---|
| Root folders | both | Which folders to draw. Several at once, each becoming its own tile |
| Asset types | both | Which types to show - meshes, materials, textures, blueprints |
| Which assets to find | Orphan Zoo | Whether that means nothing references it, or nothing leads back to it from a level. See below |
| Follow soft references | Orphan Zoo | Counts soft references as use. On by default, and safer left on |
“Which assets to find” is the setting that changes the answer. An asset is only really in your game if a level ends up using it, and use is passed along this chain:
texture -> material -> static mesh -> blueprint -> level
Anything the chain does not carry all the way to a level is dead weight.
| Mode | Finds | Use it when |
|---|---|---|
| Unreferenced (default) | assets with nothing referencing them at all | you want the easy answer, one step back, nothing to reason about |
| Unused | assets that no level uses, directly or indirectly | you want the whole dead cluster at once: the mesh nobody placed, its materials, and their textures |
Both are safe to delete as a batch. Unreferenced peels off one layer per pass, so run it again after each round of deleting; unused gets there in one.
One catch in unused mode: only the types you tick have to prove themselves. An unticked type counts as a user and protects whatever it references, so unticking meshes will keep any material a mesh references, placed or not.
Unused was called “unreachable” before version 1.0. Settings files using the old name still work.
Scripting
Every view-mode can be run directly, taking the same values as the dialog and skipping it:
from mosaic import asset_zoo
asset_zoo.run(roots=["/Game/MyPack", "/Game/Props"], exclude_keywords=["_old"])from mosaic import orphan_zoo
orphan_zoo.run(roots=["/Game/MyPack"], mode="unused")Run from a commandlet or with -unattended, the size warning becomes a log line instead of a dialog and the run continues, so a build machine is never left waiting on a popup.
Modifications
To allow extensibility I’ve deliberately provided this tooling as a python script plugin. I’m more than happy for modifications to be made - see Licence for what that covers.
| File | Holds |
|---|---|
mosaic/renderer.py |
All the drawing: measuring assets, packing them into squares, spawning them, and every default colour and size |
mosaic/common.py |
Shared lookups - asset registry queries, dependency walks, file sizes, folder trees. Never loads an asset |
mosaic/asset_zoo.py, mosaic/orphan_zoo.py |
The view-modes. Each one decides what to show and works out its own numbers, then hands a plain dictionary to the renderer |
mosaic/navigator.py |
The browse-to tools |
mosaic/settings.py, settings_dialog.py |
The settings file and the dialog built from it |
A new view-mode is a new file: build the dictionary of folders and assets, then call renderer.render(). The renderer never decides what to show, and a view-mode never touches the level. asset_zoo.py is the shortest working example of the format, at about sixty lines.
Known limits
- The first run is slow
- Showing a material means putting it in a level, and Unreal builds its shaders the first time that happens. On a library nothing has placed before, that is most of them, so the first run can sit for a long time on assets that look like they have hung. Watch Preparing Shaders in the status bar. Later runs are much faster, because the results are cached.
- Very large asset counts
- Python is slow at scale. There are warnings and progress bars to watch it with, but size your root to the scope of your assessment.
- C++ and runtime references are invisible
- Anything referenced only from C++, or from a path built while the game runs, leaves no trace for Orphan Zoo to find. This matters most for blueprints, which are often spawned that way. Always let the editor’s own Delete dialog have the final word.
- Unsaved levels hold no references
- Save your maps before trusting an audit.
- Some materials cannot be shown honestly
- Decals, post-process, anything that moves its own vertices, foliage and water. Those get a “no preview” material rather than something misleading. The check reads the material graph and never the asset’s name.
- Mosaic builds its own content on first use
-
Three materials and a label font, into
/Game/Mosaicif its own folder is read-only. Nothing is pre-cooked, so there is no asset to break when you change engine version. - Labels are Montserrat, and rasterised once
- The typeface ships with the plugin and becomes a font asset the first time a weight is used, which takes about fifteen seconds per weight. Label font weight offers the whole family, Thin through Black, or Unreal’s own font. It defaults to Bold, because a label here is geometry lying flat in a scene and read from above, where a face cut for a page reads as grey rather than as text. The font is registered for the editor process only, so nothing is installed on your machine. macOS and Linux fall back to Unreal’s default font, which costs the styling and nothing else.
- Using your own typeface
-
Point
FONT_ASSETinmosaic/renderer.pyat it. It has to be an offline-cached Font - a runtime-cached one renders nothing at all.
Licence
© 2026 Joshua Ellis, Arkode Games. Your use of Mosaic is governed by the Fab Standard Licence you bought it under, which licenses plugins per seat.
In plain terms: change it as much as you like for your own projects, and share it inside your team up to the seats you hold. What you may not do is redistribute or resell it, modified or not.
Montserrat is bundled under the SIL Open Font License 1.1 and remains the property of the Montserrat Project Authors. The licence text ships with it, in Resources/Fonts/OFL.txt.
One file is modified: Montserrat_Bold.ttf has its internal family name changed from “Montserrat” to “Montserrat Bold”, so that Windows can tell it apart from the Regular weight and Mosaic can ask for it by name. No glyph is touched. Montserrat declares no Reserved Font Name, so this is permitted; the script that does it, and its reasoning, are in Resources/make_bold_family_name.py in the source repository.
Support and refunds
Something broken, or not behaving like this page says? Please raise it with me first. Most problems are quick to fix, and a bug report is the only way a one-person tool gets better.
Include your Unreal version, which tool you ran, what you expected, and anything the Output Log said - Window > Output Log, filter for Mosaic.
arkodegames.socials@gmail.com
I build this around a full-time job, so expect a reply in a few days rather than a few hours.
Refunds go through Fab under Epic’s own policy and I won’t argue one. But if the tool isn’t doing what you bought it for, a message usually ends in a fix, and costs you less than starting again with something else.

