Navigation system
TIP
It takes about 10 minutes to read this articleThis article outlines how to implement automatic character navigation in the editor using the Navigation Volume gameplay object.
What is a navigation system
The Navigation Volume function object and dynamic navigation function are included in the navigation system.In the level scene, the Navigation Volume function object draws an area for characters or humanoid objects to move according to customized requirements, and the range of areas that can be accessed can be modified by dynamic navigation while the game is running.
How to use Navigation Volume
- step.1
In the [Gameplay Object] options on the left side of the editor, find the Navigation Volume and drag to the main viewport to create it.
The green area in the editor main viewport is an auto-navigable area. The display/hide of the area in the main viewport can be switch through the Visible menu function at the top right.
Set parameters to refer to objects that require navigation, such as the default size character or NPC when using navigation. Navigation parameters can use default values directly to ensure that character or NPC objects are not blocked when navigating. If larger or smaller objects use navigation, parameters such as capsule radius and height can be appropriately modified to make Navigation Volume calculation more accurate.
Usage tips Depending on the actual scene environment, Navigation Volume parameters can make the navigation effect smoother. For example, appropriately increasing the capsule radius parameters, can make characters update smooth when navigating around corners, avoiding moving close to the wall.
step.2
Once the Navigation Volume is created, it is automatically assigned to the Navigation Volume grouping in the object list. The Navigation Volume properties can be modified through the Property Panel to change the size of the Navigation Volume using the Relative Scale property.
Precautions
It is recommended that the scale of the Navigation Volume in each scene be kept within 2100 * 2100 * 100 to prevent the Navigation Volume too large to failing.
Deprecated
Do not modify the rotation properties associated with the Navigation Volume to avoid navigation calculation anomalies.
- step.3
Navigation Volume can be height determined, modify Z axis scale properties when navigation to high position is required.
How to get the main character (Player) to move to the target using navigation
- step.4
Create a Navigation Volume [see How to Use Navigation Volume]
- step.5
Create a script that uses the navigateTo() method to control roles for automatic navigation
@Component
export default class NewScript extends Script {
/** This function is called before the first frame update when the script is instanced */
protected onStart(): void {
let player = Player.localPlayer; // get character
let loc = new mw.Vector(1600, 0, 250); // set a target point
// Use navigateTo() to move the character to the target point
InputUtil.onKeyDown(mw.Keys.One, () => {
Navigation.navigateTo(player.character, loc, 10, () => {
console.log(`navigation succeeded');
}, () => {
console.log(`navigation failed');
});
});
// Use the stopNavigateTo() function to stop navigation of the specified object
InputUtil.onKeyDown(mw.Keys.Two, () => {
console.log(`Stop character wayfinding');
Navigation.stopNavigateTo(player.character);
});
}
}
@Component
export default class NewScript extends Script {
/** This function is called before the first frame update when the script is instanced */
protected onStart(): void {
let player = Player.localPlayer; // get character
let loc = new mw.Vector(1600, 0, 250); // set a target point
// Use navigateTo() to move the character to the target point
InputUtil.onKeyDown(mw.Keys.One, () => {
Navigation.navigateTo(player.character, loc, 10, () => {
console.log(`navigation succeeded');
}, () => {
console.log(`navigation failed');
});
});
// Use the stopNavigateTo() function to stop navigation of the specified object
InputUtil.onKeyDown(mw.Keys.Two, () => {
console.log(`Stop character wayfinding');
Navigation.stopNavigateTo(player.character);
});
}
}
How to make humanoid objects (NPCs) use navigation to continuously follow targets
- step.6
Create a Navigation Volume [see How to Use Navigation Volume]
- step.7
Create two character NPCs in the scene and set one character as the client
- step.8
Create a script in which you use the follow() method to control NPCs to follow the protagonist for automatic navigation
@Component
export default class NewScript1 extends Script {
/** This function is called before the first frame update when the script is instanced */
protected async onStart(): Promise<void> {
let player = Player.localPlayer;
let NPCforC = await mw.GameObject.asyncFindGameObjectById("216613A7") as mw.Character; // Get to client NPC by GameObject ID
// Client NPC uses follow() to start following characters
if (SystemUtil.isClient()) {
if (Navigation.follow(NPCforC, player.character)){
console.log (`Target found in Navigation Volume, start following');
Navigation.follow(NPCforC, player.character, 10, () => {
console.log (`followed target, followed success');
}, () => {
console.log(`Target not found, follow failed');
});
this.serverFollow(player.userId);
}else{
console.log(`Target not found, follow failed');
}
}
// Once you start following, use the stopFollow() function to stop the client NPC from navigation. Double-ended NPCs need to call stopFollow() on the server side;
InputUtil.onKeyDown(mw.Keys.Two, () => {
console.log(`Stop Client NPC Following}');
Navigation.stopFollow(NPCforC);
});
}
@mw.RemoteFunction(mw.Server)
serverFollow(id: string) {
let player = Player.getPlayer(id); // get the protagonist on the server side;
let NPCforSC = mw.GameObject.findGameObjectById("1CDC00EC") as mw.Character; // Get double-ended NPC from GameObject ID
Navigation.follow(NPCforSC, player.character, 10, () => {
console.log(`follow succeeded');
}, () => {
console.log(`follow failed');
});
}
}
@Component
export default class NewScript1 extends Script {
/** This function is called before the first frame update when the script is instanced */
protected async onStart(): Promise<void> {
let player = Player.localPlayer;
let NPCforC = await mw.GameObject.asyncFindGameObjectById("216613A7") as mw.Character; // Get to client NPC by GameObject ID
// Client NPC uses follow() to start following characters
if (SystemUtil.isClient()) {
if (Navigation.follow(NPCforC, player.character)){
console.log (`Target found in Navigation Volume, start following');
Navigation.follow(NPCforC, player.character, 10, () => {
console.log (`followed target, followed success');
}, () => {
console.log(`Target not found, follow failed');
});
this.serverFollow(player.userId);
}else{
console.log(`Target not found, follow failed');
}
}
// Once you start following, use the stopFollow() function to stop the client NPC from navigation. Double-ended NPCs need to call stopFollow() on the server side;
InputUtil.onKeyDown(mw.Keys.Two, () => {
console.log(`Stop Client NPC Following}');
Navigation.stopFollow(NPCforC);
});
}
@mw.RemoteFunction(mw.Server)
serverFollow(id: string) {
let player = Player.getPlayer(id); // get the protagonist on the server side;
let NPCforSC = mw.GameObject.findGameObjectById("1CDC00EC") as mw.Character; // Get double-ended NPC from GameObject ID
Navigation.follow(NPCforSC, player.character, 10, () => {
console.log(`follow succeeded');
}, () => {
console.log(`follow failed');
});
}
}
Method for dynamically modifying navigation data
After dynamic navigation is turned on, navigation data can be dynamically modified by experience running, which can be used to make navigation areas with switches such as doors and bridges. [Navigation Settings] property is added to [Settings] menu in editor to set whether to turn on dynamic navigation.
With Dynamic Navigation turned off, Navigation Volume data is built when the project is published and does not consume performance when the experience starts.
When Dynamic Navigation is turned on, the Navigation Volume in the scene is built when the experience starts. The larger the scene map, the more complex terrain collisions take to build. In the case of the OPPO A57 phone, it takes about 0.3 seconds to build 100 * 100 size terrain navigation data;
Method for dynamically modifying navigation data
- step.9 Turn on dynamic navigation in[Settings] - [World] - [Navigation]
- step.10 Set up two navigation paths in the scene and set target points
- step.11 Search for [Navigation Area modifier] in Asset Library - Gameplay Objects, place on pavement, set the area type of [Navigation Area modifier] to [Null].
- step.12 Create a script to control the area type state of the [Navigation Area modifier].
@Component
export default class NewScript2 extends Script {
/** This function is called before the first frame update when the script is instanced */
protected async onStart(): Promise<void> {
let player = Player.localPlayer;
let targetPos = new mw.Vector(1800,250,250); // set a target point
let modifierVolume =await mw.GameObject.asyncFindGameObjectById("352509AA") as mw.NavModifierVolume; //find navigation dynamic modifier area by GameObject ID
InputUtil.onKeyDown(mw.Keys.One,()=>{
Navigation.navigateTo(player.character,targetPos)
});
InputUtil.onKeyDown(mw.Keys.Two,()=>{
modifierVolume.areaClass = mw.NavModifierType.Default // Sets the navigation dynamic modifier area type to default passable;
})
}
}
@Component
export default class NewScript2 extends Script {
/** This function is called before the first frame update when the script is instanced */
protected async onStart(): Promise<void> {
let player = Player.localPlayer;
let targetPos = new mw.Vector(1800,250,250); // set a target point
let modifierVolume =await mw.GameObject.asyncFindGameObjectById("352509AA") as mw.NavModifierVolume; //find navigation dynamic modifier area by GameObject ID
InputUtil.onKeyDown(mw.Keys.One,()=>{
Navigation.navigateTo(player.character,targetPos)
});
InputUtil.onKeyDown(mw.Keys.Two,()=>{
modifierVolume.areaClass = mw.NavModifierType.Default // Sets the navigation dynamic modifier area type to default passable;
})
}
}
Open Navigation Volume Display with the Control Console Command -show Navigation When the navigation dynamic modifier type is invalid, the protagonist navigates through the side roads and reaches the target position. After changing the pathfinding dynamic modifier area type to the default passable, the main character navigates again, using a closer route to reach the target position.