Search Unity

Vector3.Lerp problem

Discussion in 'Scripting' started by Deleted User, Oct 8, 2014.

  1. Deleted User

    Deleted User

    Guest

    Code (CSharp):
    1. GameObject   car;
    2. GameObject  camera;
    3.  
    4. camera.transform.position = Vector3.Lerp(camera.transform.position,car.transform.position,TIme.deltaTime*5F);
    This is working but camera does not go smooth but it goes harsh.
    Looks like it is being teleported every 1 meter.

    I am trying to make camera follow the car , when car goes fast camera lags behind in an effect of speed.
     
    Last edited by a moderator: Oct 8, 2014
  2. jabez

    jabez

    Joined:
    Nov 2, 2013
    Posts:
    26
    Haiiii, try
    Code (CSharp):
    1. public GameObject Car;
    2.     public GameObject cam;
    3.     public float FollowSpeed = 1f;
    4.     void Update()
    5.     {
    6.         cam.transform.position = Vector3.Lerp(cam.transform.position, Car.transform.position, FollowSpeed * Time.deltaTime);
    7.  
    8.  
    9.     }

    You had TIme.deltaTime*5F backward it shouldnt matter though.
    assign follow speed in the inspector & play around with it until you like it
     
  3. Deleted User

    Deleted User

    Guest

    Still have the same problem...
     
  4. Deleted User

    Deleted User

    Guest

    WTF ???
    I have found that problem lies in Vector3.
    Somehow Vector3 coordinates of object is rounded..

    Example...
    real position of object x=0.01765765 y=1.2087897 z=2.9876987
    for real position in Vector3 you get Vector3(0.0,1.2,2.9)

    again WTF? ... from this means that you are loosing information.. is this unity3d bug?
     
  5. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    How are you getting your numbers? If you are dumping them to the console (as a Vector3) they are truncated.
     
  6. Deleted User

    Deleted User

    Guest

    you are right... ia am using debug.log()
     
  7. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Do you have a frame rate of like 10 fps, that would make delta time huge
     
  8. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    This is almost certainly a problem with FixedUpdate versus Update. Try updating your camera position in FixedUpdate instead.

    I'm assuming that your framerate is faster than your physics framerate (which is locked at 50fps, unless changed in Time settings). Basically, as far as Update is concerned, your car moves forward several meters, then holds still for a few frames, then moves forward a few more meters, and so on. It's easy to see how an apparent stutter can happen in this situation.
     
  9. Jonny-Roy

    Jonny-Roy

    Joined:
    May 29, 2013
    Posts:
    666
    Generally, it should be updated in LateUpdate, this is the last update event that fires before rendering, but it depends when and where you are updating the car position. The issue is generally that you are doing it in the same event on both gameObjects, but the events are firing in the reverse order of what you think....so:

    Camera updates to be behind car
    Car moves
    -> you see the Camera in the previous car position

    This will look very jerky.
     
  10. Deleted User

    Deleted User

    Guest

    FixedUpdate() .... this solved the problem

    Tnx for help
     
  11. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Of course the fundamental problem here is that you're misusing Lerp. It's supposed to be used for interpolating between two positions, and the third parameter (t) is the interpolation fraction (from 0 to 1). Using FixedUpdate "fixes" the problem only because Time.deltaTime is smaller there, so by sheer luck, this happens to produce a t value that makes the camera sort of appear to do what you want on your machine under your current testing conditions.

    The proper fix would be to stop abusing Lerp, and use something like Vector3.MoveTowards or Vector3.SmoothDamp instead. That's what they're for.
     
  12. anonymousunitycreator

    anonymousunitycreator

    Joined:
    Sep 20, 2014
    Posts:
    43
    Joe is 100% right.
    The incorrect use of lerp is becoming an issue here in the forums with countless questions on the matter, and I think in part it has to do with the actual unity documentation on lerp which explains it wrong.

    this is a much better guide, and mathematically correct:
    http://www.blueraja.com/blog/404/how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly
    though even with the guide above, you should still use fixedupdate so that the lerping will not be dependant on the users system, but the fixed framerate.
     
    Last edited: Oct 9, 2014
    JoeStrout likes this.
  13. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    I disagree.

    The way he's using Lerp is not the standard way of using it, but it provides a particular camera movement that a) feels really responsive, b) feels really smooth, and c) is really easy to code. If I'm not mistaken, if he were using either of your suggested methods, he would be having exactly the same issue in this situation anyway.
     
  14. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Your points a and b are only true when the framerate is sufficiently high (and the "speed" value sufficiently low). When the machine bogs down, its behavior is quite poor. Points a and c, at least, are also true of MoveTowards; whether MoveTowards feels really smooth is a matter of opinion, but if it's not smooth enough, then you use SmoothDamp (which I'll admit is a bit harder to use). And these methods would not have the same issues he was running into with Lerp.
     
  15. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    If you use MoveTowards, you definitely have the same problem.

    A: FixedUpdate fires: car moves forward
    B: LateUpdate fires: camera moves towards car
    B2: (render frame)
    C: LateUpdate fires: camera moves towards car
    C2: (render frame)
    (repeat)

    The camera will be closer to the car at point C2 than it was at B2. Thus...jitter.

    The only way MoveTowards wouldn't have this problem would be if the speed at which the camera is moving is fast enough that the camera can reach its "desired position" in B. If that's the case, why have camera smoothing at all?
     
  16. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    That's a good reference! I should bookmark it, because (as you can see in my first post above) I'm starting to get tired of explaining all that myself every time. :)

    Not so! When using Lerp correctly, you're not integrating anything; the position at any point in time is completely fixed by the start time, end time, and current time. So if it's something visual, like camera movement, then doing it in FixedUpdate is just a waste of cycles. Do it in Update, and the position will be absolutely correct on every frame, which is all that matters.

    (Now if you're lerping something that affects physics, like the position of a moving platform or some such, then yeah, you absolutely should do that in FixedUpdate.)

    The problem of course is that when you're chasing a moving target, then you essentially can't use Lerp in any sensible way. It's the wrong tool for the job. But people keep reaching for it anyway, because it's the only tool they know (and because so many tutorials have led them in the wrong direction).

    It's like, "hey, I'm cutting this board with a hammer, but the edges are coming out all jaggy, what's wrong?" And then half the responses are like "You just need to whack at the board in finer increments, then you'll get a smoother edge." When the correct response is, "Quit trying to cut the board with a hammer. Use a friggin' saw, fer crying out loud."
     
  17. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    If the thing your camera is tracking is moved by physics, and you have any camera smoothing going on at all (be it Lerp or MoveTowards or anything), you will have an apparent jitter if your camera moves in Update/LateUpdate. I hope my previous comment (just before you posted this) lays out why pretty well.

    I'd also point out that, if you're having this problem, then it means your real framerate is faster than your physics framerate. This means LateUpdate is being called more frequently than FixedUpdate, and makes the "waste of cycles" comment particularly wrong.
     
  18. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Wait, sorry, I'm not following you. What are A, B, and C here? Different frames? I would expect the sequence to be something like:

    Frame 1 FixedUpdate: car moves
    Frame 1 FixedUpdate: car moves some more
    Frame 1 LateUpdate: camera moves towards car
    Frame 1 is displayed to the user
    Frame 2 FixedUpdate: car moves
    Frame 2 FixedUpdate: car moves some more
    Frame 2 LateUpdate: camera moves towards car
    Frame 2 is displayed to the user

    ...there's no jitter here. On every frame, the camera gets closer to the car, wherever that is when the frame's about to be rendered. If you do it right (i.e. moving by an amount equal to camera speed Time.deltaTime), the speed at which it approaches the car is constant, regardless of the frame rate.

    Sure, it'll work in FixedUpdate too, but there's no need for it, since (again) you're not integrating; there is no accumulated error to worry about (integration error is why FixedUpdate exists). It'll work just as well in Update or (better) LateUpdate.
     
  19. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    I guess the notations A, B, and C weren't really clear, since B and C are a different thing than A was. They were just meant as markers of the steps of the process.

    This is kind of like a race condition. Your description assumes that one LateUpdate (or fewer) gets called for each time FixedUpdate is called. In reality there are 3 possibliities (for the sake of discussion let's use a fixed timestep of 0.02):

    1) Your game is exactly 50fps. In this case, you're correct. The car moves, then the camera moves, and everything looks smooth.
    2) Your game is less than 50fps. In this case, you're still basically correct. The car moves several times, the camera moves once, but Time.deltaTime compensates by making it move further. Everything still looks pretty smooth. (there might be a tiny jitter because Time.deltaTime is unlikely to be an exact multiple of the fixed timestep, but it will be a subtle jitter, probably not worth worrying about)
    3) Your game is more than 50fps. This is the case where your approach runs into trouble, this is where the OP had trouble, and this is what my A/B/C process was referring to.

    Rephrasing the situation I described above. I'll use PF#a to denote physics frames, and VF#a to denote visual frames (and sub-steps thereof).

    PF1a: FixedUpdate
    PF1b: Physics (The car moves)
    VF1a: Update
    VF1b: LateUpdate (The camera moves)
    VF2a: Update
    VF2b: LateUpdate (The camera moves, now closer to the car)

    Is this clearer?

    The only real issue with using FixedUpdate is that the camera is moving immediately before the car moves, and is thus essentially reacting o the car's previous state - but at least it's doing so consistently. So the camera will lag ever so slightly behind the car's movements, but it won't stutter. This could be alleviated by "tracking" your own pseudo-deltaTime: In FixedUpdate, increment myDeltaTime by the fixed timestep; then, in LateUpdate, move your camera, using myDeltaTime in place of Time.deltaTime. In reality, this approach is probably the best of all worlds. You'll never waste CPU time calculating cam movement on frames that won't be seen, and it works precisely in all three timing scenarios above, even avoiding the subtle jitter in situation #2.

    How often this visual stutter happens depends on the framerate. If you're running at 100fps, it'll be constant - every second frame, the camera will be closer to the car. If you're at 51fps, then only every 50th physics frame will have two LateUpdates running, and once per second, the car will be closer to the camera for one frame.
     
    Last edited: Oct 9, 2014
  20. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    You know what, I think I am going to make a basic webplayer demo, with multiple selectable lerp/movetowards modes, and multiple update modes (fixedupdate/update), and the ability to control the framerate in an easy way. This could be a good way to play with these things, and be able to see all these little jitters that are tough to see when you're producing an actual game.
     
  21. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    OK, thanks, now I see what you're saying.

    Right, so in theory you can have physics updates running slower than screen updates. However, I'm not convinced this has anything to do with what the OP was seeing, though. A much more likely failure mode (at least when abusing Lerp) is that your machine gets bogged down, your screen updates drop to something like 10 fps, and so Time.deltaTime (within Update or FixedUpdate) is 0.1 sec, which you're multiplying by some constant speed, and ending up with a t value much bigger than you intended (possibly bigger than 1, though it Lerp clamps it to 1 anyway).

    In other words, the speed of movement with the common Lerp abuse isn't constant; it depends on your framerate, and this is the cause of the inconsistent results people see. MoveTowards is immune to this, because you get a constant speed, independent of the frame rate. (The situation with SmoothDamp is more complex, but I think it's mostly robust to this as well.)

    But let's consider the case where your display frames are happening faster than physics frames. In this case the question becomes: on an update frame where the car hasn't moved, what do you want to do with the camera? If you don't want the camera to move either, then it's not moving, the car's not moving, nothing on screen is changing. You've effectively turned down your visual frame rate.

    So that's fine if that's what you want (but of course it'd be better in this case to reduce fixedTime so you can actually move things as fast as your display is going).

    However, I think it's equally valid to say, even if physics objects haven't moved this frame, we still want other things, like the camera position, to update. This way at least you don't get an identical frame, which the user may perceive as a "glitch" (a very brief pause in the video).

    In reality, it probably doesn't matter which you choose in this situation, because we can't see things updating at 50 Hz except in our peripheral vision, and the resolution there is really poor anyway. That's why I don't think this was the cause of the OP's complaint (or the many other complaints arising from Lerp abuse). If your physics is updating at 50 Hz, and your display is updating at 50 Hz or more, life is good no matter where you do your updates.

    The problem arises when you're not getting 50 Hz or more, because you've got too much going on and the machine can't keep up. In this case, FixedUpdate will fire multiple times for each Update. It does this to help avoid integration errors blowing up (though it may still fail, as of course it can't guarantee 50 calls per second). If you're not integrating, you're generally better off using Update or LateUpdate, so things get updated as they're shown on screen (whatever rate that works out to be).
     
  22. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    That's a good idea, I was thinking along the same lines. PM me if you want any help with it, or just want another pair of eyes on the code.

    At the end we should put up a blog post somewhere that is the Definitive Guide to Following a Target in Unity, or something like that. It looks like if you and I can come to agreement, after some careful experimentation, then I bet our answer will be enough to convince anyone! :)
     
    StarManta likes this.
  23. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    I would say that, if the focal point of the camera is being moved by physics, then the desired behavior is to have one near-duplicate frame where the camera doesn't move. It's certainly preferable to having the focal point appear to jump around the screen!

    Another thing to consider is the possibility of setting Application.targetFrameRate to 50 to match the physics timestep. I haven't tried it, but it does seem to me that that would make a pretty good standard practice.
     
  24. anonymousunitycreator

    anonymousunitycreator

    Joined:
    Sep 20, 2014
    Posts:
    43
    This is actually turning into one of the most informational lerp threads i've seen