RVO Avoidance in Chaos Vehicles

I’m attempting to switch from the PhysX vehicles system to Chaos converting from UE4 to UE5 and noticed that RVO Avoidance is not part of the vehicle movement component in Chaos. I had been using this functionality heavily from UWheeledVehicleMovementComponent in PhysX and noticed that UChaosVehicleMovementComponent does not extend IRVOAvoidanceInterface and lacks this functionality. Does the Chaos Vehicles system have an equivalent or do I need to now rebuild this useful feature myself now?

Currently in the process of implementing this myself as a separate component. I wanted to make it a UActorComponent and have the ability to attach it to my AIController since I only want this behavior for AI-controlled pawns. Unfortunately due to what I would consider an interface bug, the class implementing the IRVOAvoidanceInterface interface must also be a base class of UMovementComponent to work with UAvoidanceManager - the brains behind the RVO avoidance system. To me this makes no sense because in the UAvoidanceManager, the members taking UMovementComponent just cast the input to the interface and invokes no direct members of UMovementComponent itself. The parameter should just have been of type IRVOAvoidanceInterface to provide maximum flexibility of the interface and apply the dependency inversion principle.

Example in the source (5.0.2)

void UAvoidanceManager::UpdateRVO(UMovementComponent* MovementComp)
{
	if (IRVOAvoidanceInterface* AvoidingComp = Cast<IRVOAvoidanceInterface>(MovementComp))
	{
		FNavAvoidanceData NewAvoidanceData(this, AvoidingComp);
		UpdateRVO_Internal(AvoidingComp->GetRVOAvoidanceUID(), NewAvoidanceData);
	}
}

// ....

bool UAvoidanceManager::RegisterMovementComponent(UMovementComponent* MovementComp, float AvoidanceWeight)
{
	if (IRVOAvoidanceInterface* AvoidingComp = Cast<IRVOAvoidanceInterface>(MovementComp))
	{
		const int32 NewAvoidanceUID = GetNewAvoidanceUID();
		AvoidingComp->SetRVOAvoidanceUID(NewAvoidanceUID);
		AvoidingComp->SetRVOAvoidanceWeight(AvoidanceWeight);

		RequestUpdateTimer();

		FNavAvoidanceData AvoidanceData(this, AvoidingComp);
		UpdateRVO_Internal(NewAvoidanceUID, AvoidanceData);

		return true;
	}

	return false;
}

To avoid a breaking change another set of overloads could be added similar to what was done here with UMovementComponent - probably to support the original PhysX vehicle component use case as the original methods took UCharacterMovementComponent:

This would be my recommendation:

void Register(IRVOAvoidanceInterface*);
FVector GetAvoidanceVelocity(IRVOAvoidanceInterface*);

For now I punted and just made the component subclass UMovementComponent even though it is going to manipulate the controlled pawn’s vehicle movement component.

If I end up building from source in the future I may look to submit a patch myself.

I’ll keep this thread posted as I continue working my way through this and share any insights I find.

1 Like

So I’ve gotten this working to my liking. Discovered very quickly that this cannot be an actor component on an AIController as even though we don’t want to update the movement on player controlled vehicles, the Avoidance system needs to know about them in order to avoid running into them :slight_smile: So this must be an actor component of your vehicle pawn class as was in PhysX. What’s not necessary is for it to be your actual VehicleMovementComponent.

Also added a simple way to toggle the avoidance component on/off (swerving behavior) and the system as a whole.

Turn on/off swerving behavior:
void SetAvoidanceEnabled(bool bEnable)
Turn on/off system as a whole (defaults to enabled):
static void SetAvoidanceSystemEnabled(bool bEnable)

Here is a gist to the files that make up a working solution:

1 Like