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.

Viewing 15 posts - 1 through 15 (of 24 total)
  • Author
    Posts
  • #36796

    Neyjay
    Participant

    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?

    #36797

    Neyjay
    Participant

    Ok 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.
    #36799

    Neyjay
    Participant

    Ok 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.
    #36814

    CodersExpo
    Participant

    I 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 😉

    #36836

    prime
    Keymaster

    Yes, 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.

    #36844

    Neyjay
    Participant

    My approach is very simple but it is ai independent. Every AI will avoid in a random direction unless it isn’t possible of course.

    #36845

    mandi
    Participant

    @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?

    #36846

    mandi
    Participant

    I should add that I use Mecanim Motor with Root Motion set to off.

    #36847

    Neyjay
    Participant

    I 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.

    #36849

    mandi
    Participant

    Thank you so much.

    #36858

    Neyjay
    Participant

    Did you get it to work? Or do you still need a working example?

    #36864

    mandi
    Participant

    Well, 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:
    behaviour tree

    • This reply was modified 3 months, 2 weeks ago by  mandi.
    #36871

    Neyjay
    Participant

    Your 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.
    #36875

    mandi
    Participant

    Yeah, I tried with forever both for detect and custom action, but the result were strangely the same.

    #36877

    Neyjay
    Participant

    Well 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?

Viewing 15 posts - 1 through 15 (of 24 total)

You must be logged in to reply to this topic.