Search Unity

Vector2 Lerp twitchy

Discussion in 'Scripting' started by matias-e, Sep 1, 2015.

  1. matias-e

    matias-e

    Joined:
    Sep 29, 2014
    Posts:
    106
    Hello. So I'm trying to change the position of a GameObject with Vector2 Lerp, but the lerp is really twitchy because it seems that the lerp is being called on every update of FixedUpdate. Here's the code, the 'rightLost' gets turned on from another function that turns it to true if the right condition is met. The 'rb' bariable is a reference to the GameObject's Rigidbody2D.

    Code (CSharp):
    1. void FixedUpdate ()
    2. {
    3.     if(rightLost) {
    4.          rb.transform.position = Vector2.Lerp(rb.transform.position, rightPos, Time.fixedDeltaTime);
    5.     }
    6. }
    What could be a way to change the twitchyness? I tried changing the boolean to false within the if statement, but then the lerp gets only one frame for itself so it doesn't go to the end of the lerp at all. I think one of the causes might be that the Rigidbody's gravity is pulling the ball down all the time so the movement is jerky, but if I set the Rigidbody to kinematic and it changes back to non-kinematic the GameObject still acts as if it is kinematic, but the kinematic checkbox is unchecked.
     
    Last edited: Sep 1, 2015
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    1) Lerp is a percentage based value. By lerping by Time.fixedDeltaTime, you're lerping by (if set up for default behaviour) 1/50th the distance between current position and target position. This means that the further you are away, the more distance you actually travel... meaning the speed you travel over time slows down as you get closer and closer.

    1/50th of 100 is 2, 1/50th of 50 is 1, 1/50th of 10 is .2, so on, so forth.


    2) changing the position of a GameObject with a simulated Rigidbody (not kinematic) is not suggested. Use AddForce for that. This is because if you just move the position, the simulation's velocity/forces aren't updated, so those just start accumulating over time.... for instance gravity, which is accelerative. For instance if you keep lerping the 'y' position upwards, the rb will continually think its falling, and gravity will build up, increasing the velocity more and more. So after 1 second the velocity of the rb may be -9.8 m/s, but after 2 seconds it's -19.6, after 10 seconds it's -98. So your lerp towards the original position at second 1 moves you only 0.196 units in a single frame, but the lerp after 10 seconds moves you a much further 1.96 units per frame.


    3) You're using Vector2.Lerp on 3d vectors. Not sure if you're in 3d or in 2d... but if you're in 3d, this means the 'z' value of the position will be habitually clamped to 0. Just like the velocity dealy in (2), any velocity in the 'z' will remain constant (and if any accelerative forces effect it, they'll accelerate), so again you can getting jaggies in the 'z' that way.


    4) As for your kinematic problem... when you say "but if I set the Rigidbody to kinematic and it changes back to non-kinematic", do you mean when you set the 'isKinematic' flag back false? If so... what you'll need to do is wake up the rigidbody because it was probably put to sleep when you flagged it kinematic.

    This is the way the physics engine works to reduce cost. If an object is comes to rest, it's flagged as sleeping. It won't be simulated again until some other rigidbody enters/exits collision with it, applying a force, and waking it up.

    So for example, if the object were to fall to the ground, come to rest, and its velocity reaches 0. It goes to sleep. But then you teleport it to 10 units above the ground by setting its position, which as we discussed doesn't signal to the engine anything force wise, it's still asleep. So it'll just float in mid air until some other object comes along and hits it.

    When you flag it kinematic, and may also go to sleep, because its not simulating at all. That's the entire point of being kinematic... it's to force remove it from the simulation loop.

    So you can call Rigidbody.WakeUp to bring it back to life:
    http://docs.unity3d.com/ScriptReference/Rigidbody.WakeUp.html
     
  3. matias-e

    matias-e

    Joined:
    Sep 29, 2014
    Posts:
    106
    Thanks a bunch for the answer, I think I got it working now!