En RecastNavigation, ¿cómo puedo hacer que un agente esté inactivo después de llegar a su destino?

8

Esta pregunta es específicamente acerca de cómo tratar con la biblioteca Recast Navigation.

He agregado un agente con addAgenty establecí su objetivo con requestMoveTarget. Cuando el agente llega a su destino, se detiene, pero cuando otro agente lo empuja (intentará volver a su objetivo). En cambio, desea que se detenga y quede inactivo, de modo que cuando otro agente camine empujándolo a un lado y no regrese.

He intentado llamar resetMoveTargetal agent.nposestar cerca agent.targetPos(como si el agente hubiera llegado a su destino), pero eso parece romper la lógica interna de la simulación de la multitud: el agente simplemente seguiría caminando en la dirección anterior, sin detenerse nunca.

¿Cómo le digo correctamente a un agente que se detenga y quede inactivo (pero empujable) en RecastNavigation?

Kromster
fuente

Respuestas:

2

Se realizó una corrección aguas arriba relacionada con su solución que restablece la velocidad deseada resetMoveTarget.

bool dtCrowd::resetMoveTarget(const int idx)
 {
    if (idx < 0 || idx >= m_maxAgents)
        return false;

    dtCrowdAgent* ag = &m_agents[idx];

    // Initialize request.
    ag->targetRef = 0;
    dtVset(ag->targetPos, 0,0,0);
    dtVset(ag->dvel, 0,0,0); // <<-- This line added
    ag->targetPathqRef = DT_PATHQ_INVALID;
    ag->targetReplan = false;
    ag->targetState = DT_CROWDAGENT_TARGET_NONE;

    return true;
 }
Leif Gruenwoldt
fuente
Hasta donde puedo recordar, esta es una respuesta incompleta. Estoy confundido. ¿Es esta una respuesta o un comentario a mi respuesta a continuación? Porque también necesita restablecer el corredor de agentes, para que los agentes se vuelvan realmente inactivos (empujables).
Kromster
OK, me olvidé de que tu problema con el agente se volvió inutilizable. Trataré de reproducirme.
Leif Gruenwoldt
@KromStern Hmm Tengo problemas para reproducir esto. Sin el reinicio del cooridor, mis agentes son empujables por otros agentes. ¿Es necesario?
Leif Gruenwoldt
Intenté agregar esto a resetMoveTargetnivel local pero no observo una diferencia. ag->corridor.reset(ag->corridor.getFirstPoly(), agent->npos);
Leif Gruenwoldt
1
Por alguna extraña razón, tampoco puedo reproducirlo ahora. Parece que algo más ha cambiado desde entonces. De todos modos, ¡gracias por su participación! :)
Kromster
0

No estoy seguro, pero supongo que también debería llamar "requestMoveVelocity" con cero-vector en ese agente. Darle una oportunidad.

Rokannon
fuente
0

Nota: Esta solución parece ser superflua, pero la dejo en caso de que el problema vuelva a aparecer.

Después de mucha decodificación, prueba y error, tomé dtCrowd.resetMoveTargetcomo base y encontré una forma de modificarlo:

procedure TKMTerrainNavigation.AgentTargetClear(aIdx: Integer);
var
  ag: PdtCrowdAgent;
begin
  ag := fRecastCrowd.getAgent(aIdx);

  ag.targetRef := 0;
  dtVset(@ag.targetPos[0], 0, 0, 0);
  ag.targetPathqRef := DT_PATHQ_INVALID;
  ag.targetReplan := False;
  ag.targetState := DT_CROWDAGENT_TARGET_NONE;

  // Reset desired velocity
  dtVset(@ag.dvel[0], 0, 0, 0); 

  // Reset agents corridor so that agent won't try to walk back to his last corner
  ag.ncorners := 0;
end;

PS El código anterior está en Delphi, pero debería funcionar igual de bien en C ++.

El autor de navegación refundida comentó:

En lugar de restablecer las esquinas, debe restablecer el corredor a la posición actual de los agentes y al primer polígono.

Por lo general, se prefiere establecer la posición de destino en la posición actual de los agentes, que establecerla en 0,0,0. Pero también está restableciendo todo lo demás, creo que está bien.

Kromster
fuente