Preventing agents from going to edges near obstacles

Hey,

Is there any simple way to prevent an agent to be able to move to the edge of a node if that node is next to an obstacle?

Here’s a couple of examples:

GOOD:
Screenshot_1

BAD:
Screenshot_2

ALSO BAD:
Screenshot_3

When a behavior tree controls an agent’s AI, it always perfectly goes to the center of the node. However, when I manually control an agent, I am able to tell him to move to these odd locations.

I’m looking for the simplest solution possible. Is there any other way to do this other than with erosion?

Hi

Maybe what could work for you is to offset the whole graph by 0.5 nodes in both directions (change the center field on the grid graph by 0.5 times the node size). I think that will make the node boundaries line up with where you want them.

Hey - sorry for the delayed response.

I tried fiddling with the settings how you said but I don’t think I understand what I’m supposed to do.
Could you give me a more concrete example given my current settings? Here’s the screenshot:

Screenshot_1

I did more testing and just to clarify, what happens is that when an agent is told to move from a walkable tile onto a position that’s an obstacle, he’ll move as close as he can get but that means he’s clipping into the wall, and then he stops there, like so:

Screenshot_2 Screenshot_3

@aron_granberg Any chance you could help me out here? I’d really appreciate it. :smiley:

My idea was that by offsetting the graph by 0.5 nodes you could get something like this:
image

Note that the graph has a margin of 0.5 nodes to the walls.

Hey Aron.

I’m having issues with this again because due to RVO agents are pushing each other very close to the edge of the map, and then my internal code gets confused because no agent should be able to walk that close to the void (edge of map).

Is there now perhaps any way to limit the agents movement? Something that would be very useful is the ability to limit RVO agents to the walkable surface by using their radius field. The same way they stay away from each other and respect the radius circle, why can’t the same be done with obstacles?

I know you said that any blue area is legal to walk on, but with the addition of the above suggestion it would fix my problem, without having to meddle with settings or erosion which doesn’t fit into my game.

@aron_granberg

I’ve been experimenting with a lot of stuff and I think my suggestion could be a solution to agents getting through diagonal gaps, outside of the map or too close to obstacles.

I’m pretty bad at math so I’m not sure how to implement this, but all we need to check is if the agent’s radius (yellow circle) is colliding with an obstacle (any edge of any obstacle, such as a wall or the edge of the map), and then in MovementUpdateInternal we just tell it nextPosition = position, aka don’t go in that direction if you’d be getting “into” an obstacle. Do you have any ideas for how to implement this?

Note: the agents already do this with each other (push each other around) so I’m thinking we might be able to reuse that logic, except we stop movement instead of pushing.

This is possible to implement, but it requires some changes to the local avoidance system and a whole bunch of math. Not insurmountable by any means, but it’s a larger task that I haven’t had the time to work on yet.

That would not work. That would just make the agent stop dead when it collides with a wall, and then it would freeze there forever. You would need to move the agent to the closest point where it does not collide with the wall anymore. Essentially a simple physics engine.

Generally, navmeshes in this package are defined as the surface where it’s valid for the center of the agents to be. So from that perspective, I would still recommend the approach about changing the graph that I mentioned above.

Hi. Thank you. Even though I understand the idea behind your proposal, this is not a good solution for my game.

The first reason is (as shown in the picture) that an agent wouldn’t be able to pass through a gap between two walls. Secondly, I rely heavily on my data structures accurately representing my world. If I had a 100x100 grid, I need to know exactly what is where and which nodes are walkable. In this case, walkable nodes seem normal, but the obstacles would be not at exact node coordinates but at offsets, which would make my life a living hell in regards to coding logic.

This is possible to implement, but it requires some changes to the local avoidance system and a whole bunch of math. Not insurmountable by any means, but it’s a larger task that I haven’t had the time to work on yet.

As I am utterly horrible in math, would it be crazy of me to ask you to implement this as part of the package? I understand this is a niche problem, but it would go well with the RVO system and should be achievable out of the box.

Hmm. Is it possible for you to use 2D colliders on the obstacles and the agent to do this?

As of right now, I have several other larger systems I am rebuilding, and that I think I have to prioritize higher, I’m afraid. So I don’t think I would be able to get to that task in the foreseeable future :confused:

Hey, just wanted to let you know that I tried using 2D colliders and it works perfectly. I have, however, disabled agents colliding with others agents via Rigidbodies, so now RVO collision still works for agents and 2D collision is used for terrain-collision.

I do have a question though. In my game, a player can switch between controlling a character by “possessing it” which uses input from the keyboard for the movement (no pathfinding). In other cases, the character becomes an agent and uses AI to move (uses pathfinding and RVO). It seems like collisions with RVO still work perfectly no matter if it’s an agent-agent, agent-player, or player-player collision, but I’m wondering if there is anything I should pay attention to, or will this just work out of the box?

Great!

If you want other RVO agents to avoid it more intelligently (i.e. they will see the agent as a moving obstacle instead of a static obstacle) then you should set rvoComponent.velocity to the velocity you are moving the player with every frame.
See RVOController - A* Pathfinding Project
Note that this property doesn’t work in the beta version right now due to a bug (it will be fixed in the next beta).

Another approach to controlling an agent is to set the destination of the agent to a point a small distance (e.g. 3 meters) away from the agent based on the WASD keys. Then pathfinding will also allow it to avoid small obstructions in a natural way. You should probably set the RVOController’s priority to a very high value in that case, to make the player character have priority. Or even more extreme, you can make the player controlled character just not avoid other characters at all (the other ones would still avoid this agent).

I really need fine-tuned movements so I’ll stick to the player giving input approach instead of setting the destination.

I’ve logged an agent’s RVO velocity when moving purely to the right and it’s (3.8, 0, 0). However, I control my character via input by using Rigidbody2D.MovePosition, and when I log the Rigidbody velocity it seems to be (0, 0, 0) (presumably because I control it directly and not via forces). I know this is sort of unrelated, but do you know how I could get a characters velocity when it’s being moved by the player, so that it’s similar to the velocity I’d get when moving with RVO?

I think GetComponent<IAstarAI>().velocity will give you what you want.

Unfortunately, that still returned a zero vector. I have however switched from Rigidbody.MovePosition to Rigidbody.AddForce and the rigidbody seems to produce a similar velocity as it would if it was RVO controlled, so I can use that. Thanks you for the help!

I’m wondering if something like this has perhaps been implemented. Agents can still push each other through diagonal walls, and using their “radius” for collision with walls would be very useful to prevent that. I can’t use 2D colliders because a) they’re very expensive on a large number of units and large maps and b) it seems like having a 2d collider (and a rigidbody) screws with the movement of seeker/aipath scripts - it gets very jittery