В RecastNavigation, как я могу заставить агента бездействовать после достижения пункта назначения?

8

Этот вопрос конкретно о работе с библиотекой Recast Navigation.

Я добавил агента с addAgentи установил его цель с requestMoveTarget. Когда агент достигает своего места назначения, он останавливается, но когда его отталкивает (другой агент), он пытается вернуться к своей цели. Вместо этого, нужно, чтобы он остановился и стал бездействующим, чтобы, когда другой агент прошел мимо, отодвинул его в сторону, и он не вернулся обратно.

Я пытался дозвониться resetMoveTargetпо agent.nposблизости к agent.targetPos(как если агент достиг своего назначения), но кажется , что нарушить внутреннюю логику симуляции толпы - агент будет просто продолжать идти в старом направлении, не останавливаясь.

Как правильно сказать агенту, чтобы он прекратил работу и стал бездействующим (хотя и нереальным) в RecastNavigation?

Kromster
источник

Ответы:

2

Вверх по течению было сделано исправление, связанное с вашим решением, которое сбрасывает желаемую скорость в 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;
 }
Лейф Грюнвольдт
источник
Насколько я помню, это неполный ответ. Я смущен. Это ответ или комментарий к моему ответу ниже? Потому что вам также нужно сбросить коридор агентов, чтобы агенты стали по-настоящему бездействующими.
Кромстер
Хорошо, я забыл о твоей проблеме с агентом, становящимся непростительным. Я постараюсь воспроизвести.
Лейф Грюнвольдт
@ KromStern Хм У меня проблемы с воспроизведением. Без сброса кооридора мои агенты могут быть вытеснены другими агентами. Это необходимо?
Лейф Грюнвольдт
Я попытался добавить это к resetMoveTargetлокально, но я не вижу разницы. ag->corridor.reset(ag->corridor.getFirstPoly(), agent->npos);
Лейф Грюнволдт
1
По какой-то странной причине я не могу сейчас воспроизвести это тоже. Похоже, что-то еще изменилось с тех пор. В любом случае, спасибо за ваше участие! :)
Кромстер
0

Я не уверен, но мое предположение должно было бы вызвать "requestMoveVelocity" с нулевым вектором также на этом агенте. Попробуйте.

Rokannon
источник
0

Примечание. Это решение кажется излишним, но я оставляю его на случай, если проблема появится снова.

После многих расшифровок, проб и ошибок я взял dtCrowd.resetMoveTargetза основу и нашел способ ее изменить:

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 Выше код находится в Delphi, но он должен работать так же хорошо в C ++.

Recast Навигация автор прокомментировал:

Вместо того, чтобы сбрасывать углы, вы должны сбросить коридор до текущей позиции агентов и первого многоугольника.

Установка целевой позиции агентам текущей позиции обычно предпочтительнее, чем установка 0,0,0. Но вы сбрасываете все остальное тоже, я думаю, это нормально.

Kromster
источник