Why do I have to hold down mouse button to turn my character?

Hi! I want to create my game two controll modes. One is for out of combat (ooc) and the other is for combat.

In ooc the character turns with the A and D keys, goes forward with W and backward with D. In this state the mouse is for handling the player interface (not implemeted yet) like inventory, toolbars etc. When mouse left is pressed in ooc the camera the cursor hides and the camera enters into free mode, rotates independently from the charcater. This is for wieving the world. (not implemented yet). OOC works fine.

In combat mode the camera gets locked to the charcter so when you move the mouse it rotates with it. A and D goes into side movement. The mouse’s left and right is for attack and defense (not implemted yet). However the mouse does not rotates the character only when left or right mouse button is pressed. It is very strange because as you will see in the code and the screenshot from my inputs, I did bind it to the axis and not the action.

My solution for the camera zoom is temporary. :slight_smile: Pls dont care about it.![alt text][1]

I would appreciate any kind of advice or help.

// Fill out your copyright notice in the Description page of Project Settings.


#include "Lota.h"
#include "Lota_Hero_Character.h"

// Sets default values
ALota_Hero_Character::ALota_Hero_Character()
{
	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// Set this pawn to be controlled by the lowest-numbered player
	AutoPossessPlayer = EAutoReceiveInput::Player0;

	ZoomFactor = 0.1f;

	// Set the initial zone radius
	CharacterZoneRadius = 2000.0f;

	//The character base turn rate on its axis with wsad controll
	CharacterTurnRate = 2.0f;

	BaseSpeed = 400.0f;



	// Configure character movement
	GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...	
	GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f); // ...at this rotation rate
	GetCharacterMovement()->JumpZVelocity = 400.f;
	GetCharacterMovement()->AirControl = 0.2f;

	//Create SpringArm
	CameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
	CameraSpringArm->AttachTo(RootComponent);
	CameraSpringArm->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, 45.0f), FRotator(330.0f, 0.0f, 0.0f));
	CameraSpringArm->TargetArmLength = 300.f;
	CameraSpringArm->bUsePawnControlRotation = true;

	//CreateCamera
	HeroCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("GameCamera"));
	HeroCamera->AttachTo(CameraSpringArm, USpringArmComponent::SocketName);
	HeroCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm

												 // Create the characters's zone
	CharacterZone = CreateDefaultSubobject<USphereComponent>(TEXT("CharacterZone"));
	CharacterZone->AttachTo(RootComponent);
	CharacterZone->InitSphereRadius(CharacterZoneRadius);
}

// Called when the game starts or when spawned
void ALota_Hero_Character::BeginPlay()
{
	Super::BeginPlay();
}

// Called every frame
void ALota_Hero_Character::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (IsZoomingIn)
	{
		ZoomAmmount += DeltaTime / ZoomFactor; //Zoom in over half a second
		IsZoomingIn = false;
	}

	if (IsZoomingOut)
	{
		ZoomAmmount -= DeltaTime / ZoomFactor;        //Zoom out over half a second
		IsZoomingOut = false;
	}
	ZoomAmmount = FMath::Clamp<float>(ZoomAmmount, 0.0f, 1.0f);
	//Blend our camera's FOV and our SpringArm's length based on ZoomFactor
	HeroCamera->FieldOfView = FMath::Lerp<float>(90.0f, 60.0f, ZoomAmmount);
	CameraSpringArm->TargetArmLength = FMath::Lerp<float>(400.0f, 100.0f, ZoomAmmount);
}

// Called to bind functionality to input
void ALota_Hero_Character::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
	Super::SetupPlayerInputComponent(InputComponent);

	//Hook up events for "ZoomIn"
	InputComponent->BindAction("ZoomIn", IE_Pressed, this, &ALota_Hero_Character::ZoomIn);
	InputComponent->BindAction("ZoomOut", IE_Pressed, this, &ALota_Hero_Character::ZoomOut);

	//Combat mode on/off bindings
	InputComponent->BindAction("CombatMode", IE_Pressed, this, &ALota_Hero_Character::CombatModeOnOff);

	//Hook up every-frame handling for our four axes

	//Movement bindings
	InputComponent->BindAxis("MoveForward", this, &ALota_Hero_Character::MoveForward);
	InputComponent->BindAxis("MoveBackward", this, &ALota_Hero_Character::MoveBackward);
	InputComponent->BindAxis("MoveRight", this, &ALota_Hero_Character::MoveRight);
	InputComponent->BindAxis("MoveLeft", this, &ALota_Hero_Character::MoveLeft);
	InputComponent->BindAxis("CameraPitch", this, &ALota_Hero_Character::TurnCameraPitch);
	InputComponent->BindAxis("CameraYaw", this, &ALota_Hero_Character::TurnCameraYaw);
}

void ALota_Hero_Character::TurnCameraPitch(float AxisValue)
{
	CameraInput.Y = AxisValue;

	FRotator NewRotation = CameraSpringArm->GetComponentRotation();
	NewRotation.Pitch = FMath::Clamp(NewRotation.Pitch + CameraInput.Y, -85.0f, 85.0f);
	CameraSpringArm->SetWorldRotation(NewRotation);
}

void ALota_Hero_Character::TurnCameraYaw(float AxisValue)
{
	CameraInput.X = AxisValue;
	if (CombatMode)
	{
		FRotator NewActorRotation = GetActorRotation();

		NewActorRotation.Yaw += CameraInput.X;
		SetActorRotation(NewActorRotation);
	}
}

void ALota_Hero_Character::MoveForward(float AxisValue)
{
	if (AxisValue != 0.0f)
	{
		if (!CombatMode)
		{
			FRotator YawRotation(0, GetActorRotation().Yaw, 0);

			FRotator CameraYawRotation(CameraSpringArm->GetComponentRotation().Pitch, GetActorRotation().Yaw, CameraSpringArm->GetComponentRotation().Roll);

			CameraSpringArm->SetWorldRotation(CameraYawRotation);

			Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

			AddMovementInput(Direction, AxisValue);

			UE_LOG(LogClass, Warning, TEXT("YawRotation at MoveForward(): %s"), *YawRotation.ToString());
		}

		else
		{
			// find out which way is forward
			FRotator YawRotation(0, GetActorRotation().Yaw, 0);

			// get forward vector
			Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

			// Rotate the camera where the mouse rotates; The character default forward is the last freecameraoff rotation

			AddMovementInput(Direction, AxisValue);
		}
	}
}
void ALota_Hero_Character::MoveBackward(float AxisValue)
{

	if (AxisValue != 0.0f)
	{
		if (!CombatMode)
		{

			if (0 > AxisValue)
			{
				IsWalkingBackward = true;
			}

			FRotator YawRotation(0, GetActorRotation().Yaw, 0);

			Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

			AddMovementInput(Direction, AxisValue);

			UE_LOG(LogClass, Warning, TEXT("YawRotation at MoveBackward(): %s"), *YawRotation.ToString());
		}

		else
		{
			// find out which way is forward
			FRotator YawRotation(0, GetActorRotation().Yaw, 0);

			// get forward vector
			Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

			AddMovementInput(Direction, AxisValue);
		}
	}
}


void ALota_Hero_Character::MoveRight(float AxisValue)
{
	if (AxisValue != 0.0f)
	{
		if (!CombatMode)
		{
			// find out which way is right
			FRotator Rotation = GetActorRotation();

			if (IsWalkingBackward)
			{
				Rotation.Yaw += CharacterTurnRate * AxisValue * -1.0f;
			}
			else
			{
				Rotation.Yaw += CharacterTurnRate * AxisValue;
			}

			SetActorRotation(Rotation);

			Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::Y);

			IsWalkingBackward = false;

		}
		else
		{
			// find out which way is right
			FRotator YawRotation(0, GetActorRotation().Yaw, 0);

			// get right vector 
			Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
			// add movement in that direction
			AddMovementInput(Direction, AxisValue);
		}

	}
}

void ALota_Hero_Character::MoveLeft(float AxisValue)
{
	if (AxisValue != 0.0f)
	{
		if (!CombatMode)
		{
			FRotator Rotation = GetActorRotation();

			if (IsWalkingBackward)
			{
				Rotation.Yaw += CharacterTurnRate * AxisValue * -1.0;
			}
			else
			{
				Rotation.Yaw += CharacterTurnRate * AxisValue;
			}

			SetActorRotation(Rotation);

			Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::Y);

			IsWalkingBackward = false;
		}

		else
		{
			// find out which way is right
			FRotator YawRotation(0, GetActorRotation().Yaw, 0);

			// get right vector 
			Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
			// add movement in that direction
			AddMovementInput(Direction, AxisValue);
		}

	}
}

void ALota_Hero_Character::CombatModeOnOff()
{
	APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();

	if (CombatMode)
	{
		CombatMode = false;

		PlayerController->bShowMouseCursor = true;
		PlayerController->bEnableMouseOverEvents = true;
		PlayerController->bEnableClickEvents = true;
	}
	else
	{
		CombatMode = true;

		PlayerController->bShowMouseCursor = false;
		PlayerController->bEnableMouseOverEvents = false;
		PlayerController->bEnableClickEvents = false;
	}
}

void ALota_Hero_Character::ZoomIn()
{
	IsZoomingIn = true;
}

void ALota_Hero_Character::ZoomOut()
{
	IsZoomingOut = true;
}

Hi everyone!

I solved it myself. One must setup the input mode to game only in every tick.

Think about that for a second. Should you really do it every tick? What are the performance impacts of performing this action every tick?

You should only need to set it when transitioning from a menu.

Although this shouldn’t be done every tick, I was experiencing this issue when I forgot to set the input mode back to GameOnly from GameAndUI going from the main menu in my game to the actual game level in a multiplayer project. This was very hard to find out when testing locally.