AddMovementInput with additional angles

Hi all,

I’m using the 3rd person c++ template.
What I am trying to do is set up my character so when he runs through a trigger, it changes his direction by 45 degrees and just keeps running in the correct new direction. The whole time you just hold right on the stick. If you can imagine a camera looking at the guy, he eventually will run in a large octagon around the camera, where there are 8 distinct turns to ensure he gets back to his start position.

I have that process setup and working in c++ except after changing his angle, he adjusts back and runs exactly right.

in the Character class, the template has :



void ATheTowerCharacter::MoveRight(float Value)
{
	// add movement in that direction
	AddMovementInput(FVector(0.f,1.f,0.f), Value);
}


In my overlap function I capture running over the trigger, then change the angle:



void ATheTowerCharacter::OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Blue, "OverlapEvent: " + OtherActor->GetName());

	if ((OtherActor != nullptr) && (OtherActor != this))
	{
		// cast actor to AngleChangeTrigger
		AAngleChangeTrigger* const changeTrigger = Cast<AAngleChangeTrigger>(OtherActor);
		if (changeTrigger != nullptr)
		{
			float direction = this->InputComponent->GetAxisValue("MoveRight");
			ChangeAngle(direction);
		}
	}
}

void ATheTowerCharacter::ChangeAngle(float direction)
{
	int multiplayer = FMath::Abs(direction);
	FTransform transform = this->GetTransform();
	transform.ConcatenateRotation(FRotator(0, direction * 45, 0).Quaternion());
	transform.NormalizeRotation();
	this->SetActorTransform(transform);
}


I’m unsure at this stage if I am rotating the right object? ‘this’ is the PlayerCharacter class in the template.
Looking at the screen shot, the guy is rotated but his rotation in the transform view does not appear to have any rotation applied?
I expected when the MoveRight method says move right, it is relative to it’s transform, but it does not appear so?

Cheers

So I have gotten a little further…


 
constructor....
 MovementVector  = this->GetActorForwardVector();
 
 void ATheTowerCharacter::MoveRight(float Value)
 {
     AddMovementInput(MovementVector, Value);
 }
 
 void ATheTowerCharacter::ChangeAngle()
 {
     float multiplyer = this->InputComponent->GetAxisValue("MoveRight");
 
     if (multiplyer >= 0)
         multiplyer = 1.0f;
     else multiplyer = -1.0f;
 
     this->AddActorLocalRotation(FRotator(0.f, multiplyer * 11.250f, 0.f));
     MovementVector = this->GetActorForwardVector();
 }


So I still am using that AddMovementInput, though I would prefer not to. I think another issue I am having is the fact the player has to ‘turn’ when I change direction. So If I am going left, he does a turn before going right. This leads to a situation where my player is on the trigger while turning, no matter if I use BeginOverlap or EndOverlap, can I turn this ‘turning’ off, or is that due to me using AddMovementInput?

It’s hard to explain, but before I go for a long search would it be better to do something like this:


MoveRight Method:

Get forward Vector

Is Vector facing left?
Am I attempting to turn right?
Rotate 180

OR Is Vector facing right?
Am I attempting to turn left?
Rotate 180

Get forward Vector
this->AddLocalOffset(ForwardVector * speed);


though this feels clunky. Another option is to keep my own FRotation for the player and set it each time it runs through a trigger…which feels like the best method now

They seem like the same procedure actually. The second idea just has the benefit of you already having a function already written.

You get more control coding from scratch, but less of the flexibility/convience of using a predefined function. Choose whichever you feel you need more of.

Hey again,

So this is doing my head in haha…



void ATheTowerCharacter::OnOverlapEnd(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{

	if ((OtherActor != nullptr) && (OtherActor != this))
	{
		// cast actor to AngleChangeTrigger
		AAngleChangeTrigger* const changeTrigger = Cast<AAngleChangeTrigger>(OtherActor);
		if (changeTrigger != nullptr)
		{
			// First determine if we can enter the trigger this way
			float multiplyer = this->InputComponent->GetAxisValue("MoveRight");

			// travelling right AND is a right entered trigger...
			// OR 
			// travelling left and is a left entered trigger...
			if (multiplyer >= 0 && changeTrigger->IsRightSideTrigger() ||
				multiplyer < 0 && !changeTrigger->IsRightSideTrigger())
			{
				AActor* spawnTarget = changeTrigger->GetSpawnTarget();

				this->TeleportTo(spawnTarget->GetActorLocation(), spawnTarget->GetActorRotation());
				ATowerPlayerController* PlayerController = Cast<ATowerPlayerController>(Controller);
				PlayerController->SetControlRotation(spawnTarget->GetActorRotation());
				MovementVector = this->GetActorForwardVector();
				
				spawnTarget = nullptr;
				PlayerController = nullptr;
			}
		}
	}
}


At the moment my player can run through a trigger, and I now have a spawn point with the correct transforms to teleport my character.

I run to the right, through the highlighted trigger (in orange). This teleports me to the spawn point actor highlighted.
I am correctly facing the right way and I can run the right way, you can see in the code where I teleport to the spawn target.

When I run back to the left through the trigger coming back, to the spawn point shown, I am facing the correct way just like the spawn point - however my controls are inverted.

It’s got me baffled. From what I read SetControlRotation should be the only thing I need to rotate the player, because I need to update the controller, but I sware it is being ignored completely.

Bear in mind the movement vector - it is what kicks in inside this method:




void ATheTowerCharacter::MoveRight(float Value)
{
	AddMovementInput(MovementVector, Value);
}



so -
I run to the right, through the trigger, I teleport, the character faces the right way, guy keeps running in expected direction
I run to the left, through the trigger, I teleport, the character faces the right way, but the controls are inverted.

Anyone help me?

ok so my final answer which at least allowed me to prototype an idea was to simple multiply the forward momentum vector by the direction I was facing…simple in the end.



void ATheTowerCharacter::OnOverlapEnd(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{

	if ((OtherActor != nullptr) && (OtherActor != this))
	{
		// cast actor to AngleChangeTrigger
		AAngleChangeTrigger* const changeTrigger = Cast<AAngleChangeTrigger>(OtherActor);
		if (changeTrigger != nullptr)
		{
			// First determine if we can enter the trigger this way
			float multiplyer = this->InputComponent->GetAxisValue("MoveRight");

			// travelling right AND is a right entered trigger...
			// OR 
			// travelling left and is a left entered trigger...
			if (multiplyer >= 0 && changeTrigger->IsRightSideTrigger() ||
				multiplyer < 0 && !changeTrigger->IsRightSideTrigger())
			{
				AActor* spawnTarget = changeTrigger->GetSpawnTarget();

				this->TeleportTo(spawnTarget->GetActorLocation(), spawnTarget->GetActorRotation());
				if (multiplyer >= 0)
					MovementVector = this->GetActorForwardVector();
				else MovementVector = this->GetActorForwardVector() * -1;

				spawnTarget = nullptr;
			}
		}
	}
}