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\$
  • \$\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 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 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 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 at 18:24
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
    }
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.