Avoid stationary agents in RVO

738 views
Skip to first unread message

Joey

unread,
Aug 4, 2012, 12:14:49 AM8/4/12
to recastnavigation
The red agent is what i want to move, the other two agents is
stationary
http://postimage.org/image/b5gxxxmsf/

I want to round them to the opposite, but it got stuck.
http://postimage.org/image/qfgt54ian/

I tested RVO2 library, when agent round stationary obstacle, it has
the same issue.
I searched the forum, there is a solution: when the agent is
stationary, make the agent as a obstacle and regenerate the navmesh.
But in my RTS game, there are a lot of units, regenerating navmesh
frequently isn't a good idea maybe.

Matthew Endsley

unread,
Aug 4, 2012, 11:12:14 PM8/4/12
to recastna...@googlegroups.com

Hi Joey,

The core problem is that most avoidance algorithms make the assumption that agents in the way can move put of the way of incoming agents. If you prevent those agents from moving, you'll likely get poor results.

Have you tried rasterizing the stationary agents as obstacles yet? It may not be as big of a perf hit as you think. We do this rasterization whenever a unit comes to a stop in AirMech with good results.

Matt

Joey

unread,
Aug 5, 2012, 12:10:32 AM8/5/12
to recastnavigation
Hi, Matt,

I have played AirMech,it's awsome, the movement is very nice. I will
have a try three methods:
1. Rasterizing the stationary agents, test more units to see the
performance.
2. Turn off the obstacle avoidance flag(DT_CROWD_OBSTACLE_AVOIDANCE)
of the stationary agents,
the moving agents will push the stationary agents away with physic
simulation like StarCraft2.
3. Give the neighbor stationary agents a temporary velocity towards
the calculated agent,
the stationary agents will still not move, and the calculated
agents will calculate a good
velocity to avoid the obstacle,is't possible?

On 8月5日, 上午11时12分, Matthew Endsley <mends...@gmail.com> wrote:
> Hi Joey,
>
> The core problem is that most avoidance algorithms make the assumption that
> agents in the way can move put of the way of incoming agents. If you
> prevent those agents from moving, you'll likely get poor results.
>
> Have you tried rasterizing the stationary agents as obstacles yet? It may
> not be as big of a perf hit as you think. We do this rasterization whenever
> a unit comes to a stop in AirMech with good results.
>
> Matt

Joey

unread,
Aug 19, 2012, 5:46:33 AM8/19/12
to recastna...@googlegroups.com
Hi, Mikko, i have checked out your RVO experimental project: cane, and found this:
float vab[2];
if (vlensqr(ob->vel) < sqr(0.01f))
{
// Stationary, use VO
vcpy(vab, svel);
}
else
{
// Moving, use RVO
vab[0] = svel[0]*2;
vab[1] = svel[1]*2;
vsub(vab, vab, agent->vel);
vsub(vab, vab, ob->vel);

Using VO to handle stationary agents, Is this integrated into dtCrowd? I didn't found it.

Mikko Mononen

unread,
Aug 19, 2012, 10:45:51 AM8/19/12
to recastna...@googlegroups.com
I don't think that is in dtCrowd. I cannot remember why. I guess it
caused deadlocks in some unintended situations (i.e. two agents refuse
to move because one of the stopped or something like that). If you
want to try it out, this is the place to put it:

http://code.google.com/p/recastnavigation/source/browse/trunk/DetourCrowd/Source/DetourObstacleAvoidance.cpp#328


--mikko

Joey

unread,
Aug 19, 2012, 10:38:58 PM8/19/12
to recastna...@googlegroups.com
ok, i'll try it out

在 2012年8月19日星期日UTC+8下午10时45分51秒,Mikko Mononen写道:

Joey

unread,
Aug 21, 2012, 2:40:12 AM8/21/12
to recastna...@googlegroups.com
How to know if the agent reached the goal in dtCrowd? Because i need to play stop animation and state switch. 
If i move to a unreachable target, the agent will arrive at the nearest point.
Take a look at this picture, the agent will stop at green circle. 


Joey

unread,
Aug 21, 2012, 10:36:38 PM8/21/12
to recastna...@googlegroups.com
any help?

Joey

unread,
Aug 21, 2012, 11:59:54 PM8/21/12
to recastnavigation
I'll check the dtCrowdAgent::ncorners == 0 if agent cannot move now.

Jonas

unread,
Aug 22, 2012, 5:42:30 AM8/22/12
to recastna...@googlegroups.com
Op dinsdag 21 augustus 2012 08:40:12 UTC+2 schreef Joey het volgende:
How to know if the agent reached the goal in dtCrowd?

Verify that the distance between current position of the agent and its set destination is below a certain threshold. 

Mikko Mononen

unread,
Aug 22, 2012, 6:09:51 AM8/22/12
to recastna...@googlegroups.com
Take a look at getDistanceToGoal() in detourcrowd.cpp to check if one
of the corners is the end of the path.

--mikko

Joey

unread,
Aug 22, 2012, 10:50:46 AM8/22/12
to recastnavigation
dtCrowdAgent* ag = crowd->GetAgent(index);
if (ag && ag->active)
{
const float* target = ag->cornerVerts[0];
float dist = GetDistance(target, curPosition);
if ((ag->ncorners == 0) || (ag->ncorners == 1 && dist < threshold))
{

Mikko Mononen

unread,
Aug 22, 2012, 11:38:34 AM8/22/12
to recastna...@googlegroups.com
There are odd cases where that does not produce correct results, you
should also check that the corner has DT_STRAIGHTPATH_END flag set:

if (ag->cornerFlags[ag->ncorners-1] & DT_STRAIGHTPATH_END) {
}

It is also possible that ag->ncorners == 0 is true for some time
before the agent starts moving.


--mikko

Joey

unread,
Aug 23, 2012, 3:33:52 AM8/23/12
to recastnavigation
Got it, thanks Mikko.
How to make the agent fast arrive at the goal? When the agent run into
slowDownRadius,
it will take a long time to stop.

const float slowDownRadius = ag->params.radius*2; // TODO: make less
hacky.
const float speedScale = getDistanceToGoal(ag, slowDownRadius) /
slowDownRadius;
I add a deceleration, the agent will get ahead of the goal.

Mikko Mononen

unread,
Aug 23, 2012, 4:01:04 AM8/23/12
to recastna...@googlegroups.com
Arrival behavior is really hard. I know a lot of people have a
distance threshold, say 2m proximity the goal, and when that is hit,
they just slide the character to the correct location. This can cause
problem in cases where multiple agents try to arrive at the same
location. But that is something that should be solved by the higher
level logic anyway.

The reason I have hesitated to add all this into the DetourCrowd is
that they are very game specific.


--mikko

Joey

unread,
Aug 27, 2012, 6:35:21 AM8/27/12
to recastnavigation
I want the agent to stop when it arrive in minDistance,
if (ArrivalTest(agent, minDistance))
{
crowd->resetMoveTarget();
}

but it still move.

Joey

unread,
Aug 27, 2012, 7:07:28 AM8/27/12
to recastnavigation
The full code is here:

bool CrowdManager::ArrivalTest(const dtCrowdAgent* agent)
{
assert(agent);
if (agent->ncorners <= 0)
return true;

int endIndex = (agent->ncorners - 1) * 3;

bool endOfPath = (agent->cornerFlags[agent->ncorners-1] &
DT_STRAIGHTPATH_END) ? true : false;
float distToGoal = dtVdist2D(agent->npos, &agent-
>cornerVerts[endIndex]);

if (endOfPath && (distToGoal < agent->params.arrivalDistance))
{
return true;
}

return false;
}

void CrowdManager::OnFrame(float dt)
{
if (this->crowd)
{
this->crowd->update(dt, NULL);

for (int i = 0; i < this->crowd->getAgentCount(); ++i)
{
const dtCrowdAgent* agent = this->crowd->getAgent(i);

if (!agent->active)
continue;

if (agent->targetState != DT_CROWDAGENT_TARGET_NONE &&
ArrivalTest(agent))
{
this->crowd->resetMoveTarget(i);
}
}
}
}

Mikko Mononen

unread,
Aug 29, 2012, 5:09:54 AM8/29/12
to recastna...@googlegroups.com
I think the next step is to add a movement request state which forces the agent to stay stationary. Can you add a google code issie about that?

--mikko

Sent from my iPhone

Joey

unread,
Aug 29, 2012, 9:40:57 PM8/29/12
to recastnavigation
Now i use this method, remove the agent and add new one

On 8月29日, 下午5时10分, Mikko Mononen <memono...@gmail.com> wrote:
> I think the next step is to add a movement request state which forces the agent to stay stationary. Can you add a google code issie about that?
>
> --mikko
>
> Sent from my iPhone
>

Niello

unread,
Sep 4, 2012, 9:38:00 PM9/4/12
to recastna...@googlegroups.com
Hi.

If you are still interested in this question, you may try my approach. Instead of linear slowdown

if (DistToNavDest < SlowDownRadius) Speed *= (DistToNavDest / SlowDownRadius);

you can use inverse quadratic one:

if (DistToNavDest < SlowDownRadius) Speed *= ((2 * SlowDownRadius - DistToNavDest) * DistToNavDest) / (SlowDownRadius * SlowDownRadius);

Where DistToNavDest is distance to the navigation destination and SlowDownRadius is maximum speed * arrival threshold time, 0.5f seconds in my case.
It is not too hard for modern CPUs/FPUs and looks much better as on me.


четверг, 23 августа 2012 г., 19:33:52 UTC+12 пользователь Joey написал:
Reply all
Reply to author
Forward
0 new messages