Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Setting Rigidbody.velocity at each frame makes the character jittery

Discussion in 'Physics' started by laur-ganta, Jun 4, 2015.

  1. laur-ganta

    laur-ganta

    Joined:
    Oct 22, 2014
    Posts:
    24
    Hello!

    I work on a 3D game in which the main chracter is seen from above and is controlled with the mouse cursor. When clicked on the terrain the character will rotate and start moving towards the pointed location. The trick is that he will be moving while rotating, so I have to update the velocity for the rigidbody at each frame while rotating.


    Code (CSharp):
    1.     public IEnumerator MoveTo(Vector3 destination)
    2.     {
    3.         while (true) {
    4.            //update the velocity
    5.            _rgb.velocity = _myTransform.forward * movementSpeed;
    6.            
    7.             Vector3 targetPoint = destination - _myTransform.position;
    8.             Quaternion targetRotation = Quaternion.LookRotation (targetPoint, Vector3.up);
    9.             _myTransform.rotation = Quaternion.Slerp (_myTransform.rotation, targetRotation, Time.deltaTime * turnSpeed);
    10.  
    11.             Vector3 forward = _myTransform.TransformDirection (Vector3.forward);
    12.             Vector3 toOther = destination - _myTransform.position;
    13.              
    14.             // check if character finished rotating
    15.             if (Vector3.Dot (forward.normalized, toOther.normalized) > .99f )
    16.                 break;
    17.             // check if character reached destination while rotating
    18.             if( Mathf.Abs(_myTransform.position.x - destination.x) < .5f)
    19.             {
    20.                 if( Mathf.Abs(_myTransform.position.z - destination.z) < .5f)
    21.                 {
    22.                     StopMoving();
    23.                     return false;
    24.                 }
    25.             }
    26.             yield return null;
    27.         }
    28.         while( (Vector2.Distance(new Vector2(_myTransform.position.x - _myTransform.forward.x *.5f, _myTransform.position.z - _myTransform.forward.z *.5f),
    29.                                         new Vector2(destination.x, destination.z))) > .5f)
    30.         {
    31.  
    32.             yield return null;
    33.         }
    34.  
    35.         StopMoving();
    36.     }

    The problem is this makes the character jittery while rotating (the first "while"). After he finishes rotating he will smoothly translate to the desired location.

    Anyone knows what is the cause here? I assumed that is because I change the velocity at each frame, which (if it works the way I think it works) shouldn`t be the cause, but there is no other line of code in there that could affect it.
     
  2. MatthewW

    MatthewW

    Joined:
    Nov 30, 2006
    Posts:
    1,356
    Try making the change every FixedUpdate instead of every Update:

    yield return new WaitForFixedUpdate();

    Instead of:

    yield return null;
     
  3. laur-ganta

    laur-ganta

    Joined:
    Oct 22, 2014
    Posts:
    24
    I tried and no change. I used WaitForEndOfFrame() too and is still the same.

    I tested without the velocity update and it`s still jittery. So it means my assumption was wrong. The problem should be the way I assigned the rotation I think.
     
    Last edited: Jun 4, 2015
  4. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    better idea. dont use a co-routine.
     
  5. laur-ganta

    laur-ganta

    Joined:
    Oct 22, 2014
    Posts:
    24
    Got rid of coroutines and made a state machine like structure:

    Code (CSharp):
    1. void FixedUpdate () {
    2.         switch (state) {
    3.         case State.Idle:
    4.             break;
    5.         case State.Moving: MoveTowardsDestinaion();
    6.             break;
    7.         case State.Rotating: RotateTowardsDestination();
    8.             break;
    9.         }
    10.     }
    It works now, thanks for your suggestion.
     
  6. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,430
    Also, a rigidbody should be moved and rotated using Rigidbody.MovePosition and Rigidbody.MoveRotation instead of just modifying the transform. This ensures the rb interacts correctly with the other physic objects.