
uasset-to-glb User Guide
Convert cooked Unreal Engine projects into GLB files with PBR materials correctly wired. Works with UE4.20 through UE5.4. macOS arm64 binary ships inside the package — no .NET or Unreal install required to run.
Installation
Verify installation:
The native parser (bin/uasset-export) is a self-contained macOS arm64 binary bundled in the package. It spawns as a subprocess when you run a conversion.
Quick Start
Output:
Each GLB appears in ./out as its mesh finishes — you don't wait for the whole project.
Prerequisite: Cook Your Project First
This is the step that makes or breaks the tool. Read it carefully.
Unreal Engine stores mesh data two different ways:
- Uncooked (what's in your project's
Content/folder): geometry lives in editor-onlySourceModels. Our parser cannot read this. - Cooked (what ships in a packaged build): geometry lives in
RenderData. Our parser reads this fine.
If you point the tool at a raw project you'll get no RenderData — asset is uncooked for every mesh, and zero GLBs.
Cook from the Unreal Editor (GUI)
- Open
YourProject.uprojectin UE Editor - File → Cook Content for Mac (or Windows/Linux — any target works, we just need the cooked binary format)
- Wait a few minutes — progress shows in the bottom-right corner
- Cooked output lands at
YourProject/Saved/Cooked/<Platform>/YourProject/Content/
Cook from the command line
Adjust UE_4.27 to your installed engine version.
Verify the cook worked
You should see the same folder hierarchy as your project's Content/ directory. That's what you pass to uasset-to-glb convert.
Converting Assets
Core flags
| Flag | Purpose | Example |
|---|---|---|
-o, --output <dir> | Required. Where GLB files land. | -o ./out |
--ue <version> | Engine version. Auto-detected from .uproject if present. | --ue 4.27 |
--types <list> | Comma-separated asset types to export. | --types StaticMesh,SkeletalMesh |
--filter <substr> | Only export assets whose package path contains this substring. | --filter Characters |
--compress <fmt> | Texture compression inside the GLB. | --compress webp |
--meshopt | Apply meshopt geometry compression. | --meshopt |
--keep-staging | Keep the intermediate glTF + PNGs for debugging. | --keep-staging |
Supported asset types
StaticMesh— environment props, weapons, static geometrySkeletalMesh— characters and rigged meshes with bone hierarchiesAnimSequence— bone animations (experimental, some UE4.27 anims fail in CUE4Parse)Texture2D— loose texture export to PNGMaterial/MaterialInstanceConstant— material parameter extraction
Default (no --types) exports everything that's convertible.
Listing Assets (Dry Run)
Preview what would be exported without running the parser:
Output:
Combine with --filter to narrow:
Material Mapping
Unreal materials are arbitrary HLSL node graphs. We don't reconstruct the graph — we map the material instance's texture parameters to glTF's PBR channels using two passes:
Pass 1 — parameter name
| Unreal parameter name | glTF channel |
|---|---|
BaseColor, Diffuse, Albedo, ColorMap | baseColorTexture |
Normal, NormalMap | normalTexture |
ORM, PackedMRA, MRA, MRAO, ARM | occlusionTexture + metallicRoughnessTexture (packed, same image — glTF convention) |
RAM (Unreal's R=Rough/G=AO/B=Metal) | Swizzled to glTF ORM (R=AO/G=Rough/B=Metal) at export time |
Roughness, Metallic, AO (separate) | Combined into a synthesized ORM PNG |
Emissive, Emission, EmissiveColor | emissiveTexture |
Pass 2 — filename suffix fallback
For parameters with generic names like Texture01, we fall back to the texture asset's filename suffix:
_BC/_D/_Diffuse → color, _N/_Normal → normal, _ORM/_MRA → packed, _R/_M/_AO → separate, _E/_Emissive → emissive.
Scalars
Roughness and Metallic scalar parameters become roughnessFactor and metallicFactor in the glTF material.
What won't work perfectly
Hair, eye, cloth, and subsurface shaders use custom graph logic we don't reproduce. Expect ~80% of standard opaque surfaces to land correctly. The rest need manual fix-up — check _report.json (see next section).
Output Structure
One GLB per mesh, mirroring the project's package path. Each GLB is a single self-contained file — all textures are embedded.
_report.json
Scan the materialWarnings for assets that need manual wiring after export.
Examples
Convert only characters, compress textures to webp
Get everything packed as small as possible
Debug a single problematic asset
The path to the temp staging directory prints at the end. Open the raw glTF + PNGs there to see what the extractor produced before post-processing.
CI/CD: convert fresh cooks on every build
Troubleshooting
no RenderData — asset is uncooked
Your project hasn't been cooked yet. See the Prerequisite: Cook Your Project First section above. Uncooked .uasset files store geometry in editor-only data blocks we can't read.
Meshes render "shiny black" in my viewer
This means the base color texture is being multiplied by all-zero per-vertex colors. Our post-processor strips those out automatically — if you're still seeing it, you have an older local build. Reinstall:
Object reference not set to an instance of an object on AnimSequences
Known CUE4Parse limitation with some UE4.27 animation packages. Static + skeletal meshes still export correctly. The warning is non-fatal.
Missing textures / unmapped material parameters
Check out/_report.json for materialWarnings. Each entry tells you which parameter on which material wasn't recognized. Often the fix is: rename the texture file with a standard suffix (_BC, _N, _ORM), then re-export.
Encrypted .pak files or IoStore builds
Not supported in this version. The tool reads loose cooked .uasset files, not .pak bundles. If you only have paks, unpack them first with UnrealPak or FModel.
How It Works
The C# host wraps CUE4Parse (the same library that powers FModel). The TypeScript CLI spawns it, reads READY: <json> lines from stderr as each mesh finishes, and post-processes each one immediately so GLBs land in ./out incrementally rather than all at the end.
Source
Open source under MIT. Contributions welcome.