Search Unity

Steering Behavior Help

Discussion in 'Scripting' started by MitchStan, Apr 22, 2008.

  1. MitchStan

    MitchStan

    Joined:
    Feb 26, 2007
    Posts:
    568
    Hi there. I have steering behavior math problem. Maybe someone with steering behavior experience can provide me with an idea to solve this. Here goes:

    I need to calculate a player's position in T seconds, but the player is rotating on the Y axis by a constant turnRate (in degrees) so the velocity vector changes each time step as transform.forward changes.

    So, given an initial player position and rotation and velocity, what would be the players position in T seconds with a constant turnRate applied over the T second duration?

    Jeez, I hope that makes sense.

    Thanks for any help.
     
  2. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    The velocity vector should be seperate from the actual agent's transform. The velocity vector is just used as a "suggestion" for how the agent should move this frame.

    What are you trying to do in the "bigger picture"?

    Edit: Sounds like you are trying to handle prediction for pursuit/evade?

    -Jeremy
     
  3. MitchStan

    MitchStan

    Joined:
    Feb 26, 2007
    Posts:
    568
    Jeremy,

    Yes, I am trying to predict a certain scenario. I am using the steering behavior seek to get a steeringForce to move my player towards a stationary target.

    But I am limiting how much the player can rotate in each time step. This prevents instantaneous turns - turns are more gradual.

    So everything works great except for the occasional situation where the target is close to the player, but the player's maxTurn value and speed and distance to target send it into a continuous circle about the target. The player is too close to the target and with the maxTurn and speed, it can't turn sharp enough to put it on course with the steering Force as calculated by the seek method.

    So in the bigger picture, I'm trying to figure out the math to predict when this scenario occurs so I can tell the player to slow down (and turn sharper) or just stop, swivel and then seek.

    Any thoughts? Hope I described this in a way that makes sense.

    Thanks for any help with this.

    Mitch
     
  4. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    If the character's forward velocity is constant and it is turning by a constant amount then it is moving in a circle. Take the amount of time ahead that you want to predict and multiply it by the magnitude of the velocity vector - this will give you the distance moved around the circumference of the circle (on the basis that speed * time = distance). You can do a similar calculation to get the angle the character has turned (angular turn rate * time).

    You can now get the radius of the circle by dividing the distance moved along the circumference by the angle (you'll need the angle in radians for this). With that, the centre of the circle is easy to calculate from the character's Transform.

    With the determination of the circle, the start position and the amount of time, you should be able to predict the character's motion as far as you like. I think you could more or less make the character's speed inversely proportional to the circle radius to avoid orbiting the target.
     
  5. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    Another more simple way is to simply apply a braking force if the angle between the agent's current forward direction (agent.transform.TransformDirection(Vector3.forward)) and the direction hinted by the steering vector is too high.

    Then for each degree over the angle limit, increase the braking force. Just make sure you set a min speed so the agent will still move forward slowly no matter how much braking force is applied.

    Edit: This can also be used to simulate the turning behaviour of army tanks

    -Jeremy
     
  6. MitchStan

    MitchStan

    Joined:
    Feb 26, 2007
    Posts:
    568
    Thanks guys. Andee, that's exactly the scenario and your math suggestions did the trick.

    And Jeremy, I took your advice and applied a braking force when the condition is met.

    The steering behaviors work very nicely now. Thank you.
     
  7. pdrummond

    pdrummond

    Joined:
    Jun 23, 2005
    Posts:
    185
    Hi everyone,

    I hope this is a good place to post this. I've been looking through the forums all morning and can't find what I'm looking for. It probably is there but I've reached that brain-fried stage where I need a break.

    I'm working on AI for my game agents and need some help with the obstacle avoidance code. My agents cast a ray in front to detect any upcoming obstacles. Using the Vector3.Reflect function I can get a direction vector to use as a steering hint. What I need to do is calculate the world coordinates of the a point 1 unit along the reflection vector from the contact point. This point can be what the agent then rotates toward, steering itself around obstacles.


    Code (csharp):
    1. *Get forward direction.*/
    2. var fwd = transform.TransformDirection(Vector3.forward);
    3. /*Set ray origin just in front of the agent so we don't intersect its collider.*/
    4. var ray_origin = transform.TransformPoint(Vector3.forward * 1);
    5. /*Cast a ray out in front.*/
    6. var hit: RaycastHit;
    7. if (Physics.Raycast(ray_origin, fwd, hit, 40)) {
    8.     /*The hit normal.*/
    9.     var contact_normal = hit.normal;
    10.     /*The hit point.*/
    11.     var contact_point = hit.point;
    12.     /*Get the reflection from the contact normal.*/
    13.     var reflection = Vector3.Reflect(fwd, contact_normal);
    14.     /*Calculate the world coordinates of the point 1 unit along the reflection vector from contact_point.
    15.     [Stumped at this point]
    16. }
    The attached image shows what I mean. The green line is the ray cast in front. It gets reflected from the blue contact point. I need to calculate the world coordinates of the red point at the end of the reflection line.

    Any suggestions are appreciated. I'm sure the solution is obvious, but I've been staring at the code too long and can't think straight.

    Thanks.
     

    Attached Files:

  8. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    I think you want something like:-

    Code (csharp):
    1. hit.point + reflection.normalized * distanceAhead
    ...and you can remove the distanceAhead factor if you are sure you will only ever want to aim one unit ahead of the contact point.

    However, if the ray doesn't hit a flat surface head on then are you sure the reflection will end up pointing the right way? You could try crossing the ray's direction with Vector3.up to get a sideways-pointing vector if your current method gives you trouble.
     
  9. pdrummond

    pdrummond

    Joined:
    Jun 23, 2005
    Posts:
    185
    Thanks for that. I'll try it out and let you know.
     
  10. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    I recommend you use the normal of the surface you hit with the raycast instead of the reflected vector for your steering hint. Then you apply a force in the direction of the normal.

    -Jeremy
     
  11. pdrummond

    pdrummond

    Joined:
    Jun 23, 2005
    Posts:
    185
    Thanks. This is very helpful. Now I'm making progress.