I couldn’t think of a proper name for this style of movement.
Basically, I want to create a Dark Souls type movement. It’s 3rd Person Camera, the camera is unlocked and can be rotated freely, and the player moves according to the camera view. Forward goes away from the camera, back goes towards the camera, and left/right is based on the camera as well.
https://youtu.be/RhiOxTfhFDc?t=11m49s - There is “narrative” audio. Sorry.
What I did was I created two functions, a MoveForward and MoveRight (that also handles back/left based on negative input). I’m terrible at vector math and 3D space stuff so I just did it some hacky way I came up with and basically they do the same thing. Turn the player according to the camera and then apply a forward movement to the character.
The problem is, when I add in the Lerp to smoothly rotate the character towards the direction rather than snapping them straight to the new rotation, the character begins behaving uncontrollably
Here’s my behavior https://youtu.be/4RhIH6vwwwM
In the video I’m moving forward okay, pressing right or left spins the character okay (although he always seems to take the long way around, which looks weird), but if I press both Forward and Right he’ll only SOMETIMES go the proper way, other times he turns behind me and runs backwards and left. Same thing if I do foward and left, he’ll sometimes run backwards and right.
Now I’ve pretty much figured out it’s the lerping function. It’s constantly getting two different inputs, and splitting the difference (which is what you’d want) but the lerp is rotating in such an odd way (the long way around bit) that it’s actually causing the actor to rotate the wrong way, and then it stops at the opposite direction of what I want.
I understand this isn’t a very good way of doing it, so I’m posting on here hopefully for someone to help steer me in the right direction as to a proper way to do this.
//========================= MOVEMENT =========================
/* MoveForward() - Takes the character and makes them rotate forward before applying a forward movement */
void ABLTPlayerPawn::MoveForward(float Value)
{
if (Value == 0 || !IsLocallyControlled() || !GetMovementComponent())
return;
TurnCharacterToFront(Value); //Make the character face the proper direction towards/away from camera
AddMovementInput(GetActorForwardVector(), FMath::Abs(Value)); //Apply an Absolute value onto movement because we will always be facing forward
}
/* MoveRight() - Turns the character to face camera left/right and then applies forward movement accordingly
*
*
*
*
*/
void ABLTPlayerPawn::MoveRight(float Value)
{
if (Value == 0 || !IsLocallyControlled() || !GetMovementComponent())
return;
TurnCharacterToSide(Value); //Turn the character to the side
AddMovementInput(GetActorForwardVector(), FMath::Abs(Value)); //Apply movement in the FORWARD direction because we just made their forward vector face the camera's side. FMath::Abs (AbsoluteOf(Value)) prevents a negative input (which would end up as a "move backwards" command)
}
/* TurnCharacterToFront() - Rotates the character to face the camera's direction or to face the camera itself
* @Param - Value: Whether we're going forward or backwards
*
*
*
*/
void ABLTPlayerPawn::TurnCharacterToFront(float Value)
{
if (CameraComponent == NULL) //Return if we don't have a camera
return;
FVector LookAtVect = GetActorLocation() + (CameraComponent->GetForwardVector() * (192 * Value)); //Determine which direction the player wants to head based on camera direction and input direction (Value)
FVector MyLocation = GetActorLocation(); //Get our pawn's location
FRotator NewRotation = (LookAtVect - MyLocation).Rotation(); //Start the new Rotation by aiming our character towards where we're looking
NewRotation.Pitch = GetActorRotation().Pitch; //Just make sure we aren't pitching or rolling the character accidently from my hacky way of determing rotation
NewRotation.Roll = GetActorRotation().Roll;
NewRotation = FMath::Lerp(GetActorRotation(), NewRotation, 0.1); //Interpolate current rotation to new rotation for smooth turning
SetActorRotation(NewRotation); //Set new rotation
ServerUpdateRotation(GetActorRotation()); //Tell the server we've turned
}
/* TurnCharacterToSide() - Rotates the character to the left or the right based on Camera's view
* @Param - Value: Simply whether we're going Left or Right (passed from MoveRight())
* This is literally the same as TurnCharacterToFront, except we're using the Camera's RightVector instead. So just read those comments
*
*
*/
void ABLTPlayerPawn::TurnCharacterToSide(float Value)
{
if (CameraComponent == NULL) //Return if we don't have a camera
return;
FVector LookAtVect = GetActorLocation() + (CameraComponent->GetRightVector() * (192 * Value));
FVector MyLocation = GetActorLocation();
FRotator NewRotation = (LookAtVect - MyLocation).Rotation();
NewRotation.Pitch = GetActorRotation().Pitch;
NewRotation.Roll = GetActorRotation().Roll;
NewRotation = FMath::Lerp(GetActorRotation(), NewRotation, 0.1);
SetActorRotation(NewRotation);
ServerUpdateRotation(GetActorRotation());
}