-
Notifications
You must be signed in to change notification settings - Fork 8
Creating Dungeons
This page is a work in progress
A valheim Dungeon consists of two main parts:
- An exterior location
- An interior collection of procedurally placed rooms.
The dungeon exterior is similar to all other locations. It is placed during world generation and will follow location placement rules. However, it should have an attached DungeonGenerator to generate the dungeon rooms as well as a teleport to transfer the player from exterior to interior.
- It's a good idea to set the exterior BiomeArea to Median. This ensures the resulting DG transform will likely be placed inside the zone.
A dungeon interior is a collection of procedurally placed rooms. A DungeonGenerator holds a Theme field and will attempt to place rooms with the same Theme. Each individual room has one, or many, room connection's. For each room connection, the DungeonGenerator will attempt to place another room given a set of room connection parameters. Dungeon generation will stop when the max rooms is met or when a room exceeds the bounds of it's starting zone.
- If using m_useCustomInteriorTransform, then also set the transform.position.z value of DungeonGenerator prefab to -30.
- Endcaps should have at least one Room.Size value equal to 0.
- Endcaps should use a transform.rotation of 0,0,0
There are a few quirks to building dungeon rooms in Valheim.
-
Room sizes should be configured so as to not allow rooms to exceed the bounds of their starting zone. If a room exceeds the bounds of it's starting zone and therefore places a room connection outside the starting zone, that room connection will not receive another room. This can be circumvented by ensuring all rooms fit neatly into a 64x64 size zone or by creating endcaps with a room size of 0.
-
The transform rotation values on room connections must follow a specific pattern. See attached image below. With the UnityEditor compass in the same orientation as shown. North facing room connections must use the rotation values on the top of the black square. South facing room connections must use the rotation values on the bottom of the black square. Etc...
- Room connection prefab transform.position values should be integers. The room connection prefab should be placed at the edge of room. For example, if a room is 8x8x8 and has a transform.position of 0,0,0 then the local position of a room connection prefab should be 8,0,0.
When an interior environment is assigned via Location.m_interiorEnvironment, the environment is applied at high Y-values within the same zone as the exterior location. If the dungeon interior crosses into an adjacent zone, the environment will stop applying, often appearing as a hard black wall aligned with the zone boundary.
This commonly occurs when the exterior location is placed near the edge of a zone and the dungeon interior extends beyond the original 64x64 area.
This can be visualized using mods such as ZoneScouter, which can display zone boundaries in the sky. The environment cutoff will align exactly with a zone edge.
Enable the following fields on both prefabs:
DungeonGenerator.m_useCustomInteriorTransformLocation.m_useCustomInteriorTransform
This forces the dungeon interior to spawn at a deterministic position within the zone, avoiding zone crossover.
When enabled, place the dungeon interior at a fixed offset, commonly:
transform.position = (0, -32, 0)
Since zones are 64x64, this positions the dungeon safely within the zone instead of relying on exterior placement randomness.
Important constraints:
- The entrance room must be oriented so it builds into the zone, not outward. Ensure
RoomConnectiontransforms are correctly rotated. - All rooms must fit entirely within a single 64x64 zone.
- Room
Sizevalues should be divisible by 4 to prevent cumulative overflow.- Example: eight 8x8 rooms fit exactly (64m).
- Mixing incompatible sizes (e.g. 8x8 + 10x10) can push placement outside the zone.
An interior environment can be applied to a prefab inside the dungeon instead of using Location.m_interiorEnvironment.
This is useful for large or special rooms (e.g. oversized boss rooms) where placement cannot be controlled.
This approach is fragile:
- Only the room containing the environment is guaranteed to render correctly.
- Other rooms may still cross zone boundaries and lose the environment.
- Many issues arise from incorrect transform.rotation values.
- Utilize the vanilla
RandomPieceRotationscript to rotate pieces like vines for a more natural look.
