In RecastNavigation, come posso rendere inattivo un agente dopo aver raggiunto la sua destinazione?


8

Questa domanda riguarda in particolare la gestione della libreria di navigazione di rifusione.

Ho aggiunto un agente con addAgente impostato il suo obiettivo con requestMoveTarget. Quando l'agente raggiunge la sua destinazione, si ferma, ma quando viene spinto via (da un altro agente) proverà a tornare al suo obiettivo. Invece, vuoi che si fermi e diventi inattivo, in modo che quando un altro agente cammina spingendolo da parte e non tornerà indietro.

Ho provato a chiamare resetMoveTargetsu di agent.nposessere vicino a agent.targetPos(come se l'agente ha raggiunto la sua destinazione), ma che sembra rompere la logica interna della simulazione folla - l'agente sarebbe solo continuare a camminare nella vecchia direzione, senza mai fermarsi.

Come posso correttamente dire a un agente di fermarsi e diventare inattivo (ma pushable) in RecastNavigation?

Risposte:


2

È stata apportata una correzione a monte relativa alla soluzione che reimposta la velocità desiderata 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;
 }

Per quanto ricordo, questa è una risposta incompleta. Non ho capito bene. Questa è una risposta o un commento alla mia risposta qui sotto? Perché è anche necessario ripristinare il corridoio degli agenti, in modo che gli agenti diventino veramente inattivi (pushable).
Kromster,

OK, mi ero dimenticato del tuo problema con l'agente che diventava inutilizzabile. Proverò a riprodurre.
Leif Gruenwoldt,

@KromStern Hmm Non riesco a riprodurlo. Senza il reset del cooridor i miei agenti sono stimolabili da altri agenti. È necessario?
Leif Gruenwoldt,

Ho provato ad aggiungere questo a resetMoveTargetlivello locale ma non osservo alcuna differenza. ag->corridor.reset(ag->corridor.getFirstPoly(), agent->npos);
Leif Gruenwoldt,

1
Per qualche strana ragione non riesco nemmeno a riprodurlo ora. Sembra che qualcos'altro sia cambiato da allora. Comunque, grazie per la tua partecipazione! :)
Kromster

0

Non sono sicuro, ma la mia ipotesi sarebbe quella di chiamare "requestMoveVelocity" anche con zero-vector su quell'agente. Provaci.


0

Nota: questa soluzione sembra superflua, ma la lascio nel caso in cui il problema riappaia.

Dopo molte decodifiche, tentativi ed errori ho preso dtCrowd.resetMoveTargetcome base e ho trovato il modo di 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 Il codice sopra è in Delphi, ma dovrebbe funzionare altrettanto bene in C ++.

L'autore della navigazione di rifusione ha commentato:

Invece di ripristinare gli angoli, è necessario ripristinare il corridoio alla posizione corrente degli agenti e al primo poligono.

L'impostazione della posizione target su quella corrente degli agenti è generalmente preferita, piuttosto che impostarla su 0,0,0. Ma stai ripristinando anche tutto il resto, penso che vada bene.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.