How can I turn 180 over a short period and not immediatly

Hi,

I am trying to add a simple quick turn function to allow the player to turn 180 quickly on the spot at the touch of a button.

I have set up an input mapping for my turn, and created a method that rotates the player to turn around, so it works on a very basic level.
However, I would like to improve it so that rather than just instantly turning around, the character turns over a brief period, say half a second, so it looks more fluid. But I am not sure how to progressively add yaw input until all 360 is added. Any help would be greatly appreciated.

Here is what I currently have:

InputComponent->BindAction("QuickTurn", IE_Pressed, this, &ADemoCharacter::OnStartQuickTurn);
InputComponent->BindAction("QuickTurn", IE_Released, this, &ADemoCharacter::OnStopQuickTurn);


    void ADemoCharacter::OnStartQuickTurn()
    {
        if (CarriedObjectComp->GetIsCarryingActor())
        {
	        CarriedObjectComp->Drop();
        }

        // Turn the player around by adding yaw rotation
        AddControllerYawInput(360.f);
    }

    void ADemoCharacter::OnStopQuickTurn()
    {
    }

Hello,

I believe this solution is not pretty but it may help you. I don’t know from which class you have inherited. If you inherited from PlayerController, you should override the ProcessPlayerInput function. If that’s not the case, you can also do this in a Tick function but it is dirtier. I’ll rather have my input controls set up in a PlayerController.

Anyways the idea is to take the DeltaTime and let it do the work on time for you. So, lets have a boolean you set to true when you want to turn, an Axis Mapping bound on Pressed, a float that saves time passed and the Tick function.

void ADemoCharacter::SetupInputComponent()
{
	Super::SetupInputComponent();

	InputComponent->BindAction("QuickTurn", IE_Pressed, this, &ADemoCharacter::OnStartQuickTurn);
}

void ADemoCharacter::OnStartQuickTurn()
{
	bTurn = true;
}

void Tick(float DeltaTime) 
{
	Super::Tick(DeltaTime);

	if (bTurn) {
           TurnTime += DeltaTime;
           if (TurnTime > 0.5f)
           {
                bTurn = false;
                AddControllerYawInput(180.f * (0.5f - (TurnTime - DeltaTime));
                return;
           }
           AddControllerYawInput(180.f * DeltaTime * 2);
      }
}

180.f * DeltaTime would turn 180 degrees in 1 second. Multiplying it by 2 makes it 2 times faster == 0.5s.
180.f * (0.5f - (TurnTime - DeltaTime)) makes sure you end up with a 180 degree turn, not more not less.

Ok great thanks, I will give that a go.

Is there no way to do it outside of the tick method? (Sorry if this is a silly question - I am new to the engine)

Hello, sorry for the delay.

I guess you can use Timers, but I haven’t used them yet. However it doesn’t seem all that hard, check the docs at Gameplay Timers in Unreal Engine | Unreal Engine 5.1 Documentation

Good luck!

no problem, I ended up setting up a new class that overrides player controller so I could solve this and a few other things, but I haven’t yet figured out what to do within the processplayerinput function - should I still be using a boolean check to determine if I start the turning?

Thanks again

Well, you should do exactly what you was doing in the Tick function, just call
Super::ProcessPlayerInput(DeltaTime, bGamePaused);
instead of Super::Tick(DeltaTime);

I believe the boolean to be the simplest way, because it’s easier to read, specially if you refactor rename it to bIsTurning (my bad). However, you could always use the float TurnTime instead.

Set TurnTime = 0.f when you IE_Pressed “QuickTurn” and check if TurnTime < 0.5f instead of checking bTurn in the ProcessPlayerInput function.

That would also perfectly work, and you get rid of the boolean.

In that case to make it easier to read, you could refactor rename TurnTime to TimeSpentTurning (or similar) and set a varable to hold the time you want the player to be turning (a const float TURN_TIME = 0.5f in your case I believe).

Good Naming gets hard quite a lot of times ^^.