Skip to content

Latest commit

 

History

History
144 lines (102 loc) · 6.33 KB

File metadata and controls

144 lines (102 loc) · 6.33 KB

Typemap Guide

Perforce typemaps control how files are stored, compressed, and locked. Getting this right is critical for game development — the wrong typemap can waste terabytes of storage, corrupt binary assets, or cause merge conflicts on unmergeable files.

This guide explains every modifier we use and why.

Quick Reference

Modifier What it does When to use
+l Exclusive lock (only one user can check out) Binary assets that can't be merged: .uasset, .fbx, .psd
+F Store as-is, no server compression Pre-compressed files: .png, .jpg, .mp3, .mp4
+S Limit stored revisions (+S2 = keep 2) Large binaries that rarely need history: .exe, .dll
+w Always writable on client Engine-generated files: .csproj, .sln
+x Set executable bit Scripts: .sh, .bat
+C Server-compressed (default for binary) Uncompressed binary: .wav, .fbx

Modifiers combine: binary+lF means "binary, exclusive lock, no recompression."

Why Exclusive Locks (+l) Matter

Binary files (textures, 3D models, maps, audio) cannot be merged. If two artists edit the same .uasset or .fbx simultaneously, one person's work is lost. The +l modifier prevents this by allowing only one checkout at a time.

Rule of thumb: If a human can't resolve a merge conflict in the file, it needs +l.

Files that need +l:

  • Engine assets: .uasset, .umap, .unity, .prefab
  • 3D models: .fbx, .blend, .max, .ma, .obj
  • Textures: .psd, .tga, .png, .jpg (also +F)
  • Audio: .wav, .mp3, .ogg (compressed ones also +F)
  • Video: .mp4, .mov, .avi

Files that do NOT need +l:

  • Source code: .cpp, .h, .cs (text, mergeable)
  • Config: .ini, .json, .xml (text, mergeable)
  • Shaders: .hlsl, .usf, .shader (text, mergeable)
  • Unity .meta files (YAML text, mergeable)

Why No-Recompression (+F) Matters

By default, Perforce compresses files on the server (+C). For files that are already compressed (PNG, JPG, MP3, ZIP), this wastes CPU for zero benefit — you can't meaningfully compress a PNG further.

+F tells the server to store the file as-is, skipping compression. Combined with +l:

binary+lF = exclusive lock + no recompression. Used for: .png, .jpg, .mp3, .ogg, .mp4, .zip.

binary+l (no +F) = exclusive lock + server-compressed. Used for: .wav, .fbx, .blend, .psd — uncompressed formats that benefit from server compression.

Storage impact example:

A 100MB WAV file:

  • binary+l → stored as ~60MB on server (compressed)
  • binary+lF → stored as 100MB on server (wasted space)

A 50MB PNG file:

  • binary+l → stored as ~49.5MB (CPU wasted, barely smaller)
  • binary+lF → stored as 50MB (correct, fast)

Why Limited Revisions (+S) Matter

Executables and debug symbols are large, rebuilt constantly, and old versions are rarely needed. +S2 keeps only the 2 most recent revisions on the server, saving massive amounts of storage.

binary+S2w for executables (.exe, .dll, .dylib):

  • 50MB exe, 100 builds = 5GB without +S, 100MB with +S2
  • +w keeps them writable (build tools need to overwrite)

binary+Sw for debug symbols (.pdb):

  • Often 200MB+ each
  • +S (no number) = keep only 1 revision
  • Old PDB files are useless once the matching binary is gone

Engine-Specific Decisions

Unreal Engine 5

File Type Why
.uasset binary+l Binary, unmergeable, primary asset format
.umap binary+l Binary level files
.uproject text JSON, mergeable
.uplugin text JSON, mergeable
.ini text Config, mergeable
.usf / .ush text Shader source, mergeable
.csproj / .sln text+w Regenerated by engine, must be writable

Unity

File Type Why
.unity binary+l Scene files, unmergeable in binary mode
.prefab binary+l Prefab files, unmergeable
.asset binary+l Serialized assets
.meta text CRITICAL — YAML text, tracks asset GUIDs. Must be text, never binary.
.shader text Shader source, mergeable
.cs text C# scripts, mergeable
.asmdef text Assembly definitions, JSON-based
.csproj / .sln text+w Regenerated by Unity

Unity .meta files: These small YAML files map each asset to a GUID. If a .meta file is lost or corrupted, Unity loses track of all references to that asset. They must be versioned, and they must be text type so Perforce can merge them properly.

Typemap Layering

The typemap files are designed to be layered:

  1. game-dev-common.txt — Base mappings for textures, audio, 3D, video, documents, executables, scripts
  2. unreal-engine.txt or unity.txt — Engine-specific overrides layered on top

The ENGINE environment variable controls which layers are applied:

  • ENGINE=unreal → common + unreal
  • ENGINE=unity → common + unity
  • ENGINE=common → common only
  • ENGINE=none → no typemap (manual setup)

Engine-specific entries override common entries because Perforce uses the last matching rule. So if game-dev-common.txt sets *.cs to something, and unity.txt also sets *.cs, the Unity definition wins.

Path Patterns

All entries use //... (double slash, triple dot) which matches all depots and all paths. This means the typemap works regardless of depot name — stream depots, classic depots, whatever you create.

binary+l //.../*.uasset     # Matches //game/main/Content/MyAsset.uasset
                             # Matches //depot/art/MyAsset.uasset
                             # Matches //anything/anywhere/MyAsset.uasset

If you need per-depot rules, replace //... with //depotname/....

Viewing and Editing

# View current typemap
p4 typemap -o

# Edit typemap interactively
p4 typemap

# Apply from file
p4 typemap -i < typemap.txt

Further Reading