A* Pathfinding Project

RVO + RichAi Problem


#1

Hi,

I decided to add RvoController to my NPC and added a new game object with RvoSimulator, I want the NPCs to avoid each other and also avoid the player, but the problem is that the npc starts “flickering” basically moving left - right really fast, any idea what I did wrong?

My NPC uses mecanim root motion for movement.

My root motion code

    private void UpdateRootMotionAnimator()
    {
        if (Time.deltaTime <= 0) return;

        Vector3 nextPosition;
        Quaternion nextRotation;

        _aStarAi.MovementUpdate(Time.deltaTime, out nextPosition, out nextRotation);
        _aStarAi.FinalizeMovement(new Vector3(_animator.rootPosition.x, nextPosition.y, _animator.rootPosition.z), nextRotation);
    }

#2

Hi

It’s hard to say. Do you have a video of this happening?
I might add though that combining RVO and root motion is veery tricky because the RVO algorithm relies on being able to move the agents in very precise directions and being able to predict how they will move. Those assumptions are broken completely when using root motion as it very rarely moves exactly like you tell it to move.


#3

Here’s a video https://gfycat.com/CookedUnkemptGenet

I also found this post and there is one guy who somehow managed to solve it, but unfortunately, he disappeared mysteriously after that. I have been trying to get use of that method CalculateMovementDelta, but no luck. I am seriously considering if I should stop using root motion, its sooo problematic with everything


#4

That looks very much like something is going wrong between the movement script and the root motion parameters. Try to visualize (using Debug.DrawRay) what the desired velocity is and all that.


#5

It looks like the two scripts are conflicting. The desired velocity is (0.0, -1.8, 0,0) no matter if RVO is active or not.

What I figured out: If I have my mecanim code + RVO + RichAi, but I DONT use

_richAi.destination = destination

so the AI has no destination, it walks only forward, but that bug is gone, mecanim works and avoidance works, but in the real world you set a destination and in that case it stops working, so I have no idea where is the problem. Setting the destination only works if root motion is disabled, it makes me think the problem isnt in my mecanim code but how RVO/RichAi communicate about the target destination.

With no destination, it works, as soon as I set a destination… it stops…

Edit:

            var delta = _rvo.CalculateMovementDelta(transform.position, Time.deltaTime);

is always 0,0,0

What works is this

            _rvo.SetTarget(Destination.position, 0.7f, 0.7f);
            var delta = _rvo.CalculateMovementDelta(transform.position, Time.deltaTime);
            transform.position = transform.position + delta;

but then the root motion isnt setting the speed is there is no point to input the speed there manually


#6

The desired velocity includes gravity, so that value means that it wants to move downwards (i.e. it is just gravity). Maybe you want to remove the y component before you set your animation values?


#7

Edit:

I finally think I solved it. The problem was that canMove (as stated in the other post) should be set to false.

        _richAi.canMove = false;

Then the max speed of the RichAi is set to 1 and Im using this code for testing root motion + rvo (basically the same thing I’ve always used)

using Pathfinding;
using UnityEngine;

namespace Assets.Scripts
{
public class CharController : MonoBehaviour {

    private RichAI _aStarAi;
    private Animator _animator;
    public bool UpdateMovement;
    public Transform Destination;

    private void Start ()
    {
        _aStarAi = GetComponent<RichAI>();
        _animator = GetComponent<Animator>();

        _aStarAi.canMove = false;

        _animator.keepAnimatorControllerStateOnDisable = true;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            _animator.SetBool("IsWalking",true);
            UpdateMovement = true;
            _aStarAi.destination = Destination.position;
        }
    }

    private void OnAnimatorMove()
    {
        if (Time.deltaTime <= 0 || !UpdateMovement) return;

        Vector3 nextPosition;
        Quaternion nextRotation;

        _aStarAi.MovementUpdate(Time.deltaTime, out nextPosition, out nextRotation);
        _aStarAi.FinalizeMovement(new Vector3(_animator.rootPosition.x, nextPosition.y, _animator.rootPosition.z), nextRotation);

    }


 }
}