Search Unity

Help adjusting my steering class; Rotation jitter

Discussion in 'Scripting' started by Superflat, Jul 1, 2012.

  1. Superflat

    Superflat

    Joined:
    Mar 19, 2009
    Posts:
    354
    Hello,

    I have ships sailing around a sphere and each ship has a standard forward motion. So I give each ship it's own steering class and FSM (state machine) to handle avoidance or steering towards targets and what not. However if a ship sees an enemy, it will steer away, but when it resolves the collisions it will steer to the wall again to avoid the enemy causing a jitter like behavior.

    How do I fix this?

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Steering
    5. {
    6.     private BaseShip ship;
    7.     private Vector3 forwardFeeler;
    8.     private Vector3 rightFeeler;
    9.     private Vector3 leftFeeler;
    10.    
    11.    
    12.     private float minimumCollisionDistance = 1; // -- when distance to the hit.point is 1, speed is 0
    13.     private float distanceThreshold = 4; // -- The distance after which the slow down occurs
    14.    
    15.    
    16.     private float increasedRotateSpeed = 7;
    17.    
    18.     public Steering( BaseShip owner)
    19.     {
    20.         ship = owner;
    21.     }
    22.     private bool SteerAwayFromCollision()
    23.     {
    24.         forwardFeeler = ship.transform.forward * ship.forwardFeelerLength;
    25.         rightFeeler = ship.transform.TransformDirection( ship.smallFeelerAngle, 0 , ship.whiskerFeelerLength );
    26.         leftFeeler = ship.transform.TransformDirection( -ship.smallFeelerAngle, 0 , ship.whiskerFeelerLength );
    27.        
    28.         RaycastHit forwardHit;
    29.         RaycastHit rightHit;
    30.         RaycastHit leftHit;
    31.        
    32.         Vector3 newPos = ship.transform.position+ship.transform.up * ship.scanHeightOffset;
    33.        
    34.         #if UNITY_EDITOR
    35.         Debug.DrawRay(newPos, forwardFeeler , Color.red);
    36.         Debug.DrawRay(newPos, rightFeeler , Color.red);
    37.         Debug.DrawRay(newPos, leftFeeler , Color.red);
    38.         #endif
    39.        
    40.         bool forwardRay = Physics.Raycast(newPos, forwardFeeler.normalized, out forwardHit, ship.forwardFeelerLength);
    41.         bool rightRay   = Physics.Raycast(newPos, rightFeeler.normalized, out rightHit, ship.whiskerFeelerLength);
    42.         bool leftRay    = Physics.Raycast(newPos, leftFeeler.normalized, out leftHit, ship.whiskerFeelerLength);
    43.  
    44.         if(!forwardRay  !rightRay  !leftRay)
    45.             return false;
    46.        
    47.         else if(forwardRay)
    48.         {
    49.             CheckDistanceToCollisionPoint( forwardHit );
    50.            
    51.             if( rightRay )
    52.                 ship.transform.Rotate(ship.transform.up, (-ship.RotateSpeed * increasedRotateSpeed) * Time.deltaTime, Space.Self);
    53.             else if( leftRay )
    54.                 ship.transform.Rotate(ship.transform.up, (ship.RotateSpeed * increasedRotateSpeed)  * Time.deltaTime, Space.Self);
    55.             else
    56.             {  
    57.                 Vector3 relativePoint = ship.transform.InverseTransformDirection( forwardHit.normal );
    58.                            
    59.                 if(relativePoint.x < 0.0f)
    60.                 {
    61.                     ship.transform.Rotate(ship.transform.up, (-ship.RotateSpeed * increasedRotateSpeed) * Time.deltaTime, Space.Self);
    62.                 }
    63.                 else if (relativePoint.x > 0.0f)
    64.                 {
    65.                     ship.transform.Rotate(ship.transform.up, (ship.RotateSpeed * increasedRotateSpeed) * Time.deltaTime, Space.Self);
    66.                 }
    67.             }
    68.         }
    69.         else if( rightRay )
    70.             ship.transform.Rotate(ship.transform.up, (-ship.RotateSpeed * increasedRotateSpeed) * Time.deltaTime, Space.Self);
    71.         else if( leftRay )
    72.             ship.transform.Rotate(ship.transform.up, (ship.RotateSpeed * increasedRotateSpeed) * Time.deltaTime, Space.Self);
    73.            
    74.         return true;
    75.     }
    76.     public void SteerTowardsTarget( Transform target )
    77.     {
    78.         if( SteerAwayFromCollision() )
    79.             return;
    80.        
    81.         Vector3 relative  = ship.transform.InverseTransformPoint( target.position );
    82.         float angle = (Mathf.Atan2(relative.x, relative.z) * Mathf.Rad2Deg) * Time.deltaTime ;
    83.    
    84.         ship.transform.Rotate (0, angle * Time.deltaTime * ship.RotateSpeed, 0);
    85.     }
    86.     public void SteerAwayFromTarget( Transform target )
    87.     {
    88.         //Steer away from any possible collisions
    89.         if( SteerAwayFromCollision() )
    90.             return;
    91.        
    92.         //Otherwise
    93.         Vector3 direction = ship.transform.InverseTransformDirection( target.position );
    94.         Vector3 relative = -direction;
    95.         float angle = (Mathf.Atan2(relative.x, relative.z) * Mathf.Rad2Deg) * Time.deltaTime;
    96.        
    97.         ship.transform.Rotate (0, angle  * Time.deltaTime * ship.RotateSpeed, 0);
    98.     }
    99.  
    100.     private void CheckDistanceToCollisionPoint( RaycastHit hit)
    101.     {
    102.         //Check distance to collision point
    103.         float distance = Vector3.Distance(ship.transform.position, hit.point);
    104.         if( distance < 2 )
    105.         {
    106.             //start slowing down the ship
    107.             ship.ForwardSpeed = ship.m_speed * (distance / distanceThreshold);
    108.             Debug.Log( ship.ForwardSpeed );
    109.             if(distance < minimumCollisionDistance) ship.ForwardSpeed = 0;
    110.         }
    111.         //Otherwise, if the speed doesn't match the standard speed, bring it back up to speed
    112.         /*else if( ship.ForwardSpeed != ship.m_speed )
    113.         {
    114.             ship.ForwardSpeed += 0.1f;
    115.             if(ship.ForwardSpeed > ship.m_speed)
    116.                 ship.ForwardSpeed = ship.m_speed;
    117.         }*/
    118.        
    119.     }
    120. }
     
  2. r3po

    r3po

    Joined:
    Apr 25, 2010
    Posts:
    48
    Hi Raziel,

    Not sure if you already fixed the issue but I have the same problem and these are the things that have helped me mitigate it:

    - Use acceleration on the rotation, this will soften the motion a bit.
    - Average the two rotations
    - Establish a threshold to stop rotating in one direction and start the other one

    I'd like to know how you solved it if you already did.

    Regards!