Yo @Cedric … Do you have an example using the agentGoto ???
How do you handle rotation …
Here is how i am trying to handle agentGoto…
This class basically using a DUMMY Transform node to create the crowd agent… then every frame i get the agent position and calculate a rotation (of that dummy mesh as the agent) …
then i sync the real transform node i want to move.
FYI
My NavigationAgent Class :
module BABYLON {
/**
* Babylon navigation agent pro class (Unity Style Navigation Agent System)
* @class NavigationAgent - All rights reserved (c) 2020 Mackey Kinard
*/
export class NavigationAgent extends BABYLON.ScriptComponent {
private type: number;
private radius: number;
private height: number;
private climb: number;
private slope: number;
private speed: number;
private baseOffset: number;
private avoidRadius: number;
private avoidHeight: number;
private acceleration: number;
private angularSpeed: number;
private areaMask: number;
private autoRepath: boolean;
private autoBraking: boolean;
private autoTraverseOffMeshLink: boolean;
private avoidancePriority: number;
private obstacleAvoidanceType: number;
private stoppingDistance: number;
private startPosition:BABYLON.Vector3 = BABYLON.Vector3.Zero();
public heightOffset:number = 0;
public updatePosition:boolean = true;
public updateRotation:boolean = true;
public updateVelocity:number = 0.05;
public getAgentType():number { return this.type; }
public getAgentIndex():number { return this.m_agentIndex; }
public getAgentRadius():number { return this.radius; }
public getAgentHeight():number { return this.height; }
public getAgentClimb():number { return this.climb; }
public getAgentSlope():number { return this.slope; }
public getAgentSpeed():number { return this.speed; }
public getAgentOffset():number { return this.baseOffset; }
protected m_agentIndex:number = -1;
protected m_agentTrans:BABYLON.TransformNode = null;
protected m_agentParams:BABYLON.IAgentParameters = null;
protected m_agentMovement:BABYLON.Vector3 = new BABYLON.Vector3(0.0, 0.0, 0.0);
protected m_agentDirection:BABYLON.Vector3 = new BABYLON.Vector3(0.0, 0.0, 1.0);
public constructor(transform: BABYLON.TransformNode, scene: BABYLON.Scene, properties: any = {}) {
super(transform, scene, properties);
this.type = this.getProperty("type", this.type);
this.radius = this.getProperty("radius", this.radius);
this.height = this.getProperty("height", this.height);
this.climb = this.getProperty("climb", this.climb);
this.slope = this.getProperty("slope", this.slope);
this.speed = this.getProperty("speed", this.speed);
this.baseOffset = this.getProperty("offset", this.baseOffset);
this.angularSpeed = this.getProperty("angularspeed", this.angularSpeed);
this.acceleration = this.getProperty("acceleration", this.acceleration);
this.stoppingDistance = this.getProperty("stoppingdistance", this.stoppingDistance);
this.autoBraking = this.getProperty("autobraking", this.autoBraking);
this.avoidRadius = this.getProperty("avoidradius", this.avoidRadius);
this.avoidHeight = this.getProperty("avoidheight", this.avoidHeight);
this.obstacleAvoidanceType = this.getProperty("avoidquality", this.obstacleAvoidanceType);
this.avoidancePriority = this.getProperty("avoidpriority", this.avoidancePriority);
this.autoTraverseOffMeshLink = this.getProperty("autotraverse", this.autoTraverseOffMeshLink);
this.autoRepath = this.getProperty("autopepath", this.autoRepath);
this.areaMask = this.getProperty("areamask", this.areaMask);
}
protected awake(): void { this.awakeNavigationAgent(); }
protected update(): void { this.updateNavigationAgent(); }
protected destroy(): void { this.destroyNavigationAgent(); }
//////////////////////////////////////////////////////
// Navigation Private Functions //
//////////////////////////////////////////////////////
private awakeNavigationAgent():void {
BABYLON.Utilities.ValidateTransformQuaternion(this.transform);
//// DEBUG: this.m_agentTrans = BABYLON.Mesh.CreateBox((this.transform.name + "Agent"), 2, this.scene);
this.m_agentTrans = new BABYLON.TransformNode((this.transform.name + ".Agent"), this.scene);
this.m_agentTrans.position = new BABYLON.Vector3(0.0, 0.0, 0.0);
this.m_agentTrans.rotation = new BABYLON.Vector3(0.0, 0.0, 0.0);
BABYLON.Utilities.ValidateTransformQuaternion(this.m_agentTrans);
}
private updateNavigationAgent():void {
const plugin:BABYLON.RecastJSPlugin = BABYLON.SceneManager.GetNavigationTools();
const crowd:BABYLON.ICrowd = BABYLON.SceneManager.GetCrowdInterface(this.scene);
if (crowd == null) return; // Note: No Detour Navigation Mesh Available Yet
if (this.m_agentIndex < 0) {
this.m_agentParams = {
radius: this.radius,
height: this.height,
maxSpeed: this.speed,
maxAcceleration: this.acceleration,
collisionQueryRange: 0.5,
pathOptimizationRange: 0.0,
separationWeight: 1.0
};
BABYLON.Utilities.GetAbsolutePositionToRef(this.transform, this.startPosition);
this.m_agentIndex = crowd.addAgent(this.startPosition, this.m_agentParams, this.m_agentTrans);
}
if (this.updateRotation === true) {
const velocity:BABYLON.Vector3 = this.getAgentVelocity();
// ..
// TODO - Make Better Rotation Code that does not turn around or jitter at destination point
// ..
if (velocity.length() >= this.updateVelocity) {
velocity.normalize();
// TODO - Optimize compute direction
const dir:BABYLON.Vector3 = this.m_agentDirection.clone();
const factor:number = (0.005 * this.angularSpeed);
this.m_agentDirection = new BABYLON.Vector3((dir.x + (velocity.x - dir.x) * factor), (dir.y + (velocity.y - dir.y) * factor), (dir.z + (velocity.z - dir.z) * factor));
this.m_agentDirection.normalize();
// TODO - Optimize euler angle rotation
const targetAngle:number = (Math.PI * 0.5 - Math.atan2(this.m_agentDirection.z, this.m_agentDirection.x));
BABYLON.Quaternion.FromEulerAnglesToRef(0.0, targetAngle, 0.0, this.transform.rotationQuaternion);
}
}
if (this.updatePosition === true) {
const position:BABYLON.Vector3 = this.getAgentPosition();
position.y += (this.baseOffset + this.heightOffset);
this.transform.position.copyFrom(position);
}
}
private destroyNavigationAgent():void {
this.m_agentIndex = -1;
this.m_agentMovement = null;
this.m_agentDirection = null;
if (this.m_agentTrans != null) {
this.m_agentTrans.dispose();
this.m_agentTrans = null;
}
}
//////////////////////////////////////////////////////
// Navigation Public Functions //
//////////////////////////////////////////////////////
/** Move agent relative to current position. */
public move(offset: BABYLON.Vector3, closetPoint:boolean = true): void {
const plugin:BABYLON.RecastJSPlugin = BABYLON.SceneManager.GetNavigationTools();
const crowd:BABYLON.ICrowd = BABYLON.SceneManager.GetCrowdInterface(this.scene);
if (plugin != null && crowd != null) {
crowd.getAgentPosition(this.m_agentIndex).addToRef(offset, this.m_agentMovement);
if (this.m_agentIndex >= 0) crowd.agentGoto(this.m_agentIndex, (closetPoint === true) ? plugin.getClosestPoint(this.m_agentMovement) : this.m_agentMovement);
}
}
/** Teleport agent to destination point. */
public teleport(destination: BABYLON.Vector3, closetPoint:boolean = true): void {
const plugin:BABYLON.RecastJSPlugin = BABYLON.SceneManager.GetNavigationTools();
const crowd:BABYLON.ICrowd = BABYLON.SceneManager.GetCrowdInterface(this.scene);
if (crowd != null && this.m_agentIndex >= 0) crowd.agentTeleport(this.m_agentIndex, (closetPoint === true) ? plugin.getClosestPoint(destination) : destination);
}
/** Sets agent current destination point. */
public setDestination(destination: BABYLON.Vector3, closetPoint:boolean = true): void {
const plugin:BABYLON.RecastJSPlugin = BABYLON.SceneManager.GetNavigationTools();
const crowd:BABYLON.ICrowd = BABYLON.SceneManager.GetCrowdInterface(this.scene);
if (plugin != null && crowd != null && this.m_agentIndex >= 0) crowd.agentGoto(this.m_agentIndex, (closetPoint === true) ? plugin.getClosestPoint(destination) : destination);
}
/** Gets agent current world space position. */
public getAgentPosition(): BABYLON.Vector3 {
const crowd:BABYLON.ICrowd = BABYLON.SceneManager.GetCrowdInterface(this.scene);
if (crowd != null && this.m_agentIndex >= 0) return crowd.getAgentPosition(this.m_agentIndex);
else return null;
}
/** Gets agent current world space velocity. */
public getAgentVelocity(): BABYLON.Vector3 {
const crowd:BABYLON.ICrowd = BABYLON.SceneManager.GetCrowdInterface(this.scene);
if (crowd != null && this.m_agentIndex >= 0) return crowd.getAgentVelocity(this.m_agentIndex);
else return null;
}
/** Cancel current waypoint path navigation. */
public cancelNavigation():void {
// TODO - Cancel Navigation
}
}
}
So using script… i could do something like this:
const agent = this.getComponent("BABYLON.NavigationAgent");
agent.setDestination(pickedPosition);
But i get a bit rotation jitter at the end of the navigation… Im sure its cause how i am rotating the real mesh to try and sync to the GHOST transform node i used to create the agent.
Anyways… How are you moving a mesh/player around using agentGoTo ???