How Map Making Works
"Map making" in Holdfast covers two very different workflows. Pick the right one before you start:
Route 1: Config-Based Map Editing
Customise vanilla maps through the server configuration file: spawn props and weapon racks with objects_override, move spawns and capture points, change class limits, weapons, and weather until the map plays like something new. No tools beyond a text editor are needed, and changes apply per map rotation.
Route 2: SDK Map Building
Build entirely new maps in the Unity-based Holdfast SDK — your own terrain, water, props, spawns, and game modes — and ship them through the Steam Workshop. Servers then load them with mods_installed + load_mod and map_name modmap (see Loading a Workshop Map).
objects_override editing is the only "map modding" that works on cross-play servers, which is why it has seen renewed interest since mid-2025. See Mods and Consoles.map_name CustomMap and CustomMapNaval — two flat, empty maps. Naval CustomMap was retired around January 2024 (Open Waters does practically the same thing) and the flat land CustomMap was removed later. Neither appears in the current map name enums. Build on an existing vanilla map, or subscribe to one of the community-published flat-plane Workshop maps instead.Loading a Workshop Map
The single most-asked question in five years of modding chat. Loading a custom map from the Steam Workshop takes three config entries:
# Global section (top of config, NOT inside a rotation). # The comment after # is ignored — use it to label your mods. mods_installed 2101070095 #My Map Name # Inside the rotation: !map_rotation start map_name modmap map_name_override Swamp Town game_mode ArmyBattlefield # ... your usual rotation settings ... load_mod 2101070095 !map_rotation end
mods_installed <workshopid>installs the mod on the server. The ID is the long number in the mod's Steam Workshop URL. Onemods_installedline per mod — putting two IDs on a single line breaks the server.map_name modmaptells the rotation to use whatever modded map is loaded instead of a vanilla map. For non-map mods (uniforms, sounds, scripts) use the samemods_installed+load_modpattern but do not changemap_name.load_mod <workshopid>loads the mod for that rotation. Convention is to put it just above!map_rotation end. You can stack multipleload_modlines — one map mod but any number of skin/uniform mods per rotation.map_name_override <name>gives the map a proper display name in the map list, RC map menu, and admin panel instead of a generic "modded map" label. It works on vanilla rotations too.- Restart the server after editing the config or updating the Workshop item — or hot-reload while iterating, see Iterating Without Restarts.
- The spelling is
load_mod. A circulating example config usesmod_loaded, which does not work.
CommanderBattle game mode enum. For the popular Commander Battles mod, use game_mode ArmyAssault in the rotation. Game mode enums are listed on Server Configuration Enums.See Server Configuration for mods_installed_server_only, load_mod_client_only, load_mod_server_only, and mod variables.
Rotation Setup & Base Maps
When editing a map through config you'll spend a long time placing objects, so set up a dedicated sandbox rotation with an unlimited timer and open spawns:
!map_rotation start map_name SpanishFarm # any vanilla map enum — see Server Configuration Enums game_mode ArmyBattlefield round_time_minutes -1 reinforcements_per_faction 9000 wave_spawn_time_seconds 1 max_player_respawns -1 faction_balancing false allow_midround_spawning true allow_faction_switching true allow_spectating true minimum_players -1 maximum_players 150 time_hour 8 time_dynamic false friendly_fire true weather_preset calm weather_dynamic false game_type hardcore !map_rotation end
Choosing a Base Map
- With the flat CustomMap removed, start from a relatively open vanilla map (see the map name list) or subscribe to a community flat-plane map on the Workshop and load it as a mod map.
- Editing vanilla maps by spawning props via config needs no SDK at all, though it is wonkier and more limited than building the map properly in the SDK.
- Config prop placement and Workshop mod maps stack: you can
objects_overrideon top of a loaded mod map too.
Positioning
Before placing a prop, decide where it goes and which way it faces. Stand where you want it in-game, open the console with F1 and type get. This prints your position and rotation:
playerPosition => (15.3, 16.8, 146.9) playerRotation => (0.0, 218.0, 0.0)
- Position is (X, Y, Z). Positive X is North, positive Y is up, positive Z is West.
- Rotation is degrees around (X, Y, Z). You'll use Y most to turn objects; X and Z tilt.
- To face the opposite direction of the example above, use
(0.0, 38.0, 0.0)(218 - 180). get playerPositionandget detailscopy the values to your clipboard for pasting straight into the config.
Placing Props
Props range from simple decor (position and rotation only) to interactables with extra parameters. All objects_override lines go between !map_rotation start and !map_rotation end.
Decorative Props
objects_override <prop> <pX> <pY> <pZ> <rX> <rY> <rZ>
- <prop> — Enum from the Spawnable Props list
- <pX> <pY> <pZ> — Position (use
get playerPosition) - <rX> <rY> <rZ> — Rotation (use
get playerRotation)
Example — a target dummy:
objects_override TargetDummy 15.3 16.8 146.9 0.0 218.0 0.0
TargetDummy after the Frontlines update) pass; treat individual entries with mild suspicion rather than distrusting the whole page. Expanding the list (and a mod-map-to-config exporter) has been floated by AGS but not committed to.Weapon Racks
Players hold E to take weapons from a rack (limited supply).
objects_override WeaponRack <pX> <pY> <pZ> <rX> <rY> <rZ> <Weapon> <Count 0-255>
- <Weapon> — Enum from Weapon. Racks accept melee weapons too, not just firearms.
objects_override WeaponRack 1 2 3 7 8 9 Rifle_Pattern1800Infantry 4 objects_override WeaponRack 286.81 17.98 469.46 0.00 161.02 0.00 Axe2H_Variation1 255
Firearm Ammoboxes
Customisable ammo boxes for roleplay and events. Players replenish ammo on use.
objects_override firearmammobox <pX> <pY> <pZ> <rX> <rY> <rZ> <Firearm> <Max Uses> <Ammo Given> <Max Uses Per Player>
- <Firearm> — Enum from Firearm
- The three counts are each
0-255: total interactions until depletion, rounds given per use, and the per-player cap.
objects_override firearmammobox 1 2 3 7 8 9 Rifle_Pattern1800Infantry 20 2 1
Spawns, Capture Points & Ships (Config)
Dynamic Capture Point
A round-ending capture flag can be spawned from config on any map, including naval ones — this is how the community built a "Sea Race" mode:
dynamic_capture_point_enabled true dynamic_capture_point_position <X> <Y> <Z> dynamic_capture_point_auto_active_time 1190 dynamic_capture_point_capture_duration 360 dynamic_capture_point_max_capture_player_count 1
auto_active_timecounts from round end, not round start. On a 20-minute (1200 s) round, a value of 1190 makes the flag appear 10 seconds after the round starts; a value of 10 makes it appear 10 seconds before the round ends.dynamic_capture_point_capture_durationreportedly has no effect (the capture timer stays around 40 s), andcapture_point_overridewith objective letters didn't change it either. Verify- Manual alternative: an admin types
rc set triggerDynamicCapturePoint. Anrc delayentry in the rotation can automate the trigger.
Custom Ship Spawn Positions
A working recipe for placing ship spawns at exact positions (used for a naval training map):
objects_override shipspawnsection 374.48 0.30 333.60 0.00 156.12 0.00 ships_spawn schooner2gun 1 french 0 ships_spawn Schooner2gun 1 British 1
- The map's spawn section must be set up for Naval Battlefield in the SDK; grab the coordinates in-game with
get playerPosition. - Known limitation: only one custom-positioned ship spawn works at a time. Functional (sailable) ships cannot otherwise be spawned at an exact position.
- See Server Configuration for
ships_spawn,ships_spawn_detail_override, andships_health_detail_override.
Spawn Timing Tricks
- One-life-style custom spawn waves:
rc delayed <seconds> set characterRespawnTime 9999999inside the rotation.
Iterating Without Restarts
While building, you'll change the config constantly. Reload it without a full server restart:
rc fileReloader serverConfigFile rc mapRotation 1
- Substitute the correct rotation index.
rc mapRotationre-enters the rotation immediately — don't wait for the round to end. rc set endRoundthen advancing naturally works better for some cases (e.g. testing round-end behaviour).- If the rotation loads a Workshop mod, the mod re-downloads each time you switch to it after changing the Workshop upload.
- When the Workshop mod itself is updated, restart the server rather than relying on the hot reload.
See Remote Console Commands for the full RC reference.
SDK Setup & Unity Versions
Basic Unity familiarity helps, but map building requires no programming.
- The SDK currently targets Unity 2022.3.62f1 (SDK v2.31); 2022.3.53f1 also works since the May 2025 compatibility fix. Using any other version is the most common source of broken projects — check the SDK Version History if you are upgrading an old map.
- Install the SDK and set up your first mod following SDK Tutorial #1 – Getting Started and #2 – Creating A New Mod. The official SDK documentation covers the level editor end to end; the SDK User Guide lists all 22 video tutorials.
- Up-to-date Unity download links are maintained in the #become-a-modder Discord channel.
- Scale is 1:1: one Unity unit is one metre. Drop the default 1 m³ cube into the scene to gauge distances.
- Vanilla map terrains and heightmaps ship with the SDK — you can study or reuse their terrain data, but full map scenes cannot be opened.
Hierarchy, Layers & Colliders
Scene Hierarchy
Follow SDK Tutorial #3 – Map Scene Hierarchy. The rules that answer 90% of support questions:
- Gameplay props and buildings go under the Level parent.
- Objects without colliders (visual-only) belong under Client — the server never needs them.
- Small decorative items (cutlery, birds, clutter) go under Clutter so low-end clients can skip them.
- Remove Rigidbody components from imported static props, or they'll behave as physics objects.
Layers (the most repeated SDK advice)
- Terrain goes on the Terrain layer.
- Props players collide with go on Layer 13: Static Environment.
- The Default layer is a trap: players can stand on the object, but crouching, jumping, aiming, and weapon switching break — the game treats them as floating in mid-air.
Custom Walkable Props
For imported models players should walk on, use this pattern: an empty parent holding (a) the model child on Static Environment with no colliders, and (b) a separate empty on the Terrain/walkable layer holding primitive box colliders that approximate the shape.
- For a simple house mesh, a non-convex mesh collider is acceptable; for most props prefer primitive boxes or a LOD mesh as the collider.
- Don't tick Convex on a mesh collider if players must enter the interior — convex hulls seal it shut.
Useful Asset Names
- Cavalry spikes:
Chevaux de Frise. - Destructible artillery:
GameAsset_Artillery_*_Destructible(e.g.GameAsset_Artillery_FieldGun_9PDR_Destructible,GameAsset_Artillery_Mortar_Naval_Destructible). - Decorative ship hulls: search "Brig" and similar in the props panel. Sailable ships cannot be placed as map props.
- Spawn menu podium: place a normal
SpawnMenuCharacterScreen, rotate it, then copy its rotation to theSpawnMenuCharacterScreenEmptyvariant (the Empty variant's pivot is misleading). Its map-name sign is set up manually with TextMeshPro using the OptimusPrinceps font. - Loading-screen/ambient music: an Audio Source under Client → Ambient Sounds, set to 2D, no loop.
Tricks
- Custom spawn flags: dismantle the vanilla British spawn-flag prop and swap the flag part's texture. Faction flag props can't be rescaled — the flag cloth is loaded per-faction at runtime.
- Weather blocking underground areas: the SDK's own weather blockers don't work; an upside-down desert-gate asset scaled hugely on Y extrudes its built-in weather blocker over the area.
- Fake destructible terrain: cover a pit with the SDK's dirt-pile props and mark the prop destructible.
Terrain, Water & Grass
Terrain
- Start with SDK Tutorial #4 – Editing The Terrain.
- Duplicating a terrain without losing textures/grass: duplicate the
mapname_terrain.assetfile under Terrain Collider → Terrain Data (Ctrl+D), rename it, and drag it into the scene. - Swapping terrain textures: use the SDK's Terrain Texture Replacer tool (Holdfast SDK Options → SDK Tools) — SDK Tutorial #18.
- Import trees as props, not as Unity terrain trees (official AGS recommendation). Easy Scatter or a prefab brush speeds up placement.
- The game's water level is Y = 0. While building, add a lake/sea water prop at Y = 0 as a visual guide — but delete it before uploading, or the game's own generated ocean overlaps it and you get two water layers.
- The partial ocean system (ocean on one side, land elsewhere — Port Nile / Glacier / Mansion style) is exposed on the
HoldfastMapModOverloadroot object. - The Limited Ocean area is roughly 7500 × 7500.
- Rowboat spawners require the ocean — lake props are not enough. Their spawn obstruction check rejects any obstruction, not just ship colliders.
- Newer water workflow (post early 2024): use the
WaterSystemgame asset, set Seabed Depth and tick Generate Seabed.
Grass & Vegetation (TVE)
- Grass is now part of the base SDK — no extra download. Drag grass prefabs into the Grass script list on your terrain.
- Floating or clipping grass: raise the terrain heightmap resolution, align the TVE/grass area box to the same coordinates as the terrain, and use the TVE Height Offset setting.
- If grass breaks entirely, the reliable fix is deleting and redoing the grass + TVE elements, including the default grass area.
- Not every plant asset works as painted terrain detail — only those on the "blanket shader" (which snaps to terrain). Incompatible ones glitch across the screen; place those with a prefab brush instead.
- Multi-terrain maps have known, unresolved grass problems. Verify
Spawns, Capture Points & Game Modes (SDK)
Set up game modes with SDK Tutorial #6 – Setting Up Gamemodes.
Spawns
- Spawn menu ordering: spawn points with larger capacity appear higher in the list.
- Prefer spawn nodes over area colliders where placement matters — area spawns on sloped ground (e.g. Siege defenders) pick bad spots like the highest point.
- Area/collider spawns place players on top of whatever is above the collider, so you cannot spawn players inside buildings or underground with them.
- Players will spawn inside tent props unless you hand-place many small exact spawn positions around them.
- Battle Royale mod compatibility: add a game object named
Dynamic Spawn Positionscontaining 100+ empty children spread across the map.
Capture Points
- The old
GameAsset_Capture Mode Flagno longer exists. Use thefunctional_captureModeFlagasset placed under the capture point hierarchy, then map spawn sections to capture points and set capture requirements in the game mode section. - Duplicate objective letters (three points all showing "B") is a known setup pitfall — recheck the capture point indices.
- The server error
Spawn section tied with capture point -1 is nullmeans a spawn section is linked to a capture point that no longer exists.
Game Modes
- A map now requires the game mode's spawn objects to be enabled for the map to load in that mode. Disabling a mode's objects makes any rotation using that mode unloadable.
Performance & Optimisation
Watch the Batch Count
Batches are the number to watch, not triangle count. Above roughly 3,000 batches performance degrades noticeably; the Stats button in play mode shows it. Foliage overuse is the easiest way to blow it up (a bamboo grove alone has produced 8k batches).
Since the URP switch, many copies of the same mesh + material are cheap; the batcher suffers when many complex meshes use different materials. Small props should still be culled at distance — quad overdraw can cost more than batch overhead. Shadows remain the single biggest FPS cost.
Custom LOD Objects (Group Culling)
Distance-based group culling, added in the September 2022 SDK hotfix — see SDK Tutorial #16 – Custom LODs:
- Put the script on the parent of a prop group; range is measured from that object's pivot.
- First value = normal cull distance; second = spyglass cull distance (slightly higher).
- Typical values are 50–75 for props inside buildings. Also excellent for culling point lights.
- It culls groups; it does not override an asset's built-in LODs.
Fog Distance
Official guideline: measure from the centre of the playable zone to the centre of the first hill line, then double it (Island Plains: 550 m → fog 1100). Keep at least 900–1100 even on very small maps; naval maps use 4000–6000. Max fog distance is set on HoldfastMapModOverload.
Sizing Datapoints
- A 4096×4096 single-terrain naval map works but lags at 120+ players; the same size split into four 2048 terrains performs slightly better. Naval public servers cap around 80 players for performance.
- 300+ props is nothing to worry about — Rio Grande has roughly double that.
- Terrain rendering (MicroSplat) is mostly GPU-side, and terrain instancing is enabled on terrains using the MicroSplat replacement material.
- Occlusion culling is not available to modders and wouldn't help much on open maps.
Building & Uploading
Follow SDK Tutorial #7 – Play Testing and #8 – Uploading Mods. Steam must be running and logged in, with the Workshop terms accepted.
Rules & Workflow
- Scripts must live in the same folder as the built scene; textures and models can be anywhere in the project.
- Recommended loop: open Unity → edit → save → build → upload → close Unity before re-editing. If a "Steam Workshop Upload Scene" appears on reopen, that is not your project — use File → Open Recent Scene.
- Give the map a proper thumbnail with SDK Tutorial #9 – Custom Map Images.
Common Failures
- Upload failures are usually a too-big preview image, a too-big upload folder, or a deleted upload
.xml. - Lost your export profile after an SDK update? Create a new profile and manually create a matching folder in the
LocalLowmod-build directory. - Building creates a backup folder alongside your mod files. If a project is lost, partial recovery from the built mod is possible — terrain heightmap and asset positions can be pulled back out.
After Game Updates
[UMod...] references a mod that is not loadedserver errors after a game update mean the map must be rebuilt on the current SDK.- The
UISceneTransitionLoaderPanel.SetCustomMapDetailsNullReferenceException when loading a map points at the map'sCustomMapDetailscomponent or an outdated SDK build — rebuild.
Map Design Guidance
Community consensus distilled from years of linebattle and naval hosting:
Linebattle Maps
- Artillery should punish but not dominate. Hill height and steepness define whether a position is a hold or a push.
- Give players at least one big landmark for orientation.
- Too many trees hurt third-person line play and admin spectating.
- Rocks and trees are meaningful cannonball cover — their hitboxes actually block shots.
- Study loved maps against disliked ones: Grassy Plains 4's west side works because of its two natural hold points; large open sweeping-hill maps play poorly.
- Go easy on assets; LODs are your friends.
- Make walls destructible only where you want the action focused.
- One or two secondary capture points make Coastal Siege interesting.
General
- Don't be a perfectionist about tiny mesh overlaps; do fix glaring issues like floating props.
Troubleshooting
Recurring problems and fixes. Check the server log or press F2 during loading to see the underlying error.
| Symptom | Cause & Fix |
|---|---|
| Spawn points can't be selected on a modded map (post mid-2026) | Move the Default Camera Position into the sky so all spawn points are visible from it, rebuild. See Spawns (SDK). |
| Server breaks after adding a mod | Two Workshop IDs on one mods_installed line. One line per mod.
|
| Mod downloads but the modded map never loads | map_name modmap missing from the rotation, or load_mod missing/typo'd (mod_loaded is wrong).
|
[UMod...] references a mod that is not loaded after a game update |
Rebuild the map on the current SDK. |
SetCustomMapDetails NullReferenceException on load |
Outdated SDK build / broken CustomMapDetails component. Rebuild.
|
| Two overlapping water surfaces in-game | The guide water prop was left in the scene. Delete it — the game generates the ocean itself. See Water. |
| Rowboat spawners don't work | They require the ocean enabled; lake props aren't enough. Their obstruction check rejects any obstruction. |
| Grass floats above or clips into terrain | Raise heightmap resolution, align the TVE area box to the terrain, use TVE Height Offset. If broken, redo the grass + TVE elements. |
| Plants glitch and streak across the screen | The asset isn't on the blanket shader, so it can't be painted as terrain detail. Place it with a prefab brush instead. |
| Players can't crouch/jump/aim on a prop | Prop is on the Default layer. Move it to Layer 13: Static Environment (colliders on Terrain/walkable). See Layers. |
| Players spawn on rooftops or the highest point | Area-collider spawns place players on top of anything above the collider. Use spawn nodes. |
| Players spawn inside tents | Hand-place many small exact spawn positions around tent props. |
| Multiple capture points show the same letter | Capture point indices duplicated in the setup. Recheck them. |
Spawn section tied with capture point -1 is null |
A spawn section links to a capture point that no longer exists. Relink or remove it. |
| Map won't load in a game mode it used to support | That mode's spawn objects are disabled in the scene. Modes now require their spawn objects enabled. |
| Round-start weapons wrong on later rotations | Starting-weapon overrides leak between rotations. Re-set the override on every map. See Spawns (Config). |
SDK Version History (Map-Relevant)
Release notes that changed how maps are made. Full upgrade steps live on the SDK Upgrade Guide; full game changelogs on Game Release History.
| Version | Unity | What Changed for Map Makers |
|---|---|---|
| v2.31 (current) | 2022.3.62f1 | Unity bumped to the last LTS release of Unity 2022. 2022.3.53f1 also remains compatible. |
| Mid-2026 game update | n/a | Broke spawn point selection on older modded maps (Default Camera Position fix, see Spawns). |
| ~2024-01 | 2022.3.11f1 | New water workflow (WaterSystem asset, seabed generation); grass moved into the base SDK; Naval CustomMap removed in favour of Open Waters. Flat land CustomMap removed later.
|
| v2.15 | 2022.3.11f1 | Built-in Render Pipeline to URP. Old materials and shaders removed; batching characteristics changed (same mesh + material now cheap). Pre-2024 material/shader advice is historical. |
| 2022-09-09 hotfix | n/a | Added Custom LOD Objects (group culling) and the partial ocean system on HoldfastMapModOverload; official fog distance guidance published.
|
| Game 2.5 | n/a | Holdfast SDK 5.0: 1500+ new assets in the level, uniform, and flag editors. |
| Game 1.3 | n/a | Holdfast SDK V1 released: the first map, uniform, and flag editor. |
Tools & Resources
Official
- SDK Documentation (100+ pages) and the SDK User Guide tutorial index.
- AGS SDK Tutorial playlist — for maps especially #3 (Hierarchy), #4 (Terrain), #5 (Placing Objects), #6 (Gamemodes), #16 (Custom LODs), #18 (Terrain Texture Replacer), #19 (Out Of Bounds), #20 (Scene Camera Views).
- Wiki: Spawnable Props, Server Configuration, Server Configuration Enums, Server Config Templates, Remote Console Commands, Maps, Mods and Consoles, SDK Upgrade Guide.
Community Guides & Tools
- Rotating props without scripts (animation-based).
- eLF's procedural spawn-area generator demo.
- Flag-making in Unity and flag ripple in Photoshop (scoreboard flags).
- Easy Scatter / prefab brush assets for tree and vegetation placement.
- Updated
SoundReplacer.cs(fixes sound mods across map rotation) — pinned attachment in #mod-coding. - Toonu's
GameAsset_Artillery_*_Destructibleprop name list — posted in #mod-discussion (2022-09-27).
Example Configs
The Server Config Templates page contains hundreds of working rotations, including map_name modmap + map_name_override examples for every game mode.
Known Limitations & Open Questions
Things the community has hit the edges of. If you solve one of these, share it in #mod-support and update this page.
- Howitzer spawnable prop name: howitzers were added to community maps in 2023 but no spawnable enum for them has been found. Is one on the Spawnable Props list at all?
- Carryable flag props: the pick-uppable flag (like lanterns) has no known
objects_overrideenum. dynamic_capture_point_capture_duration: appears to do nothing — capture timer stays around 40 s regardless.- Rowboat spawn obstruction check: unclear what it raycasts against; blocks rowboat use on land maps.
- Only one custom
shipspawnsectionposition works per rotation; no known workaround. - Multi-terrain maps + grass/TVE: reported broken with no fix or acknowledgement.
- Spawning players under terrain or inside buildings with area spawns: not possible; nodes are the only partial answer.
- Spawnable Props audit: which enums were renamed or broken across the Frontlines/URP/crossplay updates has never been fully mapped out.
- Expanded spawnable props / mod-map-to-config exporter: floated by AGS in mid-2025 for cross-play events; no commitment yet.
Support
Got a question that's not covered in this documentation?
We will gladly give you a helping hand should you require, so don't shy away from asking any questions. You will also find members within the community familiar with the toolset willing to do so.
Join the Official Discord, then head to the #become-a-modder channel and click the button to get the Modder role. This will unlock all channels concerning the discussion of modifications and scripting, including #mod-support.