So all you really need is a pointer to the Actor you want to orbit around inside of your Character::MoveRight function, which probably is some kind of member variable in your Character class.
The character circle around the target but will slowly spiral away from the NearestActor.
I’ve tried more direct approaches like using the UpVector cross product of toTarget and setting direction to that value but the character would still spiral out.
Currently my set up is:
When bTargeting=True the Controller’s Rotation is set to look at the NearestActor position every frame.
Oh interesting, you’re right it seems this solution will take a little bit more work to accomplish your task! The gif you posted shows perfectly why the spiraling behavior occurs, since the movement component is always pushing the player along the tangent to the circle around your target actor.
I think you might need to do some math to figure out the secant that you need to take around the circle to end up at the same distance away from the target actor, or maybe implement some extra logic in your actors tick function to maintain distance from the target.
Seems like a job for some good ol’ fashioned pen & paper geometry sketches at this point.
How does the movement component push the player, so that the circle the player is orbiting gets bigger?
I don’t get how this could be happening if we are calculating the correct path the player should take.
The naive solution I posted, similar to the link you posted, will move the character tangent to the circle around the target actor. Your desired direction is a secant of this circle, so more calculations must be done to achieve this.
So the lastest thing I tried was this:
Looking at the picture, if I rotate the character movement inward a bit then the tangent becomes a secant of a circle of radius x.
As I change the amount I want the character movement to rotate inward by, I can make the circle the player moves around bigger or smaller. The next challenge would be finding a way to automatically get that value to rotate inward by.
Hopefully, this is a good direction to go in resolving this issue.
I got this to work by not using the AddMovementInput function. Instead, I opted to use polar coordinates to find the position my character needs to be at.
The glaring issue with this code is that the player will clip into some geometry it fits into, since we are just setting the position. That will be the next problem to solve
void MoveRight(float Value)
{
if ( (Controller != NULL) && (Value != 0.0f) )
{
if (bTargeting)
{
FVector TargetLocation = NearestActor->GetActorLocation();
FVector PlayerLocation = RootComponent->GetComponentLocation();
//Math to find where we need to place the player relative to enemy
FVector2D Radius = FVector2D(TargetLocation - PlayerLocation);
float AngleDistance = (TargetingHorizontalSpeed / (2.0f * Radius.Size() * PI)) * 360.0f;
FVector RotateValue = -FVector(Radius.X, Radius.Y, 0.0).RotateAngleAxis(AngleDistance * -Value, FVector::UpVector);
FVector NewLocation = TargetLocation + RotateValue;
TeleportTo(FVector(NewLocation.X, NewLocation.Y, PlayerLocation.Z), RootComponent->GetComponentRotation(), false, false);
}
else
{
FVector Direction;
// use camera based right
const FRotator YawRotation(0, Controller->GetControlRotation().Yaw, 0);
Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
// add movement in that direction
AddMovementInput(Direction, Value);
}
}
}