Level Transitions

How It Works

Level transitions work similarly to Half-Life 2. When a transition fires, the engine snapshots the current map’s state, loads the destination map, and carries any entities that were inside a designated transition volume across to the new level. The player’s position in the new map is determined by a LogicTransitionLevel anchor entity placed in both maps.

The engine calculates the offset between the two anchors and shifts all transitioning entities by that amount, so the player lands in the right spot without any manual coordinate work. The anchors can be placed anywhere in world space; what matters is their position relative to the surrounding geometry.

Maps you’ve already visited are cached in memory for the session. Transitioning back restores the map to the state it was in when you left rather than resetting to the original file.

Setting Up the Source Map

Every transition needs three things in the source map: a transition volume, a LogicTransitionLevel entity, and a fire trigger.

1
Create the transition volume

Draw a FuncTrigger brush that covers the area where entities need to be to carry over. This should be big enough to contain the player and any NPCs you want to bring along. Give it a target name like level_transition_volume and apply the tool_trigger texture to all faces.

2
Place a LogicTransitionLevel entity

Place a LogicTransitionLevel entity at the threshold between the two spaces. Give it a target name and set its properties:

Transition Volume

The target name of your FuncTrigger volume, e.g. level_transition_volume.

Destination Anchor

The target name of the matching LogicTransitionLevel in the destination map.

3
Create the fire trigger

Place a second, smaller FuncTrigger at the actual threshold where you want the load to happen. Set up an output on it:

From My Output

OnTriggerEnter

To Entity

Your LogicTransitionLevel entity name.

Input Target

TransitionLevel

Input Parameter

The destination map name, relative to the current map’s folder, with no file extension. For example: level_b.

4
Add a class filter to the fire trigger

Without a filter, any entity walking through the fire trigger will set off the transition. Place a LogicClassFilter entity and set its Classname property to your player class (e.g. Player). Set the fire trigger’s Filter Name property to this entity’s target name. Now only the player can fire the transition.

Setting Up the Destination Map

The destination map needs a matching LogicTransitionLevel placed at the same relative position as the one in the source map. The engine uses the offset between the two anchors to reposition transitioning entities.

Give this entity the same target name you set in Destination Anchor back in the source map. That’s all the engine needs to find it.

Set up the reverse transition here too so the player can walk back. Make sure the return fire trigger is not placed right where the player arrives. If the player transitions in and immediately steps on the return trigger, they’ll bounce back and forth. Leave enough space that the player has to deliberately walk back.

Note

Use a LogicClassFilter on the return trigger too. Non-player entities walking through can trigger an unintended transition in both directions.

What Carries Over

Any entity physically inside the transition volume when the transition fires will be carried to the new map. This includes the player and any NPCs or physics objects in that space. Their position, rotation, velocity, and custom controller data all transfer.

This system is built on top of the save system. Technically, entities that transfer are serialized and re-spawned, so anything you want to carry over needs to be saved via [SaveValue] or CaptureCustomData() as described on the save system page. Everything else will reset to default values on the new map.

Global state flags set via GlobalState are also preserved across transitions.

Note

In the FPS template, both the source and destination map can have a Player entity placed. When the player spawns from transition, the template’s player controller removes any other existing player entity, leaving only the one that transferred over. This also means you can use the same map for chapter-based games and still be able to test individual maps without needing to have transitioned from somewhere else.

Saving Across Transitions

The session map cache is included in save files. If the player saves after visiting multiple maps, all cached states are written to disk and restored on load. A player can save in Map B, load later, return to Map A, and find it in exactly the state they left it.

Starting a new game should call SaveManager.ClearSessionMapStates() to wipe cached states from any previous session.