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