Generating navigation mesh – DayZ

From Bohemia Interactive Community
Jump to navigation Jump to search
No edit summary
(Removed no longer working links and adjusted the documentation.)
 
(6 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[[Category:DayZ:Editing|Terrain]]
{{GameCategory|dayz|Terrain Editing}}
[[Category:DayZ:Terrain_Editing|Terrain]]


==Overview==
== Overview ==


This page describes the basics of generating navigation mesh file (often called 'navmesh') for your terrain. Navmesh for your terrain is not mandatory (game will cope without it), but it contains essential data for the AI (obstacles, door links, jump links,..) without which it wont be able to navigate properly (AI entities will stand frozen on their spawn point). For guaranteed behaviour of the AI, it is '''necessary to re-generate navmesh after each new terrain build''' (each time wrp is binarized to be precise).
This page describes the basics of generating navigation mesh file (often called 'navmesh') for your terrain. Navmesh for your terrain is not mandatory (game will cope without it), but it contains essential data for the AI (obstacles, door links, jump links,..) without which it wont be able to navigate properly (AI entities will stand frozen on their spawn point). For guaranteed behavior of the AI, it is '''necessary to re-generate navmesh after each new terrain build''' (each time wrp is binarized to be precise).


Requirements:
Requirements:
Line 10: Line 9:
* Have a '''working custom terrain''' (mod) files, '''binarized and packed into pbo'''.
* Have a '''working custom terrain''' (mod) files, '''binarized and packed into pbo'''.


==Game config==
== Game config ==
In order to get your navmesh generated and then loaded by the game, configuration file (precisely your ''CfgWorlds'' entry) for your terrain '''has to contain Navmesh class'''. This class contains all the necessary parameters for generation and also later use in the game.
In order to get your navmesh generated and then loaded by the game, configuration file (precisely your ''CfgWorlds'' entry) for your terrain '''has to contain Navmesh class'''. This class contains all the necessary parameters for generation and also later use in the game.
<syntaxhighlight lang="c++">
<syntaxhighlight lang="c++">
class CfgWorlds
class CfgWorlds
{
{
  ..
/* ... */
  ..
class yourterrain: CAWorld
  class yourterrain: CAWorld
  {
    ..
class Navmesh
{
{
navmeshName="\path\to\your\navmesh\file.nm";
/* ... */
filterIsolatedIslandsOnLoad = true;
class Navmesh
visualiseOffset = 0.0;
{
navmeshName="\path\to\your\navmesh\file.nm";
filterIsolatedIslandsOnLoad = true;
visualiseOffset = 0.0;


class GenParams
class GenParams
{
tileWidth = 50.0;
cellSize1 = 0.25;
cellSize2 = 0.1;
cellSize3 = 0.1;
filterIsolatedIslands = true;
seedPosition[] = {7500, 0, 7500};
class Agent
{
{
diameter = 0.6;
tileWidth = 50.0;
standHeight = 1.5;
cellSize1 = 0.25;
crouchHeight = 1.0;
cellSize2 = 0.1;
proneHeight = 0.5;
cellSize3 = 0.1;
maxStepHeight = 0.45;
filterIsolatedIslands = true;
maxSlope = 60.0;
seedPosition[] = {7500, 0, 7500};
};
class Agent
class Links
{
class ZedJump387_050
{
{
jumpLength = 1.50;
diameter = 0.6;
jumpHeight = 0.50;
minCenterHeight = 0.3;
standHeight = 1.5;
jumpDropdownMin = 0.5;
crouchHeight = 1.0;
jumpDropdownMax = -0.5;
proneHeight = 0.5;
areaType="jump0";
flags[] = {"jumpOver"};
maxStepHeight = 0.45;
color = 0x66ff0000;
maxSlope = 60.0;
};
};
class ZedJump388_050
{
class Links
jumpLength = 1.50;
{
jumpHeight = 0.50;
class ZedJump387_050
minCenterHeight = -0.5;
{
jumpDropdownMin = 0.5;
jumpLength = 1.50;
jumpDropdownMax = -0.5;
jumpHeight = 0.50;
areaType="jump0";
minCenterHeight = 0.3;
flags[] = {"jumpOver"};
jumpDropdownMin = 0.5;
color = 0x66dd5500;
jumpDropdownMax = -0.5;
};
areaType="jump0";
class ZedJump387_110
flags[] = {"jumpOver"};
{
color = 0x66ff0000;
jumpLength = 3.90;
};
jumpHeight = 1.1;
class ZedJump388_050
minCenterHeight = 0.5;
{
jumpDropdownMin = 0.5;
jumpLength = 1.50;
jumpDropdownMax = -0.5;
jumpHeight = 0.50;
areaType="jump0";
minCenterHeight = -0.5;
flags[] = {"jumpOver"};
jumpDropdownMin = 0.5;
color = 0x66008000;
jumpDropdownMax = -0.5;
};
areaType="jump0";
class ZedJump420_160
flags[] = {"jumpOver"};
{
color = 0x66dd5500;
jumpLength = 4.0;
};
jumpHeight = 1.6;
class ZedJump387_110
minCenterHeight = 1.1;
{
jumpDropdownMin = 0.5;
jumpLength = 3.90;
jumpDropdownMax = -0.5;
jumpHeight = 1.1;
areaType="jump0";
minCenterHeight = 0.5;
flags[] = {"jumpOver"};
jumpDropdownMin = 0.5;
color = 0x660000ff;
jumpDropdownMax = -0.5;
};
areaType="jump0";
class ZedJump265_210
flags[] = {"jumpOver"};
{
color = 0x66008000;
jumpLength = 2.45;
};
jumpHeight = 2.5;
class ZedJump420_160
minCenterHeight = 1.8;
{
jumpDropdownMin = 0.5;
jumpLength = 4.0;
jumpDropdownMax = -0.5;
jumpHeight = 1.6;
areaType="jump0";
minCenterHeight = 1.1;
flags[] = {"climb"};
jumpDropdownMin = 0.5;
color = 0x669400d3;
jumpDropdownMax = -0.5;
};
areaType="jump0";
class Fence50_110deer
flags[] = {"jumpOver"};
{
color = 0x660000ff;
typeId = 100;
};
jumpLength = 8.0;
class ZedJump265_210
jumpHeight = 1.1;
{
minCenterHeight = 0.5;
jumpLength = 2.45;
jumpDropdownMin = 1.0;
jumpHeight = 2.5;
jumpDropdownMax = -1.0;
minCenterHeight = 1.8;
areaType="jump2";
jumpDropdownMin = 0.5;
flags[] = {"jumpOver"};
jumpDropdownMax = -0.5;
color = 0x66aaaaFF;
areaType="jump0";
};
flags[] = {"climb"};
class Fence110_160deer  
color = 0x669400d3;
{
};
typeId = 101;
class Fence50_110deer
jumpLength = 8.0;
{
jumpHeight = 1.6;
typeId = 100;
minCenterHeight = 1.1;
jumpLength = 8.0;
jumpDropdownMin = 1.0;
jumpHeight = 1.1;
jumpDropdownMax = -1.0;
minCenterHeight = 0.5;
areaType="jump3";
jumpDropdownMin = 1.0;
flags[] = {"jumpOver"};
jumpDropdownMax = -1.0;
color = 0x6624fff8;
areaType="jump2";
};
flags[] = {"jumpOver"};
class Fence50_110hen
color = 0x66aaaaFF;
{
};
typeId = 110;
class Fence110_160deer  
jumpLength = 4.0;
{
jumpHeight = 1.1;
typeId = 101;
minCenterHeight = 0.5;
jumpLength = 8.0;
jumpDropdownMin = 0.5;
jumpHeight = 1.6;
jumpDropdownMax = -0.5;
minCenterHeight = 1.1;
areaType="jump4";
jumpDropdownMin = 1.0;
flags[] = {"jumpOver"};
jumpDropdownMax = -1.0;
color = 0xFFFFAA00;
areaType="jump3";
};
flags[] = {"jumpOver"};
class Fence110_160hen
color = 0x6624fff8;
{
};
typeId = 111;
class Fence50_110hen
jumpLength = 4.0;
{
jumpHeight = 1.6;
typeId = 110;
minCenterHeight = 1.1;
jumpLength = 4.0;
jumpDropdownMin = 0.5;
jumpHeight = 1.1;
jumpDropdownMax = -0.5;
minCenterHeight = 0.5;
areaType="jump4";
jumpDropdownMin = 0.5;
flags[] = {"jumpOver"};
jumpDropdownMax = -0.5;
color = 0xFFFFAA00;
areaType="jump4";
flags[] = {"jumpOver"};
color = 0xFFFFAA00;
};
class Fence110_160hen
{
typeId = 111;
jumpLength = 4.0;
jumpHeight = 1.6;
minCenterHeight = 1.1;
jumpDropdownMin = 0.5;
jumpDropdownMax = -0.5;
areaType="jump4";
flags[] = {"jumpOver"};
color = 0xFFFFAA00;
};
};
};
};
};
};
};
/* ... */
};
};
    ..
  };
};
};
</syntaxhighlight>
</syntaxhighlight>
Line 167: Line 165:
*''seedPosition'' - parameter should ideally be the center of your map (in meters)
*''seedPosition'' - parameter should ideally be the center of your map (in meters)


==Generation process==
== Generation process ==


Navmesh generation requires a '''working terrain in the game''', so make sure your terrain contains everything you want and you can access it in the game without any issues (can be done by running the game and using simple empty mission, see workshop item called [https://steamcommunity.com/sharedfiles/filedetails/?id=1558331009 Sandbox] for an example).
Navmesh generation requires a '''working terrain in the game''', so make sure your terrain contains everything you want and you can access it in the game without any issues (can be done by running the game and using simple empty mission, see workshop item called {{Link|https://steamcommunity.com/sharedfiles/filedetails/?id{{=}}1558331009|Sandbox}} for an example).


For the generation itself, you are going to need to do following:
For the generation itself, you are going to need to do following:
* Setup a completely empty mission on your terrain (download example [http://tom4897.info/depot/dayz/modding/dayz_te_navmesh_mission.zip here]).
* Setup a completely empty mission (folder should be called empty.yourworldname) on your terrain with a following init.c file:
* Create a server config that is pointing to the empty mission (download example [http://tom4897.info/depot/dayz/modding/dayz_te_navmesh_servercfg.zip here]).
void main()
{
}
class CustomMission: MissionServer
{
override PlayerBase CreateCharacter(PlayerIdentity identity, vector pos, ParamsReadContext ctx, string characterName)
{
Entity playerEnt;
playerEnt = GetGame().CreatePlayer(identity, characterName, Vector(2681, 0, 10070), 0, "NONE");//Creates random player
Class.CastTo(m_player, playerEnt);
GetGame().SelectPlayer(identity, m_player);
return m_player;
}
override void StartingEquipSetup(PlayerBase player, bool clothesChosen)
{
player.RemoveAllItems();
}
};
 
Mission CreateCustomMission(string path)
{
return new CustomMission();
}
* Use a server config that is pointing to the empty mission (you can take server cfg from the server files for example).
* Run DayZDiag_x64 (located near other game executables, make sure it is not blocked by the firewall) using following parameters:
* Run DayZDiag_x64 (located near other game executables, make sure it is not blocked by the firewall) using following parameters:
   DayZDiag_x64 -server -mod=yourmodfolder -startNavmeshDataServer -port=2302 -config=ServerDZNV.cfg
   DayZDiag_x64 -server -mod=yourmodfolder -startNavmeshDataServer -port=2302 -config=ServerDZNV.cfg
Line 183: Line 208:
Be ware of the fact that on a single machine, generation can take quite some time (depends on the size and complexity of the terrain) and can be quite taxing on your HW.
Be ware of the fact that on a single machine, generation can take quite some time (depends on the size and complexity of the terrain) and can be quite taxing on your HW.


==Using the generation output==
== Using the generation output ==
After navmesh generation is finished (progress reaches 100%), make sure '''NOT to close the tool''' and use ''File > Save NavMesh''. This will open up a window offering you to choose a location, where the navmesh file can be saved. Make sure to include ''.nm'' at the end of the file-name. The full path should correspond to the one you have defined in the navmesh config (see game config part of this article).
After navmesh generation is finished (progress reaches 100%), make sure '''NOT to close the tool''' and use ''File > Save NavMesh''. This will open up a window offering you to choose a location, where the navmesh file can be saved. Make sure to include ''.nm'' at the end of the file-name. The full path should correspond to the one you have defined in the navmesh config (see game config part of this article).

Latest revision as of 08:34, 22 October 2024


Overview

This page describes the basics of generating navigation mesh file (often called 'navmesh') for your terrain. Navmesh for your terrain is not mandatory (game will cope without it), but it contains essential data for the AI (obstacles, door links, jump links,..) without which it wont be able to navigate properly (AI entities will stand frozen on their spawn point). For guaranteed behavior of the AI, it is necessary to re-generate navmesh after each new terrain build (each time wrp is binarized to be precise).

Requirements:

  • DayZ and DayZ Tools package installed.
  • Have a working custom terrain (mod) files, binarized and packed into pbo.

Game config

In order to get your navmesh generated and then loaded by the game, configuration file (precisely your CfgWorlds entry) for your terrain has to contain Navmesh class. This class contains all the necessary parameters for generation and also later use in the game.

class CfgWorlds
{
	/* ... */
	class yourterrain: CAWorld
	{
		/* ... */
		class Navmesh
		{
			navmeshName="\path\to\your\navmesh\file.nm";
			filterIsolatedIslandsOnLoad = true;
			visualiseOffset = 0.0;

			class GenParams
			{
				tileWidth = 50.0;
				
				cellSize1 = 0.25;
				cellSize2 = 0.1;
				cellSize3 = 0.1;
				
				filterIsolatedIslands = true;
				seedPosition[] = {7500, 0, 7500};
				
				class Agent
				{
					diameter = 0.6;
					
					standHeight = 1.5;
					crouchHeight = 1.0;
					proneHeight = 0.5;
					
					maxStepHeight = 0.45;
					maxSlope = 60.0;
				};
				
				class Links
				{	
					class ZedJump387_050
					{
						jumpLength = 1.50;
						jumpHeight = 0.50;
						minCenterHeight = 0.3;
						jumpDropdownMin = 0.5;
						jumpDropdownMax = -0.5;
						areaType="jump0";
						flags[] = {"jumpOver"};
						color = 0x66ff0000;
					};
					class ZedJump388_050
					{
						jumpLength = 1.50;
						jumpHeight = 0.50;
						minCenterHeight = -0.5;
						jumpDropdownMin = 0.5;
						jumpDropdownMax = -0.5;
						areaType="jump0";
						flags[] = {"jumpOver"};
						color = 0x66dd5500;
					};
					class ZedJump387_110
					{
						jumpLength = 3.90;
						jumpHeight = 1.1;
						minCenterHeight = 0.5;
						jumpDropdownMin = 0.5;
						jumpDropdownMax = -0.5;
						areaType="jump0";
						flags[] = {"jumpOver"};
						color = 0x66008000;
					};
					class ZedJump420_160
					{
						jumpLength = 4.0;
						jumpHeight = 1.6;
						minCenterHeight = 1.1;
						jumpDropdownMin = 0.5;
						jumpDropdownMax = -0.5;
						areaType="jump0";
						flags[] = {"jumpOver"};
						color = 0x660000ff;
					};
					class ZedJump265_210
					{
						jumpLength = 2.45;
						jumpHeight = 2.5;
						minCenterHeight = 1.8;
						jumpDropdownMin = 0.5;
						jumpDropdownMax = -0.5;
						areaType="jump0";
						flags[] = {"climb"};
						color = 0x669400d3;
					};
					class Fence50_110deer
					{
						typeId = 100;
						jumpLength = 8.0;
						jumpHeight = 1.1;
						minCenterHeight = 0.5;
						jumpDropdownMin = 1.0;
						jumpDropdownMax = -1.0;
						areaType="jump2";
						flags[] = {"jumpOver"};
						color = 0x66aaaaFF;
					};
					class Fence110_160deer 
					{
						typeId = 101;
						jumpLength = 8.0;
						jumpHeight = 1.6;
						minCenterHeight = 1.1;
						jumpDropdownMin = 1.0;
						jumpDropdownMax = -1.0;
						areaType="jump3";
						flags[] = {"jumpOver"};
						color = 0x6624fff8;
					};
					class Fence50_110hen
					{
						typeId = 110;
						jumpLength = 4.0;
						jumpHeight = 1.1;
						minCenterHeight = 0.5;
						jumpDropdownMin = 0.5;
						jumpDropdownMax = -0.5;
						areaType="jump4";
						flags[] = {"jumpOver"};
						color = 0xFFFFAA00;
					};
					class Fence110_160hen
					{
						typeId = 111;
						jumpLength = 4.0;
						jumpHeight = 1.6;
						minCenterHeight = 1.1;
						jumpDropdownMin = 0.5;
						jumpDropdownMax = -0.5;
						areaType="jump4";
						flags[] = {"jumpOver"};
						color = 0xFFFFAA00;
					};
				};
			};
		};
		/* ... */
	};
};

We recommend you to use config above as the parameters are closely tied to the performance, AI and its animations. It is recommended to only change parameters listed below.

  • navmeshName - parameter corresponds to the path to the generated navmesh file, navmesh files can be quite large (hundreds of MBs) so plan accordingly where it will be kept in your data
  • seedPosition - parameter should ideally be the center of your map (in meters)

Generation process

Navmesh generation requires a working terrain in the game, so make sure your terrain contains everything you want and you can access it in the game without any issues (can be done by running the game and using simple empty mission, see workshop item called Sandbox for an example).

For the generation itself, you are going to need to do following:

  • Setup a completely empty mission (folder should be called empty.yourworldname) on your terrain with a following init.c file:
void main()
{

}

class CustomMission: MissionServer
{	
	override PlayerBase CreateCharacter(PlayerIdentity identity, vector pos, ParamsReadContext ctx, string characterName)
	{
		Entity playerEnt;
		playerEnt = GetGame().CreatePlayer(identity, characterName, Vector(2681, 0, 10070), 0, "NONE");//Creates random player
		Class.CastTo(m_player, playerEnt);
		
		GetGame().SelectPlayer(identity, m_player);
		
		return m_player;
	}
	override void StartingEquipSetup(PlayerBase player, bool clothesChosen)
	{
		player.RemoveAllItems();
	}
};
 
Mission CreateCustomMission(string path)
{
	return new CustomMission();
}
  • Use a server config that is pointing to the empty mission (you can take server cfg from the server files for example).
  • Run DayZDiag_x64 (located near other game executables, make sure it is not blocked by the firewall) using following parameters:
 DayZDiag_x64 -server -mod=yourmodfolder -startNavmeshDataServer -port=2302 -config=ServerDZNV.cfg
  • Run NavMeshGenerator tool (from DayZ Tools package) and make sure it is not blocked by the firewall.
  • Use Generation > Connect Data Server (built-in log should tell if it was a success or not).
  • After successful connection to the local server, use Generation > Start generation.
  • Confirm following window and the generation process should start.

Be ware of the fact that on a single machine, generation can take quite some time (depends on the size and complexity of the terrain) and can be quite taxing on your HW.

Using the generation output

After navmesh generation is finished (progress reaches 100%), make sure NOT to close the tool and use File > Save NavMesh. This will open up a window offering you to choose a location, where the navmesh file can be saved. Make sure to include .nm at the end of the file-name. The full path should correspond to the one you have defined in the navmesh config (see game config part of this article).