Aim Offsets - Always have player aim to mouse cursor

Hi all,

I’m trying to figure out a twin stick control scheme, and I want the players upper torso to move independently from the lower torso. I have my aim offsets working, my aim offset on both axes takes a value of -0.5 to 0.5 on both axes. For now in my code, I’m manually setting the pitch to 0.

Here’s what my code looks like -

FRotator ADerelictCharacter::GetAimOffsets() const
{
	if (Controller)
	{
		ADerelictPlayerController* PC = Cast<ADerelictPlayerController>(GetController());
		FRotator currentRotation = GetActorRotation();
		FVector target = PC->GetMouseLocationInWorldSpace();
		FVector start = GetActorLocation();
		FVector direction = -(target - start);
		FRotator targetRot = FRotationMatrix::MakeFromX(direction).Rotator();

		const FVector RotationDir = targetRot.Vector();
		const FVector LocalDir = ActorToWorld().InverseTransformVectorNoScale(RotationDir);
		const FRotator LocalRotation = LocalDir.Rotation();
		return FRotator(currentRotation.Pitch, -(LocalRotation.Yaw + currentRotation.Yaw), currentRotation.Roll);
	}
	return FRotator::ZeroRotator;
}

This works -

http://giant.gfycat.com/UnfitUnlinedCaudata.gif

Here, not so much…

http://giant.gfycat.com/WeeCompetentBobolink.gif

Thanks for any / all help!

I started working on the other code I’m going to need to make this control scheme work. I implemented code so that my pawn is always rotating towards my mouse cursor.

When he had a yaw of > 90 degrees or < -90 degrees the aim offset stopped working and he just kind of snapped between two angles for any degrees between there.

I started checking in my getaimoffset function for the actors current rotation like so -

    FRotator ADerelictCharacter::GetAimOffsets() const
    {
    	if (Controller)
    	{
    		ADerelictPlayerController* PC = Cast<ADerelictPlayerController>(GetController());
    		FRotator currentRotation = GetActorRotation();
    		FVector target = PC->GetMouseLocationInWorldSpace();
    		FVector start = GetActorLocation();
    		FVector direction = -(target - start);
    		FRotator targetRot = FRotationMatrix::MakeFromX(direction).Rotator();
    
    		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Yaw " + FString::SanitizeFloat(currentRotation.Yaw)));
    
    		const FVector RotationDir = targetRot.Vector();
    		const FVector LocalDir = ActorToWorld().InverseTransformVectorNoScale(RotationDir);
    		FRotator LocalRotation = LocalDir.Rotation();
    
    		if (currentRotation.Yaw > 90 || currentRotation.Yaw < -90) {
    			return FRotator(currentRotation.Pitch, (LocalRotation.Yaw + currentRotation.Yaw), currentRotation.Roll);
    		}
    		else {
    			return FRotator(currentRotation.Pitch, -(LocalRotation.Yaw + currentRotation.Yaw), currentRotation.Roll);
    		}
    
    		
    	}
    	return FRotator::ZeroRotator;
    }

I get decent results with this solution - but still not optimal. I’m still encountering deadzones where the character just snaps to an angle - which is to be expected the way I’m handling this. As soon as the pawn’s rotation reaches a certain value, I invert the offset, which isn’t correct. I’m missing something when calculating the offset, I’m pretty sure.

Any ideas?

http://giant.gfycat.com/ImaginaryFirsthandBlackrhino.gif