Download

Third Person Template C++ Camera Turn Limitations

I’m currently in the process of prototyping a battle system that is similar to WoW or FFXIV. I am currently programming the camera capabilities so that holding right click changes the behavior of the pawn’s movement and causes the mouse to disappear, giving you control over the camera at the cost of being able to interact with the UI until you let go.

However, with my implementation I noticed two separate issues that have me scratching my head:

1) The max delta yaw is being limited by what I assume to be the bounds of the viewport. I can only go so far left or right before the camera stops abruptly. The closer I start to the edge, the quicker it stops. SOLVED BELOW

2) When I press and hold right mouse, the cursor disappears as it should and gives me control of the camera … however, when I press the left mouse button while the right mouse button is being held, the turn rate on the camera is cut down dramatically. I have verified that it actually cuts down on the rate that is being sent to MyProjectCharacter::TurnAtRate(float Rate) through debug messages in PIE. SOLVED BY OMITTING FUNCTIONALITY (REMOVED LEFTCLICKING FROM ACTION INPUTS)

Before pressing left click: Screenshot - c29187ccab5ccec98c9a401e663636fc - Gyazo
After pressing left click (both mouse buttons held down simultaneously, persists even after letting go of LMB): Screenshot - d18cfd401cefa0cf72e95430e6173649 - Gyazo

Here are my mouse settings for the project (I’ve tried messing with these extensively, but this seems to be the best of what’s available for my purposes):

And what follows is my implementation for my left click and right click inputs:



void MyProjectCharacter::LeftClicking() {
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("LeftClicking()")));
if (PC)
{
// Right right mouse isn't already pressed, store position and disable mouse for anything outside of turning camera
if (!PC->IsInputKeyDown(EKeys::RightMouseButton)) {
GetWorld()->GetGameViewport()->GetMousePosition(MousePos);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("MousePos: %d, %d"), MousePos.X, MousePos.Y));
PC->bShowMouseCursor = false;
PC->bEnableClickEvents = false;
PC->bEnableMouseOverEvents = false;
PC->SetIgnoreLookInput(false);
}
}
}

void MyProjectCharacter::UnLeftClicking() {
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("UnLeftClicking()")));
if (PC)
{
// If right mouse isn't pressed, restore mouse position and enable mouse and disable camera turning
if (!PC->IsInputKeyDown(EKeys::RightMouseButton)) {
FViewport* v = CastChecked<ULocalPlayer>(PC->Player)->ViewportClient->Viewport;
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("MousePos: %d, %d"), MousePos.X, MousePos.Y));
v->SetMouse(MousePos.X, MousePos.Y);
PC->bShowMouseCursor = true;
PC->bEnableClickEvents = true;
PC->bEnableMouseOverEvents = true;
PC->SetIgnoreLookInput(true);
}
}
}

void MyProjectCharacter::RightClicking() {
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("RightClicking()")));
if (PC)
{
// If left mouse isn't already pressed, store position and disable mouse for anything outside of turning camera
if (!PC->IsInputKeyDown(EKeys::LeftMouseButton)) {
GetWorld()->GetGameViewport()->GetMousePosition(MousePos);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("MousePos: %d, %d"), MousePos.X, MousePos.Y));
PC->bShowMouseCursor = false;
PC->bEnableClickEvents = false;
PC->bEnableMouseOverEvents = false;
PC->SetIgnoreLookInput(false);
}
}
}

void MyProjectCharacter::UnRightClicking() {
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("UnRightClicking()")));
if (PC)
{
// If left mouse isn't pressed, restore mouse position and enable mouse and disable camera turning
if (!PC->IsInputKeyDown(EKeys::LeftMouseButton)) {
FViewport* v = CastChecked<ULocalPlayer>(PC->Player)->ViewportClient->Viewport;
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("MousePos: %d, %d"), MousePos.X, MousePos.Y));
v->SetMouse(MousePos.X, MousePos.Y);

PC->bShowMouseCursor = true;
PC->bEnableClickEvents = true;
PC->bEnableMouseOverEvents = true;
PC->SetIgnoreLookInput(true);
}
}
}



This was set up in my bindings in the action section: Screenshot - 2068aa10c77f349262110da93d7fa906 - Gyazo

and I’ve added it to my SetupPlayerInputComponent function as so:



// Mouse capturing to turn camera
PlayerInputComponent->BindAction("LeftClicking", IE_Pressed, this, &MyProjectCharacter::LeftClicking);
PlayerInputComponent->BindAction("LeftClicking", IE_Released, this, &MyProjectCharacter::UnLeftClicking);
PlayerInputComponent->BindAction("RightClicking", IE_Pressed, this, &MyProjectCharacter::RightClicking);
PlayerInputComponent->BindAction("RightClicking", IE_Released, this, &MyProjectCharacter::UnRightClicking);


Has anyone had any similar issues with the camera not behaving as you thought it would?

EDIT: I’ve gotten around issue #1 by forcing the mouse cursor to be updated to the middle of the viewport when either click is held down, however, issue #2 seems insurmountable at the moment, as it seems to stem from something much deeper. Any ideas? If someone else runs into this issue where camera is locked based on viewport, try:



// Allow user to turn full circle, not limited by the edges of the viewport
if (PC->IsInputKeyDown(EKeys::LeftMouseButton) || PC->IsInputKeyDown(EKeys::RightMouseButton)) {
//Viewport Size
const FVector2D ViewportSize = FVector2D(GEngine->GameViewport->Viewport->GetSizeXY());
//Viewport Center!
const FVector2D ViewportCenter = FVector2D(ViewportSize.X / 2, ViewportSize.Y / 2);

FViewport* v = CastChecked<ULocalPlayer>(PC->Player)->ViewportClient->Viewport;
v->SetMouse(ViewportCenter.X, ViewportCenter.Y );
}


**EDIT2: I’ve ‘solved’ issue #2 by simply omitting the functionality I had originally intended to implement. Removing the left click input from the action bindings allowed me to get around the Val in APawn::AddControllerYawInput(float Val) from dropping drastically when left clicking after holding right click. I’m still not sure what’s happening here. Any advice welcomed.

EDIT3: EDIT#2 was a lie; it doesn’t work. Left clicking will still cause APawn::AddControllerYawInput to take in lower Val values.**

Marking as solved, even though the solution to problem #2 is not ideal.

EDIT: Nevermind, I lied, that doesn’t fix it either. It’s just an inherent problem with the APawn::AddControllerYawInput function.