So through a very large amount of google-fu, piecing together bits of information, copying and pasting, etc, I have managed to figure out a solution. A disclaimer I’ll add here though is that I’m not 100% certain how it works, but it works. Looking into quarternions and rotational stuff is something I’m going to do down the line to figure out how/why this works but for now I want to post a solution. Also unfortunately this doesn’t account for any other camera control, but simply will orient the player the way they want them.
Far too often I find the exact question I need answered, go unanswered, or see that someone has found a solution, but didn’t post it up themselves, so I’m going to give 2 blocks of code that anyone may find useful in the future.
The following will do a cast, and use the impact normals to orient the character accordingly, regardless of which way they are facing.
FTransform PawnTransform = Character->GetTransform();
FQuat PawnQuat = PawnTransform.GetRotation();
FVector PawnUpVector = PawnQuat.RotateVector(FVector(0, 0, 1));
FVector PawnRightVector = PawnQuat.RotateVector(FVector(0, 1, 0));
FVector PawnForwardVector = PawnQuat.RotateVector(FVector(1, 0, 0));
FVector PawnLocation = PawnTransform.GetLocation();
FVector Start = PawnLocation + PawnUpVector;
FVector End = PawnLocation - PawnUpVector * 100;
FCollisionQueryParams Params(true);
Params.AddIgnoredActor(Character);
FHitResult OutHit;
GetWorld()->LineTraceSingle(OutHit, Start, End, ECC_Pawn, Params);
DrawDebugDirectionalArrow(GetWorld(), Start, End, 40, FColor::Green, true, 5);
if (OutHit.bBlockingHit)
{
FVector ImpactNormal = OutHit.ImpactNormal;
FVector ImpactPoint = OutHit.ImpactPoint;
DrawDebugDirectionalArrow(GetWorld(), Start, ImpactPoint, 40, FColor::Green, true, 5);
FVector c = FVector::CrossProduct(PawnUpVector, ImpactNormal);
float d = FVector::DotProduct(PawnUpVector, ImpactNormal);
float s = FMath::Sqrt((1.0 + d) * 2.0);
float rs = 1.0 / s;
FQuat q(c.X * rs, c.Y * rs, c.Z * rs, s * 0.5);
q = q * PawnQuat;
q.Normalize();
PawnTransform.SetRotation(q);
Character->GetCapsuleComponent()->SetWorldTransform(PawnTransform);
Character->GetController()->SetControlRotation(PawnTransform.Rotator());
}
And the following will orient the character around a predefined vector point.
FVector PointLocation;
FVector DirectionalVector;
DirectionalVector = PointLocation - Character->GetActorLocation();
DirectionalVector.Normalize();
DirectionalVector.X = 0;
FTransform PawnTransform = Character->GetTransform();
FQuat PawnQuat = PawnTransform.GetRotation();
FVector PawnUpVector = PawnQuat.RotateVector(FVector(0, 0, 1));
FVector c = FVector::CrossProduct(PawnUpVector, DirectionalVector);
float d = FVector::DotProduct(PawnUpVector, DirectionalVector);
float s = FMath::Sqrt((1.0 + d) * 2.0);
float rs = 1.0 / s;
FQuat q(c.X * rs, c.Y * rs, c.Z * rs, s * 0.5);
q = q * PawnQuat;
q.Normalize();
PawnTransform.SetRotation(q);
Character->GetCapsuleComponent()->SetWorldTransform(PawnTransform);
Character->GetController()->SetControlRotation(PawnTransform.Rotator());
I’ll also provide a link to where I originally found the code to do this, someone else’s, so I can’t take any credit for it. You can find the thread here.
I very much so hope someone else finds this as helpful as I have.