Hey,
Ive encountered an issue with the detour crowd. In our game we have some AI agents that uses the detour crowd avoidance and we have implemented the `ICrowdAgentInterface` on our player character so that the agents don’t just run into the player.
However one of our developers noticed that occasionally our AI still Ignores the player and just walks into him.
I checked with the detour crowd avoidance debug drawing `ai.crowd.DebugSelectedActors` and it seemed like the player was not detected as a neighbor of the AI agent anymore.
(See the screenshot. The white sphere is the player character and the selected actor is the AI agent)
Then after double checking that the `groupsToAvoid` and `groupsToIgnore` are setup correctly I believe I traced the issue down to the function `dtCrowd::updateStepCorridor` in `DetourCrowd.cpp`.
dtCrowdAgent* ag = m_activeAgents[i];
if (ag->state != DT_CROWDAGENT_STATE_WALKING)
continue;
// Move along navmesh.
m_navquery->updateLinkFilter(ag->params.linkFilter.Get());
const bool bMoved = ag->corridor.movePosition(ag->npos, m_navquery, &m_filters[ag->params.filter]);
if (bMoved)
{
// Get valid constrained position back.
dtVcopy(ag->npos, ag->corridor.getPos());
}
// If not using path, truncate the corridor to just one poly.
if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
{
ag->corridor.reset(ag->corridor.getFirstPoly(), ag->npos);
}
In here the agent location of the player is constrained to its corridor which in this case is just the navmesh polygon on which he is located If I understand correctly. But if the player moves off the navmesh his crowd agent location is still clamped to the navmesh which causes other agents to incorrectly avoid him.
When the player then again enters onto the navmesh his location is sometimes not updated as well which causes the issue we had where AI agents don’t avoid the player at all because the player agents location is outside the range where they would detect him as a neighbor.
From my testing moving the part of the function where the corridor is truncated before the part where we handle moving along navmesh seems to fix this issue.
dtCrowdAgent* ag = m_activeAgents[i];
if (ag->state != DT_CROWDAGENT_STATE_WALKING)
continue;
// If not using path, truncate the corridor to just one poly.
if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
{
ag->corridor.reset(ag->corridor.getFirstPoly(), ag->npos);
continue;
}
// Move along navmesh.
m_navquery->updateLinkFilter(ag->params.linkFilter.Get());
const bool bMoved = ag->corridor.movePosition(ag->npos, m_navquery, &m_filters[ag->params.filter]);
if (bMoved)
{
// Get valid constrained position back.
dtVcopy(ag->npos, ag->corridor.getPos());
}
My questions are the following then:
- Is it intended that agents that are not necessarily on the navmesh are constrained to the navmesh for detour crowd avoidance?
- Could this be fixed? (our company has a strict no engine modification policy)
Kind Regards, Daan.
[Attachment Removed]