How to make a non-simulating actor apply forces to all simulating actors it bumps against? (in custom movement component)

So I’ve been trying to make a custom movement component for a 3d platformer character for some time now. I’ve been mostly succesful, I made a movement component with multiple movement modes and a good amount of parameters that can be edited/set in blueprints.
One thing I could not entirely do, however, is make the character properly interact with physics simulating objects.

I was able to make the character apply a force to any actor it touches, however it only applies a force to the first object it touches. So if the character bumps into a single physics simulating box, the box will move correctly. However, if the character is already in contact with an object and touches a second object, it will not apply a force to the second object until it stops touching the first. In other words, it only applies a force to one object at a time.

How can I make it apply a force to a second and third objects? Any suggestion would be appreciated.

could you show us what you’re doing right now?

1 Like

(Sorry, I should’ve included the code in the post)

When moving the character, if it bumps into an object, it applies a force to it and also slides along its side (it works as intended up to this point). Then, if it bumps into another object, it also tries to apply a force to it (however this part does not work, it doesn’t apply a force to the second object, only the first). Here’s the code for the movement part:

void UPlatformerMovementComponent::ApplyMovementInput(float DeltaTime)
{

	FVector DesiredMovementThisFrame = ConsumeInputVector();

	if (!DesiredMovementThisFrame.IsNearlyZero())
	{
		FHitResult Hit;

		//Safe move character.
		SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit);

		//If we bump into something...
		if (Hit.IsValidBlockingHit())
		{
			AActor* FirstHitActor = Hit.GetActor();

			//apply force to it...
			ApplyForceToHitObject(DesiredMovementThisFrame, Hit, DeltaTime);

			//Compute new slide desired movement (for future use):
			FVector SlideMovementVector = ComputeSlideVector(DesiredMovementThisFrame, Hit.Time, Hit.Normal, Hit);

			//then slide along its side.
			SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit, true);

			//Store new slide desired movement to desired movement this frame (for future use):
			DesiredMovementThisFrame = SlideMovementVector;


			//And if we bump into second object...
			if (Hit.IsValidBlockingHit())
			{

				//apply force to it too.
				ApplyForceToHitObject(DesiredMovementThisFrame, Hit, DeltaTime);

				AActor* SecondHitActor = Hit.GetActor();

				SlideMovementVector = ComputeSlideVector(DesiredMovementThisFrame, Hit.Time, Hit.Normal, Hit);

				SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit);

				DesiredMovementThisFrame = SlideMovementVector;


			}
			else
			{
				//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("No second valid blocking hit "));
			}

		}

		
	}
	
}

And here is the function that actually applies force to the objects:

void UPlatformerMovementComponent::ApplyForceToHitObject(FVector DesiredMovementThisFrame, FHitResult& Hit, float DeltaTime)
{
	//if we bump into physics simulating object, apply force to it
	if (Hit.GetComponent() && Hit.GetComponent()->IsSimulatingPhysics())
	{

		//Calculate force vector:
		FVector Force = DesiredMovementThisFrame.ProjectOnTo(Hit.Normal * -1.f) * CharacterMass / DeltaTime;

		//Add force along normal of impoact (less realistic but avoids some issues):
		Hit.GetComponent()->AddForceAtLocation(Force, Hit.Location);
		//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Applying force to " + Hit.GetActor()->GetActorNameOrLabel() + "\n Force vector: " + Force.ToString()));
	}
	else
	{
		//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Ttried to apply force to " + Hit.GetActor()->GetName() + " but is not simulating physics"));
	}
	
}