Today I needed to get the angle of the surface on which my character is standing on. It was surprisingly easy.
FHitResult hit;
auto c = FCollisionQueryParams(false);
c.AddIgnoredActor(this);
auto start = GetActorLocation();
auto end = start + FVector(0, 0, -1000);
this->GetWorld()->LineTraceSingle(hit, start ,end,ECC_WorldStatic,c);
auto a = hit.GetActor();
if (a != nullptr){
auto angle = FMath::RadiansToDegrees(FMath::Acos( FVector::DotProduct(hit.Normal, FVector(0,0,1))));
GEngine->AddOnScreenDebugMessage(0, 0.5f, FColor(1, 0, 0), FString::Printf(TEXT("Angle: %f"),angle));
}
I do a line trace from the position of my character downwards to (0,0,-1000). Then you can check the surface normal of the actor that you have hit.
Now remember that the dot product looks like this
DOT(A,B) = |A| * |B| * cos theta
now if A and B are of length 1 we are left with cos theta, which we can use to get the angle of our surface.
FVector::DotProduct(hit.Normal, FVector(0,0,1))
With the help of the dot product we now have the cosine which we need to inverse in order to get to the angle.
acos x = theta
cos theta = x
Now our angle is in radians which is fine but you can also convert it to degrees with
FMath::RadiansToDegrees