Guide
Game asset pipeline explained
Harbor Arena’s Season 1 PC build shipped with 14 GB of mostly uncompressed 4K textures, duplicate weapon meshes, and no automated import rules. Cold loads exceeded 38 minutes on a mid-range SSD; artists re-exported the same rifle twelve times because nobody owned the folder structure. Season 2 replaced ad-hoc drops with a game asset pipeline: typed export presets from Blender and Substance, engine-side import profiles, platform texture compression, derived LOD chains, addressable bundles per map, and CI gates that fail builds when poly or memory budgets break. Load time fell to under four minutes and patch sizes shrank by 70%. A game asset pipeline is the end-to-end path from authorable source files (meshes, textures, audio, animations) to runtime-ready content your engine streams efficiently on each target platform. This guide covers source vs cooked assets, import conventions, mesh and texture processing, bundling and streaming, version control for binaries, automated validation, a Harbor Arena refactor worked example, an approach decision table, common pitfalls, and a production checklist.
What an asset pipeline is (and is not)
An asset pipeline is not a single script or a folder on a network drive. It is the contract between art, design, and engineering about how content enters the game, transforms, and ships. The pipeline answers: Where do artists export? What import settings apply? How are duplicates detected? What runs in CI before a build merges?
Without that contract, every feature team invents its own naming scheme, texture sizes drift upward, and programmers hard-code paths to files that move during crunch. The pipeline’s job is to make the right thing easy and the wrong thing visible early — ideally as a failed pull request, not a frame-rate cliff in QA.
Source assets vs cooked runtime assets
Source assets live in DCC tools (Blender, Maya, Substance Painter, Photoshop) or audio workstations. They are large, editable, and often stored in Git LFS, Perforce, or a dedicated art depot. Cooked assets are what the player downloads: compressed textures in ASTC or BC7, simplified meshes with generated tangents, baked animation clips, and platform-specific audio codecs. The pipeline’s transform step is deterministic: same source + same import profile = same cooked output, so builds are reproducible.
Folder structure, naming and export presets
Consistency beats cleverness. A typical layout separates Source/
(artist exports) from Content/ (engine imports) and
Generated/ (CI-built bundles). Names should encode type and variant:
WP_RifleMk2_LOD0.fbx, T_CharacterBody_BC_2K.png
(BC = base color). Suffixes for texture channels — BC, NRM, ORM (occlusion/
roughness/metallic packed) — let import rules auto-assign compression and
sRGB vs linear color space.
Export presets in DCC tools enforce scale (1 unit = 1 meter), forward axis (usually -Z forward, Y up for engines), triangulation, and applied transforms. Artists should never manually fix axis flips in-engine; that belongs in the preset. Document one “golden” export for characters, props, and environment modules, and version those preset files in source control.
Metadata sidecars (JSON or YAML next to exports) can declare intended poly
budget, material slot count, and which gameplay tags attach on import. Harbor
Arena attached Weapon and Cosmetic tags from sidecars
so designers did not re-tag hundreds of prefabs by hand.
Texture processing and platform formats
Raw PNGs are authoring formats, not shipping formats. The pipeline should resize, generate mipmaps, and compress per platform: BC7 for high-quality color on PC and Xbox, ASTC block sizes for mobile and Switch, BC5 for normal maps. Albedo textures use sRGB; data maps (normal, roughness, metallic) stay linear.
Establish resolution tiers tied to asset class: hero characters 2K, props 1K, distant environment atlases 512–1K. Upscale requests should require tech-art approval with a memory budget impact note. Atlasing static props in a biome cuts draw calls; the pipeline can batch imports nightly and emit combined sheets with updated UV layouts.
Alpha handling matters: cutout foliage needs appropriate mip bias or alpha-to-coverage; soft particles may stay uncompressed on a separate atlas. Mip streaming (loading higher mips as the camera approaches) pairs with LOD so distant objects do not reserve 4K memory they never display.
Mesh import: LOD, collision and materials
On import, meshes should auto-generate or attach LOD chains. High-poly sculpts can pass through an automated decimation step with silhouette preservation; hero assets may keep hand-authored LOD1–LOD3. Collision meshes are separate simplified hulls — never reuse render LOD0 for physics unless you enjoy invisible walls from ornate geometry.
Tangents and normals must be consistent with your
shader
workflow (MikkTSpace is the common standard). Material slots in the FBX should map
1:1 to engine material instances; slot names like M_Body and
M_VisorGlass prevent artists from rebuilding materials per prefab.
Skeletal meshes need bone count limits, root motion flags, and retargeting profiles for shared animation rigs. Static meshes benefit from lightmap UV generation rules (second UV channel, no overlapping islands above a texel density threshold). Procedural content from procedural generators should still pass through the same import profiles so runtime and authored assets share budgets.
Bundling, addressables and streaming
Monolithic builds that load everything at startup do not scale. Modern pipelines split content into addressable bundles (Unity Addressables, Unreal pak chunks, Godot resource packs) keyed by map, season, or cosmetic tier. A manifest lists bundle hashes so the launcher downloads only deltas.
Design bundle boundaries around player flow: boot essentials (UI, core weapons), per-map geometry and audio, optional cosmetic packs. Shared dependencies (common shaders, font atlases) live in a base chunk referenced by others to avoid duplication. Label assets with memory estimates so designers see bundle weight before locking a season pass.
Runtime pooling complements streaming: once bundles load, reuse instances via object pooling instead of instantiate-destroy loops that fragment memory. The pipeline should tag which prefabs are poolable and their warmup counts for first-match hitch avoidance.
Version control for binary content
Git without LFS is painful for games; Perforce and Plastic SCM remain common for
large teams because file locking and binary diff tools are first-class. Smaller
teams often use Git LFS with strict pointer rules and art-branch policies:
never commit cooked Library/ or DerivedDataCache/
folders.
Branching strategy should separate work-in-progress art from
integration-ready assets. A tech-artist merge gate runs import
locally or in CI before assets land on main. Store import settings as text
(Unity .meta, Unreal .uasset sidecars) so diffs show
when someone changed compression or LOD distances.
CI validation and budget gates
Automated checks catch problems humans miss at 2 a.m. Useful gates include: maximum triangle count per asset class, texture dimension ceilings, missing reference scans, duplicate GUID detection, shader variant explosion counts, and audio loudness normalization (LUFS targets).
Run a headless import on every PR that touches
Content/. Fail the build if any asset exceeds budget or references a
moved file. Nightly full builds can produce a memory report per map: textured
geometry, animation, audio, UI atlases. Trend those numbers; regressions should
page someone before players do.
Integrate with playtest telemetry when possible: if a map’s 95th-percentile load time spikes after an art drop, tie the report back to bundle hashes added that week.
Worked example: Harbor Arena Season 2 pipeline
Harbor Arena’s refactor started with an audit: 2,400 unique textures, 38% duplicates
by hash, average prop at 18K tris (target 8K). Tech art introduced three export
presets (character, weapon, environment), moved sources to
Source/Harbor/, and added import profiles that auto-compressed to
BC7/ASTC per build target.
LOD0–LOD2 generated on import for weapons and cover pieces; collision hulls
authored once in Blender and merged automatically. Maps split into
Arena_Core, Map_Docks, and Cosmetics_S2
addressable groups. CI failed PRs when any weapon exceeded 12K tris or any
non-hero texture exceeded 2K without approval label.
Results after six weeks: install size 14 GB to 4.2 GB, cold load 38 min to 3 min 40 sec, patch for a new cosmetic skin 800 MB to 120 MB. Artists spent less time re-fixing imports and more time on silhouette reads that matter in combat readability.
Approach decision table
| Team / context | Recommended pipeline shape | Watch for |
|---|---|---|
| Solo / jam | Minimal presets, manual import, no CI | Scope creep on texture sizes; document conventions anyway |
| Small team, one platform | Git LFS, import profiles, local budget script | Duplicate assets; missing meta files in commits |
| Multi-platform live service | Addressables, per-platform cooks, full CI gates | Bundle coupling; shader variant blowups |
| Large co-dev / outsourcing | Perforce locks, sidecar metadata, automated receipt reports | Axis/scale mismatches; unauthorized LOD skips |
| Procedural-heavy game | Shared import profiles for generated + authored assets | Runtime gen bypassing memory budgets |
Common pitfalls
- Shipping source PNGs. Uncompressed textures dominate install size and RAM; always cook per platform.
- One-off import fixes. Manual per-asset settings do not scale; encode rules in profiles.
- Collision from render meshes. ornate geometry creates unfair hitches and stuck players.
- Monolithic loads. Loading all seasons at boot punishes new players and patch cadence.
- No duplicate detection. Ten copies of the same rock texture waste memory silently.
- Ignoring shader variants. Unique materials per prop explode compile times and batch breaks.
- Art branches without gates. Broken references land on main and block the whole team.
Production checklist
- Document folder layout, naming suffixes, and scale/axis conventions.
- Publish versioned DCC export presets for each asset class.
- Define texture resolution tiers and platform compression tables.
- Configure engine import profiles (materials, LOD, tangents, collision).
- Split addressable bundles by player flow and patch boundaries.
- Set up Git LFS or Perforce with ignore rules for cooked caches.
- Add CI headless import with poly, texture, and reference checks.
- Track install size, load time, and memory per map in nightly reports.
- Train artists on receipt reports; fix at export, not in crisis.
- Re-audit budgets each milestone or season, not only at gold.
Key takeaways
- Pipelines are contracts — conventions beat heroics.
- Cook for the platform — source art is not ship art.
- Derive LOD and collision — do not ship sculpts to GPU and physics.
- Bundle for streaming — players download flows, not folders.
- Automate budgets — CI failures are cheaper than live patches.
Related reading
- Game LOD explained — mesh and texture fidelity tiers at distance
- Game shaders explained — material workflows that import rules must match
- Unity fundamentals explained — prefabs, import settings, and build targets
- Game object pooling explained — runtime reuse after bundles load