Wie kann ich in RecastNavigation einen Agenten nach Erreichen seines Ziels inaktiv machen?

8

Diese Frage befasst sich speziell mit der Recast Navigation-Bibliothek.

Ich habe einen Agenten mit hinzugefügt addAgentund sein Ziel mit festgelegt requestMoveTarget. Wenn der Agent sein Ziel erreicht, stoppt er, aber wenn er (von einem anderen Agenten) aus dem Weg geschoben wird, versucht er, zu seinem Ziel zurückzukehren. Möchten Sie stattdessen, dass es anhält und untätig wird, damit andere Agenten, die vorbeigehen, es beiseite schieben und es nicht zurückkehrt.

Ich habe versucht, resetMoveTargetin agent.nposder Nähe zu sein agent.targetPos(als ob der Agent sein Ziel erreicht hätte), aber das scheint die innere Logik der Crowd-Simulation zu brechen - der Agent würde einfach weiter in die alte Richtung gehen und niemals anhalten.

Wie kann ich einen Agenten in RecastNavigation ordnungsgemäß anweisen, anzuhalten und inaktiv (und dennoch drückbar) zu werden?

Kromster
quelle

Antworten:

2

Im Zusammenhang mit Ihrer Lösung wurde eine Korrektur vorgenommen , die die gewünschte Geschwindigkeit in zurücksetzt 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
quelle
Soweit ich mich erinnern kann, ist dies eine unvollständige Antwort. Ich bin verwirrt. Ist dies eine Antwort oder ein Kommentar zu meiner Antwort unten? Weil Sie auch den Agentenkorridor zurücksetzen müssen, damit die Agenten wirklich untätig werden (drückbar).
Kromster
OK, ich hatte vergessen, dass Ihr Problem mit dem Agenten nicht mehr zu lösen ist. Ich werde versuchen zu reproduzieren.
Leif Gruenwoldt
@KromStern Hmm, ich habe Probleme, dies zu reproduzieren. Ohne das Zurücksetzen des Cooridors können meine Agenten von anderen Agenten gedrückt werden. Ist es nötig?
Leif Gruenwoldt
Ich habe versucht, dies resetMoveTargetlokal hinzuzufügen, aber ich beobachte keinen Unterschied. ag->corridor.reset(ag->corridor.getFirstPoly(), agent->npos);
Leif Gruenwoldt
1
Aus irgendeinem seltsamen Grund kann ich es jetzt auch nicht reproduzieren. Es sieht so aus, als hätte sich seitdem etwas anderes geändert. Trotzdem vielen Dank für Ihre Teilnahme! :)
Kromster
0

Ich bin nicht sicher, aber meine Vermutung wäre, "requestMoveVelocity" auch mit dem Nullvektor auf diesem Agenten aufzurufen. Versuche es.

Rokannon
quelle
0

Hinweis: Diese Lösung scheint überflüssig zu sein, aber ich lasse sie, falls das Problem erneut auftritt.

Nach viel Dekodierung, Versuch und Irrtum nahm ich dtCrowd.resetMoveTargetals Basis und fand einen Weg, es zu ändern:

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 Der obige Code ist in Delphi, sollte aber in C ++ genauso gut funktionieren.

Der Autor der Neufassung der Navigation kommentierte:

Anstatt die Ecken zurückzusetzen, sollten Sie den Korridor auf die aktuelle Position und das erste Polygon des Agenten zurücksetzen.

Das Setzen der Zielposition auf die aktuelle Position des Agenten wird im Allgemeinen bevorzugt, als das Setzen auf 0,0,0. Aber Sie setzen auch alles andere zurück, ich denke, es ist in Ordnung.

Kromster
quelle