0
\$\begingroup\$

I have been struggling with this problem for a while. In my project (RTS in space) I have a ship moving on a 2D plane. I want to make the right movement in space so that when I click somewhere in space:

  1. The ship began the movement by constantly turning its nose towards the destination point. It will turn out some kind of curve;
  2. or turned around its axis while standing still and then moved to the point if this happens faster than in the first version.

For the first version i came with this pseudocode (assume that Z component always 0, and assume that moveTo is called every tick)

int moveTo(vector3 &position, float deltaTime)
{
    float forwardSpeed = 10;
    float forwardTurningSpeed = forwardSpeed * 0.5;

    // Find direction to destination point
    vector3 direction = position - GetActorLocation(); 
    direction.normalize();

    // Find on which angle to rotate the actor
    float angleBetweenDirectionAndWorldRightVector = getAngleBetweenVectors(direction, GetRightVector());
    float angleBetweenActorForwardVectorAndWorldRightVector = getAngleBetweenVectors(GetActorForwardVector(), GetRightVector());
    // This subtracion is the root of all problems
    float angle = angleBetweenDirectionAndWorldRightVector - angleBetweenActorForwardVectorAndWorldRightVector;
    // When finding angle between direction vector and actor`s forward vector the value is from 0 to 180
    // and there is no difference when direction is to the left by say 10 degrees or to the right
    // I thought that by subtracting angle between actor`s forward vector and world`s right 
    // vector i could decide whether direction is to the left or to the right from actor`s forward vector
    // but its not working in this way

    if(angle < 10 || angle > -10)
    {
        // If actor looking at target position nearly straight then move forward
        vector3 newPosition = GetActorLocation() + GetActorForwardVector() * forwardSpeed * deltaTime;
        SetActorLocation(newPosition);
    }
    else
    {
        // Rotate actor while moving around Z axis (on a plane XY)
        if (angle < 180)
        {
            // Rotate counter-clockwise
            SetActorRotation(0,0,GetActorRotation().Yaw() + angle * deltaTime);
        }
        else
        {
            // Rotate clockwise
            SetActorRotation(0,0,GetActorRotation().Yaw() + angle*(-1) * deltaTime);
        }
        // Move forward after rotation
        vector3 newPosition = GetActorLocation() + GetActorForwardVector() * forwardTurningSpeed * deltaTime;
        SetActorLocation(newPosition);
    }
    // Stop if reached destination
    if((position - GetActorLocation()).LenghtSquared() < 100) return 1;
}

float getAngleBetweenVectors(vector3 &first, vector3 &second)
{
    // Find angle using dot product
    float dotProduct = dotProduct(first, second);
    float cosinus = dotProduct / (first.length() * second.length());
    return acosd(cosinus); // returns angle in degree
}

This is what I`ve got. enter image description here The second variant is quite simple by using standard MoveComponentTo unreal function twice. First apply to rotate around Z axis while standing still and second apply to move straight to destination.

I don`t know how to prebuilt path to avoid obstacles so this is next step.

\$\endgroup\$
4
  • \$\begingroup\$ It looks like you have a working solution here. What specific help do you need from users on this site? \$\endgroup\$
    – DMGregory
    Feb 20, 2020 at 18:33
  • \$\begingroup\$ The ship is not turning the right way. I whant to know how to properly calculate angle to rotate to \$\endgroup\$
    – Nikita. L
    Feb 20, 2020 at 18:38
  • \$\begingroup\$ So you started by searching for existing answers about working with angle differences, right? How have you tried applying this research to your case? \$\endgroup\$
    – DMGregory
    Feb 20, 2020 at 18:57
  • \$\begingroup\$ DMGregory, Thank you very much for pointing out the correct wording of the search query. Scrolling through several pages found a solution. The most interesting thing is that before I asked my question I thought about the solution I found, but I rejected it because I thought it was too fanciful \$\endgroup\$
    – Nikita. L
    Feb 21, 2020 at 18:24

1 Answer 1

0
\$\begingroup\$

So the answer I got was very simple. I had to use cross product instead of dot product. The answer code listing is connected to my question

int moveTo(vector3 &position, float deltaTime)
{
    ...
    // This way the angle between direction and forward vector can be obtained (0-180 degrees)
    float angle = getAngleBetweenVectors(direction, GetForwardVector());
    // This will obtain the cross product value (standard UE4 function)
    float crossProduct = CrossProduct(direction, GetForwardVector());

    if (crossProduct < 0)
    {
        // turn right by angle value
    } 
    else if (crossProduct > 0)
    {
        // turn Left by angle value
    }
    else if (crossProduct == 0) 
    {
        // move forward
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .