Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Newbie question: Rigidbody's rotation is lagging

Discussion in 'Physics' started by semaforo, Oct 30, 2019.

  1. semaforo

    semaforo

    Joined:
    Jun 25, 2017
    Posts:
    3
    Hey guys, newbie here. Not exactly a programmer, but I started recently to mess around with Unity and Bolt, and I was trying to make a few things here and there.

    But I recently ran into an issue on a controller I'm trying to make.

    Every time I change directions on the keyboard, the character itself takes a few frames to actually catch up. Which means if you are facing right, and press left on the keyboard, the character will walk a bit right before turning left.

    I'll try to explain how I made the controller, since Bolt doesn't really provide a C# script, sorry. But I don't think it's hard to understand.
    - My character is using a RigidBody component.
    On Update:
    - I first shoot a raycast downwards, get the normal, do a Vector3.Cross with the player's transform.right and set it as a variable called forwardDirection;
    - I then take input from both Axis (GetAxis Horizontal and Vertical) onto an Atan2 function, multiyply by Rad2Deg, add my camera's Y rotation, and set the result as a Y value on a quaternion variable called targetRotation;
    - I put an if statement (if GetAxis Horizontal !=0 or GetAxis Vertical !=0), then set the transform.rotation of the player to equal targetRotation;
    On Fixed Update:
    - I use the same if statement (if GetAxis Horizontal !=0 or GetAxis Vertical != 0), then RIgidbody.MovePosition to Rigidbody.position + forwardDirection * speed * time.deltaTime.

    Hopefully this gif helps illustrate (the red capsule is the player, the white one is representing my actual input on the keyboard, and the blue arrow is a debug.drawray from transform.position to forwardVector).


    My begginer skills in debugging have led me to the following:
    I substituted transform.Rotation for Rigidbody.MoveRotation, put it in FixedUpdate before the actual movement took place, and I kept the input on Update. What I got was that the delay was gone, but the player always rotates towards the camera before it rotates towards my input, kinda like the Atan2 function is giving 0 before the actual angle of my input. And what I take from that is... I don't know. Is that a thing Atan2 does?

    Can anybody help? Is the lack of a proper C# script here a lost cause for online help? Any help is appreciated.
     
  2. semaforo

    semaforo

    Joined:
    Jun 25, 2017
    Posts:
    3
    A few days later, I'm still thinking about this and trying to find a solution. Here are a few possibilities I thought
    • My computer (a relatively old laptop) is not powerful enough to run unity.
    I tried on a much powerful desktop, and it didn't fix my issue at all.
    • Atan2 has a native delay
    I tried creating a very basic function to check if Atan2 was indeed having a delay in its output.

    Essentially I made an Empty Object who only took the Horizontal and Vertical Axis, applied them in an Atan2 function, and printed the result.
    Playtesting this shows that Atan2's results are super weird. It always gives me the right angle, but it totally has a delay, and sometimes it prints the result more times than it should (but never at the moment of input, always one or two frames late), although this one could be just placebo on my part, upon seeing its delays.
    So Atan2 has a native delay to it, right?
    I then decided to drop Atan2. Made another system that took the Axis inputs, mapped them on a Vector 3, then used Vector3.SignedAngle between Vector3.forward and my input vector.
    It gave me the same results as the Atan2 function, and apparently it had no lag.

    Unfortunately once I actually applied on my character, it didn't fix my issue at all either, it's the exact same thing. My character always moves a little bit on the direction he is facing before he actually makes a turn. And now I don't even know if Atan2 has a delay either or if I'm just going crazy.

    And this is where I'm at currently...

    My third guess is that Bolt is just messing up, and if I use VisualStudio and stop being afraid of actually coding, it will work out. I'm gonna try actually writing some code now and seeing if it works.

    EDIT: Downloaded VisualStudio, and wrote the following

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Atan2 : MonoBehaviour
    6. {
    7.  
    8.  
    9.     Vector2 input;
    10.     float angle;
    11.    
    12.     Quaternion targetRotation;
    13.  
    14. void Update()
    15.     {
    16.         GetInput();
    17.  
    18.         if (Mathf.Abs(input.x) < 1 && Mathf.Abs(input.y) < 1) return;
    19.  
    20.         CalculateDirection();
    21.         Rotate();
    22.  
    23.     }
    24.  
    25.     void GetInput()
    26.     {
    27.         input.x = Input.GetAxisRaw("Horizontal");
    28.         input.y = Input.GetAxisRaw("Vertical");
    29.  
    30.     }
    31.  
    32.     void CalculateDirection()
    33.     {
    34.         angle = Mathf.Atan2(input.x, input.y);
    35.         angle = Mathf.Rad2Deg * angle;
    36.  
    37.     }
    38.  
    39.     void Rotate()
    40.     {
    41.         targetRotation = Quaternion.Euler(0, angle, 0);
    42.         transform.rotation = targetRotation;
    43.  
    44.         Debug.Log(transform.rotation);
    45.     }
    46.    
    47.  
    48. }
    It essentially comes from this tutorial here:


    Except I don't slerp my rotation, I just change the transform.rotation immediately.

    This code gives the exact same delay I'm having with Bolt, so I'm guessing this is not an issue with it.

    I also just rendered the title of this thread false, because I applied this to an empty game object, with no RigidBody, and it's still lagging by a frame or two. So it's not just the RigidBody either.
    Try applying this to an object, and tapping a direction on your keyboard to see what I mean. The console won't print out the transform.rotation immediately, it will lag.
     
    Last edited: Nov 2, 2019
  3. semaforo

    semaforo

    Joined:
    Jun 25, 2017
    Posts:
    3
    I guess my problem in the end is either not that simple or I'm just not able to actually explain it properly (very sorry, English is not my first language).

    But I guess this is my last post in this thread unless someone can actually understand what my problem here is.
    Either way, I have found out a bunch of things by going out to a few friends' houses and trying it out on other computers.

    Turns out, this whole thing is only happening on lower spec rigs, because something here is probably frame dependent (the powerful desktop I tried last time was actually having other issues unrelated to Unity and wasn't running the game very well, so I tried someone else's PC and it worked well).

    But it doesn't really solve my issues. I tried limiting the game's framerate with:

    Code (CSharp):
    1.  void Awake () {
    2.      QualitySettings.vSyncCount = 0;
    3.      Application.targetFrameRate = 10;
    4. }
    and the issue consistently pops up, but it doesn't really help me.

    My conclusion is that if the game is performing differently dependending on framerate, then it means I'm lacking a Time.deltaTime somewhere in the code. That being said, I tried applying a Time.deltaTime everywhere, and nothing. I tried Lerping and Slerping some of these values (like the transform.rotation), just so I could multiply it by delta time and nothing.

    For a simple test, I tried pressing the left and right keys at a fast pace, to see the character respond. On the lower end rig (top half), the player often doesn't turn (the game here is running at around 70FPS). On the higher end though (bottom half), it works perfectly (forgot the FPS, but it was above 200).



    I legitmately don't know anymore what I can try. I tried making the turning in about 3-4 different ways, and they all behave the same, Time.deltaTime is not helping at all.

    I guess the issue is just unoptimization and inexperience on my part. I'll probably scrap this controller and make another one from scratch. Thanks if anyone tried looking into it themselves.