Using Navmesh Regions
While respecting performance considerations for deterministic roll-backs in Quantum navmesh Regions are a compromise to Unitys dynamic navmesh carving. They can be used to dynamically toggle pre-defined areas of the navmesh with very little performance overhead.
Because regions are encoded as a mask inside the triangles (unsigned long) the maximum number of different region using the Advanced
region import mode ids per map is 64 (Navigation.Constants.MaxRegions
). Reusing the same id for different regions is possible in Advanced
mode.
The Walkable
area always converted to region 0 and called MainArea
.
All regions for a map are accessible in this list Map.Regions
. A region id is an integer and refers to the index of a region inside that map which can be retrieved using the Map.RegionMap
lookup.
Importing Navmesh Regions
Importing Quantum navmesh regions from a Unity navmesh can be done in two different modes.
Simple (Quantum SDK 3.0.1)
The Unity navmesh areas are directly mapped as regions and called their respective area names.
This allows only for 30 different regions in total.
Advanced
Additional scripts (QuantumNavMeshRegion
) and GameObject with Meshes have to be added to Unity scene. An Unity navmesh area is only used to mark any region, during import it is tried to backtrack from the Unity navmesh triangulation back to the source region script which contains the final region name.
This allows for 64 different regions per map.
Step By Step Tutorial
Step 1) Add areas to Unity navigation areas (Window > AI > Navigation
)
Step 2) Select the region import mode and toggle areas that should be converted to regions on the Quantum navmesh import description object MapNavMeshUnity
.
Step 3) [Advanced Mode Only] Setup the Quantum regions caster scripts.
Unity uses a MeshRenderer
to project areas onto the navmesh. Create a GameObject with a MeshRenderer
and attach the MapNavMeshRegion
.
The Id
is a unique string that will be accessible from code via the Map.RegionMap
from which can later get the region id (int, flag).
CastRegion
must be set to CastRegion
. The script is re-used for Off Mesh Links for example that do not require to project regions to the navmesh.
NavMeshHelper
shows if the GameObject is set up correctly: for example if is it set to static
and if the selected overwrite area is a region area.
During the navmesh import the areas that the navmesh triangles are matched back to the original region script using the bounding box of the mesh.
Because triangles are not generated 100% exact MapNavMeshUnity
has a setting that adds margin during the fitting (RegionDetectionMargin
). The value can be increased if regions are not exported but when it becomes too large there may be problems detecting neighboring regions.
The MeshRenderer
and this region script that generate the regions only have to be active during the baking.
Step 4) The map can be baked now using the BakeAll
button on the map GameObject (include the Navmesh baking steps).
When selecting the map GameObject the Quantum navmesh gizmos are shown. The colored areas of triangles in the navmesh are the regions. If the gizmos are not shown: Right-click on the Scene tab > Overlays > Quantum Gizmos
.
Step 5) Toggle the region globally in the simulation.
C#
public override void OnInit(Frame f) {
var regionId = f.Map.RegionMap["foo"];
f.NavMeshRegionMask->ToggleRegion(regionId, false);
}
The NavMeshPathfinder
component also has a RegionMask that can be used to toggle off regions for individual agents.
The following screenshot shows a deactivated region with an agent moving around it.
Step 6) Region activation is accessible and stored in the frame.
The mask needs to be reset when a new map is loaded. Run FrameBase.ClearAllNavMeshRegions()
for example during the ISignalOnMapChanged
signal.
C#
public class ResetRegionsSystem : SystemSignalsOnly, ISignalOnMapChanged {
public void OnMapChanged(Frame f, AssetRefMap previousMap) {
f.ClearAllNavMeshRegions();
}
}
The NavMeshRegionMask Class
The NavMeshRegionMask
object controls what regions are enabled using an internal bitset.
NavMeshRegionMask.Default
- Creates a region mask with all regions enabled.
NavMeshRegionMask.MainArea
- Creates a region mask that includes only the MainArea.
NavMeshRegionMask.Empty
- Creates a region mask that has no enabled regions.
NavMeshRegionMask.ToggleRegion(int region, bool enabled)
- Toggle a region on or off using the region id.
NavMeshRegionMask.IsRegionEnabled(int region)
- Test if a region is enabled.
NavMeshRegionMask.Clear()
- Reset the mask and sets all regions to enabled.