Search Unity

In Update the X and Z movement has a lag and in FixedUpdate the Y movement has a lag. Any idea?

Discussion in 'Scripting' started by heromade, Aug 17, 2019.

  1. heromade

    heromade

    Joined:
    Aug 27, 2017
    Posts:
    33
    Hello everyone!

    The X and Z movement of my player is controlled by setting the position. The Y movement is controlled by AddForce. I have a camera script that moves with the player in 3rd person with damping:

    Code (CSharp):
    1.        
    2.         Vector3 v3TargetOffset = targetToFollow.position;
    3.         v3TargetOffset += (desiredOffset.z * targetToFollow.transform.forward);
    4.         v3TargetOffset += (desiredOffset.y * targetToFollow.transform.up);
    5.         v3TargetOffset += (desiredOffset.x * targetToFollow.transform.right);
    6.  
    7.         Vector3 v3CurrentCameraPos = transform.position;
    8.         v3CurrentCameraPos.x = Mathf.Lerp(v3CurrentCameraPos.x, v3TargetOffset.x, speed * Time.deltaTime);
    9.         v3CurrentCameraPos.y = Mathf.Lerp(v3CurrentCameraPos.y, v3TargetOffset.y, speed * Time.deltaTime);
    10.         v3CurrentCameraPos.z = Mathf.Lerp(v3CurrentCameraPos.z, v3TargetOffset.z, speed * Time.deltaTime);
    11.         transform.position = v3CurrentCameraPos;
    12.  
    13.         transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(targetToFollow.transform.position - transform.position, targetToFollow.transform.up), speed * Time.deltaTime);
    14.  
    Now when I put this code in the Update method, the camera movement in Y direction lags when I jump. When I put the code in the LateUpdate method the X and Z movement of the camera lags. That must be because I handel the Y with AddForce and the others with setting the position. I don't want / can't change this though.

    Is there any way to make the camera movement smooth?

     
    Last edited: Aug 17, 2019
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    What do you mean by "the camera lags" specifically? It is true that movement from physics (your Y movement) updates during the physics step just after FixedUpdate, but you don't actually see that on screen until after the next Update anyways. So I don't see why updating your camera in LateUpdate wouldn't be the way to go.
     
  3. heromade

    heromade

    Joined:
    Aug 27, 2017
    Posts:
    33
    I added a video as demonstration to the original post. Now I have changed the code to this:

    Code (CSharp):
    1.     private void Update()
    2.     {
    3.         // Calculate offset vector.
    4.         Vector3 v3TargetOffset = targetToFollow.position;
    5.         v3TargetOffset += (desiredOffset.z * targetToFollow.transform.forward);
    6.         v3TargetOffset += (desiredOffset.y * targetToFollow.transform.up);
    7.         v3TargetOffset += (desiredOffset.x * targetToFollow.transform.right);
    8.         // Lerp the camera.
    9.         Vector3 v3CurrentCameraPos = transform.position;
    10.         v3CurrentCameraPos.x = Mathf.Lerp(v3CurrentCameraPos.x, v3TargetOffset.x, speed * Time.deltaTime);
    11.         v3CurrentCameraPos.y = transform.position.y;
    12.         v3CurrentCameraPos.z = Mathf.Lerp(v3CurrentCameraPos.z, v3TargetOffset.z, speed * Time.deltaTime);
    13.         transform.position = v3CurrentCameraPos;
    14.  
    15.         transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(targetToFollow.transform.position - transform.position, targetToFollow.transform.up), speed * Time.deltaTime);
    16.     }
    17.  
    18.     private void FixedUpdate()
    19.     {
    20.         // Calculate offset vector.
    21.         Vector3 v3TargetOffset = targetToFollow.position;
    22.         v3TargetOffset += (desiredOffset.z * targetToFollow.transform.forward);
    23.         v3TargetOffset += (desiredOffset.y * targetToFollow.transform.up);
    24.         v3TargetOffset += (desiredOffset.x * targetToFollow.transform.right);
    25.         // Lerp the camera.
    26.         Vector3 v3CurrentCameraPos = transform.position;
    27.         v3CurrentCameraPos.x = transform.position.x;
    28.         v3CurrentCameraPos.y = Mathf.Lerp(v3CurrentCameraPos.y, v3TargetOffset.y, speed * Time.deltaTime);
    29.         v3CurrentCameraPos.z = transform.position.z;
    30.         transform.position = v3CurrentCameraPos;
    31.  
    32.         //transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(targetToFollow.transform.position - transform.position, targetToFollow.transform.up), speed * Time.deltaTime);
    33.     }
    Everything is smooth as long as I walk on top of the cube but not on the other sides... Geez this is getting complicated.
     
  4. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    There are 2 approaches for moving characters; CharacterControllers (a slightly better version of setting the position yourself) and Ridigbodys. You are kind of mixing the 2 by handling your XZ movement different from your Y movement, which is, as far as i know, not recommended.
    That said, i'm definitely not an expert on camera movement. Did you try updating the camera in LateUpdate, as Joe suggested? If that alone does not work, try doing all your position updates in FixedUpdate and then updating the camera in LateUpdate.
     
  5. heromade

    heromade

    Joined:
    Aug 27, 2017
    Posts:
    33
    First of all, I dont use a CharacterController because its collider cant be rotated and I need that to walk around the cube. I just set the position.
    For the jumping in Y direction I used the rigidbody and it's gravity because its the only way to detect the collision with the ground. If I would have made a custom gravity script and set the Y direction with the position, the player would just fall through the cube.

    I tried updating the camera in LateUpdate, did not change anything. I tried doing the position updates in FixedUpdate, that made the camera lag in every direction, no matter in what update I put the camera movement code.
     
  6. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    You can also cast a (or multiple) ray downwards and (dis)allow jumping based on the detected distance.
    Proper jumping and detection is a major pain in the butt tho, i agree.

    As for the camera, the update code should be called in LateUpdate() according to Unity, or at least that's what they do in every example i found in a quick search. Which makes sense, since that should guarantee that the camera is moved after all other motion happened.
    The jitter may be caused by something else. Does it jitter if you remove Lerp?
    If not, did you try replacing Lerp with something else, like SmoothDamp?
     
  7. heromade

    heromade

    Joined:
    Aug 27, 2017
    Posts:
    33
    Good point, have not thought about that. But it must be like a boxcast then

    If I put the camera movement in LateUpdate all directions lag. Or jitter might actually be the better word for what happens :D

    So if I dont Lerp is runs smooth. I just tried to replace it with the SmoothDamp but the jitter still exists the same as it does with Lerp. :/
     
  8. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    You are right, i totally forgot that BoxCasts exist, so i would have simply done it with 4 or so raycasts to prevent false detection of falling, simply because the character mostly stands on the edge of some hole or something. But a BoxCast is probably a better solution, yeah.

    By the way, which type is targetToFollow for you? At some point you are calling targetToFollow.position, implying it's a Transform, but below that you call targetToFollow.transform.position, implying it's an GameObject.

    I took your code for a test drive to try and figure out the problem. For me at least, following normal (= fully transform based) movement worked perfectly. Applying physics on top of that, by adding a rigidbody to the followed object introduced the jitter. Now, it seems to be possibly, albeit a bit tricky, to have a smooth follow cam for rigidbodies.
    I experimented a bit and thought i got it to work, but it turned out it worked perfectly fine in free fall, but not as soon as the object hit the ground. With that as my best result, i still believe the main problem here is that you are mixing physics-based movement with purely position based movement, which is not recommended.
    I'll probably experiment a bit more after i'm back home later this day, but if at all possible, try implementing a solution that does not rely on a rigidbody, or only relies on it, and tell us if that fixes the problem.
     
  9. heromade

    heromade

    Joined:
    Aug 27, 2017
    Posts:
    33
    That is a good question, it is a Transform. I copied the original piece of code from a different Thread cause I was too dumb to figure it out myself.

    Thanks a lot man! I already figured out that for rigidbody forces I would need to make the camera movement in FixedUpdate and for normal positions in the normal Update or LateUpdate. But mixing them makes the problem.
    When I have time I will try to move the player by setting the velocity. If that does not work I will have to make the Y-movement via Boxcasts as you said.

    And thank you for not trying to change or ask for the way I operate. Usually people directly say things like "Just use a Rigidbody and dont set the position" but they dont know the project and that I might need this kind of movement. So thanks for being an actual help! :)
     
  10. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    Glad i was of any help. Maybe as a final advice on which movement to pick:
    Rigidbodies make it easy to have physically realistic movements, like bouncing around, but are a lot harder to control since you have to apply force to get the movement you want. CharacterControllers on the other hand (or setting the position yourself for that matter) gives you full control, but you have to implement some of "smoothnes" into it that you get for free with the Rigidbody.
    I'd say those are the two main factors to consider. Having physically realistic movements, that are hard to control (thus writing code to make it more controllable), vs. having perfectly controllable movements, but having to add code that makes it feel less on-rail. Even tho, from what i read follow-cams seem to be a bit more tricky for rigidbodies, so i'd say overall, for most game concepts, a CharacterController based approach works best. You'll have to see what works for you.

    Edit: also, i believe you are not supposed to directly set the velocity, but rather use AddForce on the rigidbody to actually get the physically realistic movement which is the main argument for rigidbodies.

    Good luck!
     
  11. heromade

    heromade

    Joined:
    Aug 27, 2017
    Posts:
    33
    I know, but right now I am setting the position the same as I would set the the velocity. So I would not have to change that much I guess. And there was some reason why I did not use the AddForce for movement, I think it was because the box collider would just fall or the drag would be too annoying for the player.
    But I will find out what works best.