Problems with navigation system and cursor bounding

Hello everyone!

I’ve recently started playing with the topdown sample after a year or so to see if things have improved.

While there seems to be a bit more polish now, I still found two rather odd problems, one I would simply like to warn about if someone else was to run into it, and one problem I’m still looking for a good solution for.

(1) The first problem was getting ClipCursor (confining the mouse to the screen / region of the screen) to work. Calling any combination of SetInputMode / LockCursorToView / LockMouseToWidget was unexpectedly uncooperative. I ran into several problems, sometimes the cursor would not be confined at all, sometimes it would confine the cursor until you pressed a mouse button, sometimes it would work intermittently. The most common symptom was the second one by far however. I debugged this quite a bit, first using profiling / breakpoints, but after no luck I started binary search debugging it using the strategy game sample and finally found that setting bShowCursor in my playercontroller was causing the strange behavior! Really quite bizarre. I followed the usage of this variable through all lines I could find, but I couldn’t really find a root cause. It has to be some OS interaction going on here is what I figure at the moment. In any case,

**simply not setting bShowCursor to true, calling setinputmode on LMB up (to make sure we reget the capture focus after an alt-tab) and drawing my own cursor fixed the problem. **

(2) The second problem I had, that I have not solved yet, was getting multiple pawn pathfinding to work.
The problem here is that as soon as you add more than one pawn, and order them to run to some point, if they happen to collide on the way, they either fly away hand in hand (yes, they literally fly away into the sky) if you have CanCharStepUp enabled, and if disabled, they seem to throw each other away, I assume to prevent their colliders from clipping into each other or some interaction like that.
I played around with this quite a bit the last time I fiddled with this sample, and there didn’t seem to be any solution to the problem back then. It still also does seem to be a problem unfortunately. I don’t seem to be alone anymore with the problem either, I found a couple of people describing the same problems… here is one for example:

I’ve also tried RVO and detour (PathFollowingComponent) to see if I could get them to not run into each other. Much like this other poster mentions, this does decrease the collision frequency, but it still happens, and as such is not very usable.

I’m going to play around a bit more with this problem, but I’m very interested to hear if someone else already knows what causes this problem, and has an idea for a solution.

Best regards,

Here is a video showing the quite funny effect of the bug (this is with CanStepUp activated):

Here is the code I use to set up my movementcomponent (in ctor of the character class):

UCharacterMovementComponent* CharacterMovement = GetCharacterMovement();
if (CharacterMovement)
	CharacterMovement->UpdatedComponent = GetCapsuleComponent();
	CharacterMovement->GetNavAgentPropertiesRef().bCanJump = true;
	CharacterMovement->GetNavAgentPropertiesRef().bCanWalk = true;
	CharacterMovement->bUseControllerDesiredRotation = true;
	CharacterMovement->bAlwaysCheckFloor = false;
	CharacterMovement->bUseRVOAvoidance = true;

Here is the code I use when issuing commands for the characters:

void ASelectableCharacter::MoveToLocation(const FVector& Destination)
	/** The nav system seems to stop the characters when the outer part of their model reaches the target.
	and not when they are centered on it, so we overshoot to adjust for this*/
	auto Direction = Destination - GetActorLocation();
	auto ActualDestination = Destination + Direction * GroundRadius;

	UNavigationSystem* const NavSys = GetWorld()->GetNavigationSystem();
	float const Distance = FVector::Dist(Destination, GetActorLocation());
	// We need to issue move command only if far enough in order for walk animation to play correctly
	if (NavSys && (Distance > MoveDistanceDeadZoneRadius))
		NavSys->SimpleMoveToLocation(Controller, ActualDestination);

I should expect that the character being thrown about is an issue with the interaction between the collision capsules. I think whats happening is that the movement component isn’t correctly handling the case where collision capsules touch but instead keeps applying force to move the character, eventually reaching enough force to cause the behavior you see. I’ve seen it happen when I’ve got a few agents moving around each other. It does diminish if you use the detour crowd pathfollowing component rather than the normal one. Best bet is to handle the capsule collisions yourself and either stop or do something like sidestepping or some such. I also remember seeing a checkbox that determines who handles the collision between the capsules. Might be on the movement component.

Its definitely fixable for sure. Just low on my list of things to work on right now :slight_smile:

Hey zoombapup!

Thanks for the input, it’s greatly appreciated :slight_smile:
I didn’t see much of a difference when using detour/recast/pathfollowingcomponent unfortunately compared to the standard RVO, it might just be how the topdown sample’s environment is set up. I’m currently playing around with custom collision just like you also suggested, so hopefully I can find a solution there that works out.

I’m really interested in that last checkbox you are talking about, I’m definitely going to check that out to see if I can find it, and if it has any effect :slight_smile:

Best regards and happy holidays,

I found the problem with the navigationsystem. I made a mistake when setting up detour, and tried to use InitNavigation to set up the component since I didnt want to use the ObjectInitializer (I’m trying to use the GENERATED_BODY macro instead of GENERATED_UCLASS_BODY as much as I can since I like the simple constructor pattern more).

Unfortunately, using InitNavigation either in the ctor or in beginplay doesn’t seem to have any effect!
I found this out by trying to access the component and casting it to the crowdfollowing one in tick later on.

Anyways, using

ASelectableCharacterAIController::ASelectableCharacterAIController(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer.SetDefaultSubobjectClass<UCrowdFollowingComponent>(TEXT("PathFollowingComponent")))

And restarting the engine seems to have done the trick.

Best regards,