0
\$\begingroup\$

I am trying to implement Reynolds' seek steering behaviour, but I am having problems on the rotation part. This is what I have:

void FixedUpdate()
{
// get position of current waypoint
        Vector3 targetPos = new Vector3(path[currentWaypoint].x, transform.position.y, path[currentWaypoint].z);

        // velocity vector towards target
        Vector3 desiredVelocity = targetPos - transform.position;

        // calculate the steerforce required for the desired velocity based on current velocity
        Vector3 steerForce = desiredVelocity - currentVelocity;
        steerForce = new Vector3(steerForce.x, 0, steerForce.z);
        steerForce = Vector3.ClampMagnitude(steerForce, maxSteer);

        // create a move vector to be added to agent's current position
        // Then normalize it so it can be scaled according to the agent's max speed
        Vector3 moveVector = steerForce.normalized * moveSpeed * Time.fixedDeltaTime;
        transform.Translate(moveVector);
}

How would I do it so my agent will be rotated smoothly based only on the code above? I tried rotating based on the current velocity, but the agents is rapidly rotated in one frame towards the target waypoint. I am not working with rigidbodies.

Am I doing something wrong? What am I missing?

Thanks, Jack

\$\endgroup\$
  • 1
    \$\begingroup\$ Have you looked at Vector3.lerp? \$\endgroup\$ – user3797758 May 15 '16 at 14:52
  • \$\begingroup\$ In addition, none of the code here deals with rotation, only movement. \$\endgroup\$ – Draco18s May 15 '16 at 15:38
  • \$\begingroup\$ @Draco18s Yes, that is because I am not sure how to handle rotation using vectors. That is what I am trying to find out how to do. \$\endgroup\$ – JackMini36 May 15 '16 at 15:43
  • \$\begingroup\$ @user3797758 Isn't that for position movements? \$\endgroup\$ – JackMini36 May 15 '16 at 15:45
  • \$\begingroup\$ it's for getting one vector from state A to B over a certain amount of time. Since I don't see you doing anything with quaternions i don't see why it wouldn't work... \$\endgroup\$ – user3797758 May 15 '16 at 15:49
0
\$\begingroup\$

After looking up how Reynolds seek steering works i realised that lerping wouldn't work. What you have to do is limit the steering to the maximum force which should be set very low to avoid instant steering.

void FixedUpdate()
{
    //move to position
    transform.Translate(Seek(new Vector3()) * Time.fixedDeltaTime);
}

Vector3 Seek(Vector3 target)
{
    //Reynolds steering behaviour = desired - velocity
    //Should be global variables
    float maxSpeed = 4f;    //fastest possible speed
    float maxForce = 0.1f;  //turning speed of the object

    //the direction that you need to go to reach the target
    Vector3 desired = target - transform.position;
    desired.Normalize();
    desired *= maxSpeed;

    //steering (reynolds steering)
    Vector3 steer = desired - currentVelocity;
    steer.y = 0f; //assuming you want 2D motion on the XZ plane

    //limit the steering
    if(steer.sqrMagnitude > maxForce * maxForce)
    {
        steer.Normalize();
        steer *= maxForce;
    }

    return steer;
}

This should work but it's untested. Tell me if there is a problem with it. You will need to change the target location in the update method as i doubt that you want to go the the origin of the scene.

EDIT

To get the rotation to work you need to get the object to face into the direction that it is moving. So by changing the update function too this it should work (in theory):

void FixedUpdate()
{
    transform.Translate(Seek(new Vector3()) * Time.fixedDeltaTime);//change position
    transform.rotation = Quaternion.LookRotation(currentVelocity);//change the rotation
}
\$\endgroup\$
  • \$\begingroup\$ Thanks! The movement works, but the steering does not seem to get limited, it just immediately change towards the next target when one is reached (it is not done gradually). When I lower maxForce, the only thing that is limited is the moving speed \$\endgroup\$ – JackMini36 May 15 '16 at 17:23
  • \$\begingroup\$ Oh I completely misunderstood the problem. \$\endgroup\$ – user3797758 May 15 '16 at 18:37
  • \$\begingroup\$ @JackM36 So you want the object to slowly turn towards the target as it's moving? \$\endgroup\$ – user3797758 May 15 '16 at 18:44
  • \$\begingroup\$ Yes, when the target is not straight ahead, I want the agent (object) to steer towards it (based on desired velocity and the steer force), and at the same time rotate towards the direction it is heading, much like a car or a real human \$\endgroup\$ – JackMini36 May 15 '16 at 18:49
  • \$\begingroup\$ You just need to get the agent (object) to face the direction that it's moving in \$\endgroup\$ – user3797758 May 15 '16 at 20:57
0
\$\begingroup\$

I have a MathHelper class for stuff like this (I've got a fast/inaccurate distance check, various radians-degrees conversions, this angle trig, safe angle addition, a snap method...). Here's the one that is of interest to you:

public static double AngleBetweenPointsRadiansDouble(Vector2 P1, Vector2 P2) {
    return Math.Atan2( ( P2.y - P1.y ), ( P2.x - P1.x ) );
}

You'd want to plug in Vector2 versions of your Vector3s's .x and .z (as you are ignoring the Y component).

Vector2 pos = new Vector2(transform.position.x,transform.position.z);
double angle = MathHelper.AngleBetweenPointsRadiansDouble(pos, pos+moveVector);

You'd want to convert this to degrees and then apply it to the transform's eulerAngles's Y component.

\$\endgroup\$
  • \$\begingroup\$ Thanks! I did not make it exactly that way, but this helped! \$\endgroup\$ – JackMini36 May 16 '16 at 19:45
  • \$\begingroup\$ @JackM36 Glad to help. Feel free to mark my answer as useful/accepted. :) \$\endgroup\$ – Draco18s May 16 '16 at 23:58

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.