Getting MoveRight to orbit around other object

If I have the position of another object, how can get the player to orbit around that object then they move the analog stick right or left?

This is the current code block

void Character::MoveRight(float Value)
{
    if ( (Controller != NULL) && (Value != 0.0f) )
    {
        const FRotator Rotation = Controller->GetControlRotation();
	    const FRotator YawRotation(0, Rotation.Yaw, 0);

	    // add movement in that direction
	    const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
	    AddMovementInput(Direction, Value);
    }
}

I can get the calculate the orbit using the distance from the object point, but how do i translate that to the player’s movement?

One potential solution is to derive “Rotation” from an FVector instead of your Controller’s rotation. Something like this:

const FVector toTarget = targetActor->GetActorLocation() - GetActorLocation();
const FRotator Rotation = toTarget.Rotation();

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.

I implemented your solution and it seems to get me part way to what I’m looking for.

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.

Thank you for your help!

I found a good example gif of what I’m experiencing in this question, but there is no good answer:

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.

Hopefully this sketch will help you see what is wrong and how you might want to fix it.

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.

ooohhhhh, okay I get it now. I’ll try to come up with a new solution with this then.
Thanks!

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 :slight_smile:

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);
	    }
    }
}

*Edit 1: Use TeleportTo rather than SetActorLocation so you dont clip into walls