William G. C. Fox

UE5 prototyping: Mantling

Created April 12, 2023

Have just started doing some UE5 fps prototyping. Currently trying to create a mantling system so when the player hits a ledge they will "climb" over it. Going to look into more systems to implement like power ups and different weapon types just hope to keep the scale down.

The mantle works on collision and takes a pointer to the player and calls a function on the player to set the RootComponent to set the player's position to above the wall. This checks that the player is facing the wall using the dot product. If the player's dot product with the wall is > 0.9, == to 1, or < -0.9. This gives a range for the player facing the wall.

	AFpsPrototypeCharacter* Pl = Cast<AFpsPrototypeCharacter>(OtherActor);

	if (Pl != nullptr)
	{
		float dot = FVector::DotProduct(Pl->GetActorForwardVector(), GetActorForwardVector());
		UE_LOG(LogTemp, Warning, TEXT("dot = %f"), dot);
		UE_LOG(LogTemp, Warning, TEXT("Overlapping"));
		
		if (dot > 0.9 || dot < -0.9 || dot == 1)
		{
			Pl->SetLocation(endPos);
		}

	}
	else
	{
		UE_LOG(LogTemp, Error, TEXT("Not cast"));
		return;
	}

The player has to have they're weapon away to "climb" the wall. I added a switch that puts the weapon and then stops firing with out removing the mapping. I adapted the UE5 generated code from the UE5 generated code so I could increase my knowledge of adapting code given to me.

//Switch the weapon on and off 
void AFpsPrototypeCharacter::SwitchWeapon()
{
	UE_LOG(LogTemp, Warning, TEXT("Switch Weapon Hit"));
	if (weapon == nullptr) 
	{ 
		UE_LOG(LogTemp, Error, TEXT("No Weapon"));
		return; 
	}
	
	if (switchbool)
	{
		UE_LOG(LogTemp, Warning, TEXT("Weapon True, Switching weapon off"));
		switchbool = false;
		weapon->StopFiring(switchbool); //Stops the firing of the gun
		weapon->SetActive(switchbool);
		
		SetHasRifle(switchbool);
		
	}
	else 
	{
		UE_LOG(LogTemp, Warning, TEXT("Weapon False, Switching weapon on"));
		switchbool = true;
		weapon->SetActive(switchbool);
		weapon->StopFiring(switchbool);
		SetHasRifle(switchbool);
	}
}

//Modified fire 

void UTP_WeaponComponent::Fire()
{


	if (bcanfire == false) { return; } //this is added to stop firing

	// Try and fire a projectile
	if (ProjectileClass != nullptr)
	{
		UWorld* const World = GetWorld();
		if (World != nullptr)
		{
			APlayerController* PlayerController = Cast<APlayerController>(Character->GetController());
			const FRotator SpawnRotation = PlayerController->PlayerCameraManager->GetCameraRotation();
			// MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle position
			const FVector SpawnLocation = GetOwner()->GetActorLocation() + SpawnRotation.RotateVector(MuzzleOffset);
	
			//Set Spawn Collision Handling Override
			FActorSpawnParameters ActorSpawnParams;
			ActorSpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding;
	
			// Spawn the projectile at the muzzle
			World->SpawnActor<AFpsPrototypeProjectile>(ProjectileClass, SpawnLocation, SpawnRotation, ActorSpawnParams);
		}
	}
	
}

void UTP_WeaponComponent::StopFiring(bool newFire)
{
	bcanfire = newFire;
}

When the player jumps it checks that the player is off the ground then using the movement component checks if the player is off the ground. I did this by saving a pointer to the character movement component and getting if the character is grounded or not. With these conditions met the player then "mantles" to the specified edge.``` void AFpsPrototypeCharacter::SetLocation(FVector newLocation) { UCharacterMovementComponent* Movement = GetCharacterMovement();

if (Movement != nullptr) 
{
	bool grounded = Movement->IsMovingOnGround();
	UE_LOG(LogTemp, Warning, TEXT("isGrounded: %s"), (grounded ? TEXT("true") : TEXT("false")));
	if (grounded == false && bHasRifle == false) 
	{
		RootComponent->SetWorldLocation(newLocation);
	}
	else
	{
		return;
	}		
	
}
else 
{
	return;
}

}