News › Forums › RAIN › General Discussion and Troubleshooting › Avoid collision with other players/AI
This topic contains 23 replies, has 4 voices, and was last updated by Neyjay 2 months, 3 weeks ago.
-
AuthorPosts
-
March 20, 2022 at 4:43 am #36796
So I have my AI walking along waypoints, but I want them to take a minor detour around other players/AI, in order for them to not pass through each other or push each other away. Like in a crowd of people when people walk by each other and avoid each other only slightly to not collide with each other.
How would I go about this?
March 20, 2022 at 5:36 am #36797Ok I figured it partially out.
I added a visual detect (around 40° horizontal and 180° vertical, with line of sight checked) and entity aspects on each character (AI and player).
Then in a custom action (which runs forever) I check if there are any aspects found. If there are check if they are too near. Then do an avoidance based on the cross vector of the difference vector between both positions (I added some randomness to the direction left or right). Then I move the character with ai.motor.moveto.This works well except that the AI now ignores the Navmesh during this movement. Trying to figure out how to get that to work now. If anyone knows anything before I can figure it out, I’d appreciate the help.
- This reply was modified 3 months, 3 weeks ago by Neyjay.
March 20, 2022 at 6:01 am #36799Ok I think I figured it mostly out now. It’s working great I think. The only thing missing is if left or right avoidance is impossible, that the AI should turn around and go back. Might do that later though.
For those who want to see how I did it, here’s the code:
using System.Collections; using System.Collections.Generic; using RAIN.Action; using RAIN.Core; using RAIN.Representation; using RAIN.Navigation; using RAIN.Navigation.Graph; using RAIN.Entities.Aspects; [RAINAction] public class AvoidCollision : RAINAction { public Expression avoidRange; private Vector3 _target; private IList<RAINAspect> _targetsToAvoid; private float range; private Vector3 between; private Vector3 avoidVector; public override void Start(RAIN.Core.AI ai) { base.Start(ai); _targetsToAvoid = ai.Senses.Match("proximity", "aObj"); if(!float.TryParse(avoidRange.ExpressionAsEntered, out range)) range = 2f; } public override ActionResult Execute(RAIN.Core.AI ai) { if(_targetsToAvoid.Count == 0) return ActionResult.SUCCESS; foreach(RAINAspect aspect in _targetsToAvoid) { if(IsTooClose(ai, aspect)) DoAvoidance(ai, aspect); } return ActionResult.SUCCESS; } public override void Stop(RAIN.Core.AI ai) { base.Stop(ai); } private bool IsTooClose(AI ai, RAINAspect aspect) { float dist = Vector3.Distance(ai.Kinematic.Position, aspect.Position); if(dist <= range) return true; return false; } private void DoAvoidance(AI ai, RAINAspect aspect) { between = ai.Kinematic.Position - aspect.Position; avoidVector = Vector3.Cross(Vector3.up, between); int direction = Random.Range(0, 100); avoidVector.Normalize(); if(direction < 50) avoidVector *= -1; if(!CheckPositionOnNavMesh(avoidVector, ai)) avoidVector *= -1; if(!CheckPositionOnNavMesh(avoidVector, ai)) { Debug.Log("Avoid not possible!"); return; } ai.Motor.MoveTo(ai.Kinematic.Position + avoidVector); } private bool CheckPositionOnNavMesh(Vector3 loc, AI ai) { RAIN.Navigation.Pathfinding.RAINPath myPath = null; if(ai.Navigator.GetPathTo(loc, 10, true, out myPath)) return true; return false; } }
Any improvements to my code are welcomed.
- This reply was modified 3 months, 3 weeks ago by Neyjay.
March 21, 2022 at 1:44 am #36814I think you’re doing awesome NeyJay. I have actually been reviewing Aron Granberg’s A* project and the use of the RVO (Reciprocal Velocity Obstacles) local avoidance solution http://arongranberg.com/astar/docs/local-avoidance.php
I created custom motion and navigator scripts allowing the character to move among waypoints and avoid other players. This is all done by creating a RainSerializableClass that derives from RAINMotor. In the override ‘Move’ method you could call A* AIPath CalculateVelocity to get the direction(dir) and then call rvoController.Move(dir). Make sure you add the RVO Controller script on your subject as defined in the link above.
It’s a bit complicated and probably not worth it really to explain in greater detail in this thread. This also depends a great deal on the use of a 3rd party navigation mesh rather than RAIN. There are other solutions to creating obstacle avoidance as you have already explored. In the past I have also reviewed:
http://gamedevelopment.tutsplus.com/series/understanding-steering-behaviors-gamedev-12732
and
Let me know if any of tis gets you thinking….
I do know RT is working on local avoidance. So some day soon it will be built in 😉
March 23, 2022 at 6:56 am #36836Yes, thanks for sharing your approach @Neyjay. I’ve been meaning to try it out, but haven’t had a chance yet.
Just to mention the RVO approach briefly, that is not an approach we’re considering for RAIN. RAIN operates on the principle of independent AI and we stay away from approaches that involve collective decision making. RVO works by calculating a set of group movements that result in collision avoidance. Everyone should feel free to use that along with Aron’s stuff if it makes sense for your game, but it won’t be officially brought in or supported by RAIN.
March 23, 2022 at 11:31 am #36844My approach is very simple but it is ai independent. Every AI will avoid in a random direction unless it isn’t possible of course.
March 23, 2022 at 11:46 am #36845@Neyjay,
thank you for the code, it seems fine, but I could not get it to work - I assume there is something wrong with my Behavior Tree that cancells the motion applied in your avoidance script. Could you share a working example?March 23, 2022 at 11:49 am #36846I should add that I use Mecanim Motor with Root Motion set to off.
March 23, 2022 at 11:56 am #36847I will be able to do that tomorrow then. It’s pretty simple. Use the custom action in parallel with the detect node. Don’t think that it will interfere with your normal movement. The avoid movement is just done in between when it is needed and then the normal movement will be continued.
March 23, 2022 at 12:40 pm #36849Thank you so much.
March 24, 2022 at 4:09 am #36858Did you get it to work? Or do you still need a working example?
March 24, 2022 at 7:09 am #36864Well, I tried for several hours, but I must be missing something very simple indeed. After your last post I added a detect node(although I thought your scripts handles detection), but the behaviour is still the same.
Attached you will find my BT screenshot (it works great, apart from collision avoidance 😉 ).
My logs indicated that AI.Senses.Match return a list that’s greater than 0, so obviously I am detecting something, but no proper avoidance occurs.Link to the screenshot:
- This reply was modified 3 months, 2 weeks ago by mandi.
March 24, 2022 at 8:53 am #36871Your detect has to repeat forever and the custom action too. That should fix your problem^^
- This reply was modified 3 months, 2 weeks ago by Neyjay.
March 24, 2022 at 9:16 am #36875Yeah, I tried with forever both for detect and custom action, but the result were strangely the same.
March 24, 2022 at 9:30 am #36877Well you say you do have targetstoavoid > 0 , so then the avoidance is the problem. You tried putting some Debug.Logs into the various methods and for-loops to see where it might be going wrong?
-
AuthorPosts
You must be logged in to reply to this topic.