Question about "Crowd AgentGoto"

Hello everyone,

I have a question about the “crowd.agentGoto” function. You can find the demo page where the problem occurs here. In this demo, I added the following code, which results in a peculiar error: when the agent reaches the first point, it prints “reached the point” and then proceeds to the next point as expected. The second point is very close to the agent, but it never reaches the second point (it doesn’t print “arrived at the point” a second time). As a beginner, I’m unsure if there is any misunderstanding in my approach. If possible, could you please help me with this issue? Any insights or suggestions would be greatly appreciated. Thanks!
And the full code is here

var agents = [];
var createScene = function () {

    // This creates a basic Babylon Scene object (non-mesh)
    var scene = new BABYLON.Scene(engine);
    let navigationPlugin = new BABYLON.RecastJSPlugin();

    // This creates and positions a free camera (non-mesh)
    var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(-6, 4, -8), scene);
    // This targets the camera to scene origin
    camera.setTarget(BABYLON.Vector3.Zero());
    // This attaches the camera to the canvas
    camera.attachControl(canvas, true);

    // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
    var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
    // Default intensity is 1. Let's dim the light a small amount
    light.intensity = 0.7;

    var staticMesh = createStaticMesh(scene);
    var navmeshParameters = {
        cs: 0.2,
        ch: 0.2,
        walkableSlopeAngle: 90,
        walkableHeight: 1.0,
        walkableClimb: 1,
        walkableRadius: 1,
        maxEdgeLen: 12.,
        maxSimplificationError: 1.3,
        minRegionArea: 8,
        mergeRegionArea: 20,
        maxVertsPerPoly: 6,
        detailSampleDist: 6,
        detailSampleMaxError: 1,
        };

    navigationPlugin.createNavMesh([staticMesh], navmeshParameters);
    var navmeshdebug = navigationPlugin.createDebugNavMesh(scene);
    navmeshdebug.position = new BABYLON.Vector3(0, 0.01, 0);

    var matdebug = new BABYLON.StandardMaterial('matdebug', scene);
    matdebug.diffuseColor = new BABYLON.Color3(0.1, 0.2, 1);
    matdebug.alpha = 0.2;
    navmeshdebug.material = matdebug;
    
    // crowd
    var crowd = navigationPlugin.createCrowd(10, 0.1, scene);
    
    var i;
    var agentParams = {
        radius: 0.1,
        height: 0.2,
        maxAcceleration: 4.0,
        maxSpeed: 1.0,
        collisionQueryRange: 0.5,
        pathOptimizationRange: 0.0,
        separationWeight: 1.0};
        
    for (i = 0; i <1; i++) {
        var width = 0.20;
        var agentCube = BABYLON.MeshBuilder.CreateBox("cube", { size: width, height: width }, scene);
        var targetCube = BABYLON.MeshBuilder.CreateBox("cube", { size: 0.1, height: 0.1 }, scene);
        var matAgent = new BABYLON.StandardMaterial('mat2', scene);
        var variation = Math.random();
        matAgent.diffuseColor = new BABYLON.Color3(0.4 + variation * 0.6, 0.3, 1.0 - variation * 0.3);
        agentCube.material = matAgent;
        var randomPos = navigationPlugin.getRandomPointAround(new BABYLON.Vector3(-2.0, 0.1, -1.8), 0.5);
        var transform = new BABYLON.TransformNode();
        //agentCube.parent = transform;
        var agentIndex = crowd.addAgent(randomPos, agentParams, transform);
        agents.push({idx:agentIndex, trf:transform, mesh:agentCube, target:targetCube});
    }
    
    var startingPoint;
    var currentMesh;
    var pathLine;
    var getGroundPosition = function () {
        var pickinfo = scene.pick(scene.pointerX, scene.pointerY);
        if (pickinfo.hit) {
            return pickinfo.pickedPoint;
        }

        return null;
    }
let positions = [
        new BABYLON.Vector3(-1.41, 0.2, 0.68),
        new BABYLON.Vector3(0.68, 0.2, -0.50),
        new BABYLON.Vector3(1.98, 0.2, -2.26),
    ]
    let positionIndex = 0

    var gotoDist = function() {
        startingPoint = positions[positionIndex];
        console.log(startingPoint);
        if (startingPoint) {
            var agents = crowd.getAgents();
            var i;
            for (i=0;i<agents.length;i++) {
                crowd.agentGoto(agents[i], navigationPlugin.getClosestPoint(startingPoint));
            }
        }
    }
    gotoDist();
    crowd.onReachTargetObservable.add((pickInfo) => {
        console.log('arrived the point', pickInfo);
        positionIndex++;
        gotoDist();
    });
    var pointerDown = function () {
            startingPoint = getGroundPosition();
            console.log(startingPoint)
            if (startingPoint) {
                var agents = crowd.getAgents();
                var i;
                for (i=0;i<agents.length;i++) {
                    crowd.agentGoto(agents[i], navigationPlugin.getClosestPoint(startingPoint));
                }
            }
    }
    
    scene.onPointerObservable.add((pointerInfo) => {      		
        switch (pointerInfo.type) {
			case BABYLON.PointerEventTypes.POINTERDOWN:
				if(pointerInfo.pickInfo.hit) {
                    pointerDown(pointerInfo.pickInfo.pickedMesh)
                }
				break;
                }
                });

    scene.onBeforeRenderObservable.add(()=> {
        var agentCount = agents.length;
        for(let i = 0;i<agentCount;i++)
        {
            var ag = agents[i];
            ag.mesh.position = crowd.getAgentPosition(ag.idx);
            let vel = crowd.getAgentVelocity(ag.idx);
            crowd.getAgentNextTargetPathToRef(ag.idx, ag.target.position);
            if (vel.length() > 0.2)
            {
                vel.normalize();
                var desiredRotation = Math.atan2(vel.x, vel.z);
                ag.mesh.rotation.y = ag.mesh.rotation.y + (desiredRotation - ag.mesh.rotation.y) * 0.05;
            }
        }
    });
    return scene;
};

function createStaticMesh(scene) {
    var ground = BABYLON.Mesh.CreateGround("ground1", 6, 6, 2, scene);

    // // Materials
    // var mat1 = new BABYLON.StandardMaterial('mat1', scene);
    // mat1.diffuseColor = new BABYLON.Color3(1, 1, 1);

    // var sphere = BABYLON.MeshBuilder.CreateSphere("sphere1", {diameter: 2, segments: 16}, scene);
    // sphere.material = mat1;
    // sphere.position.y = 1;

    // var cube = BABYLON.MeshBuilder.CreateBox("cube", { size: 1, height: 3 }, scene);
    // cube.position = new BABYLON.Vector3(1, 1.5, 0);
    // //cube.material = mat2;

    var mesh = BABYLON.Mesh.MergeMeshes([ground]);
    return mesh;
}

cc @Cedric

Please @cris_wang , centralize your questions in one topic and create playgrounds so we can help you.

Hi,
Thanks for your reply.
Here is the PG https://playground.babylonjs.com/#1KCCM0

In this PG, I want the agent to pass through three points following a route that I have defined. I want onReachTargetObservable to trigger when the agent reaches each point.
However, when I execute it, it prints correctly at the first point, but when the Agent continues down the route, it never reaches the second point.
Thanks.

This is weird, indeed. let me take a look.

3 Likes

Thanks a bunch! Really appreciate your help.

2 Likes