Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Let us know a bit about your interests, and if you'd like to become more directly involved. Take our survey!
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Some skate physics problem

Discussion in 'Physics' started by Mehd, Aug 9, 2018.

  1. Mehd

    Mehd

    Joined:
    Apr 29, 2016
    Posts:
    79
    Hello y'all

    I'm making a small skating game, mostly because I'm interested in mechanics but I'm stuck with an orientation problem I can't figure out.

    To adapt the rotation of the skater with respect to its environment, I break the logic into several components:

    • A PhysicRotation : Returns the Quaternion to go from the skater's transform.up to the normal of the point he's at
    Code (CSharp):
    1. Quaternion GetPhysicsRotation()
    2.     {
    3.         Vector3 target_vec = Vector3.up;
    4.         Ray ray = new Ray(transform.position, Vector3.down);
    5.         RaycastHit hit;
    6.  
    7.         if(Physics.Raycast(ray, out hit, 1.05f*height))
    8.         {
    9.             target_vec = hit.normal;
    10.         }
    11.  
    12.         return Quaternion.FromToRotation(transform.up, target_vec);
    13.     }
    • A velocity rotation: So that the character faces the direction he's going. This rotation is contrained to a plane
    Code (CSharp):
    1. Quaternion GetVelocityRot()
    2.     {
    3.         Vector3 vel = rb.velocity;
    4.         if(vel.magnitude > 0.2f)
    5.         {
    6.             vel.y = 0;
    7.             Vector3 dir = transform.forward;
    8.             dir.y = 0;
    9.             Quaternion vel_rot = Quaternion.FromToRotation(dir.normalized, vel.normalized);
    10.             return vel_rot;
    11.         }
    12.         else
    13.             return Quaternion.identity;
    14.     }
    • And finally, I an InputRotation that rotates the force applied for moving
    • All of this is then tied in this function:
    Code (CSharp):
    1. void SkaterMove(Vector2 inputs)
    2.     {
    3.    
    4.  
    5.         Quaternion PhysicsRotation = aerial ? Quaternion.identity : GetPhysicsRotation(); // Rotation according to ground normal
    6.         Quaternion VelocityRotation = GetVelocityRot();
    7.         Quaternion InputRotation = Quaternion.identity;
    8.         Quaternion ComputedRotation = Quaternion.identity;
    9.  
    10.  
    11.         if(inputs.magnitude > 0.1f)
    12.         {
    13.             Vector3 adapted_direction = CamToPlayer(inputs);
    14.             Vector3 planar_direction = transform.forward;
    15.             planar_direction.y = 0;
    16.             InputRotation = Quaternion.FromToRotation(planar_direction, adapted_direction);
    17.  
    18.             if(!aerial)
    19.             {
    20.                 Vector3 Direction = InputRotation*transform.forward*Speed;
    21.                 rb.AddForce(Direction);
    22.             }
    23.         }
    24.  
    25.         ComputedRotation = PhysicsRotation*VelocityRotation*transform.rotation;
    26.         transform.rotation = Quaternion.Lerp(transform.rotation, ComputedRotation, RotatingSpeed*Time.deltaTime);
    27.  
    28.  
    29.  
    30.     }

    The thing works rather well, but always stumbles on one specific case. Here's a video I made the explain it better:


    Basically, when in the quarter, if the character's speed carries him in the air, he does a strange spin and and breaks its flow. I can't figure out where in the code I'm allowing it to do this. I've tried various tests, but I can't figure out where the problem is.

    Could anyone point me in the good direction ?

    Thanks !
     
  2. David_Liebemann

    David_Liebemann

    Joined:
    Apr 29, 2018
    Posts:
    1
    Hey - at around 0:30 you demonstrate a case that's working (slow speed, player is touching the ramp at all time) and around 0:39 there's a case that's not working (higher speed, player is airborne for a short time). Could it be the part
    Code (CSharp):
    1.  Quaternion PhysicsRotation = aerial ? Quaternion.identity : GetPhysicsRotation(); // Rotation according to ground normal
    that's causing the PhysicsRotation to be an identity quaternion for a moment, and then return to rotation according to ground normal?
     
  3. Mehd

    Mehd

    Joined:
    Apr 29, 2016
    Posts:
    79
    But if it's the identity quaternion, shouldn''t it just keep its current rotation ? That was actually what I was expecting.
     
  4. GoodByte

    GoodByte

    Joined:
    Dec 14, 2013
    Posts:
    2
    You are right, the way you are concatenating the rotations that should work.
    Look at exactly 0:10 in the video - the instant you get airborne, the charakters rotation returns to horizontal. At that point it doesn't really feel weird, but I guess the same happens on the ramp, which then leads to unexpected behaviour.
    That rotation is not in the code you have shown - all rotations in the code shown are limited by the Lerp you are using, so they can't cause instant rotations as seen in the video.
     
  5. Mehd

    Mehd

    Joined:
    Apr 29, 2016
    Posts:
    79
    Your comment led me to an idea. Because the rotation is never touched outside of this Lerp. So, I monitored the difference between my current rotation and the computed rotation and sometimes, the difference amounts to 100 degrees. So I'm gonna try to clamp it to a max threshold, see if it improves. I'll let you know !

    Thanks !
     
    GoodByte likes this.
  6. MisterMashu

    MisterMashu

    Joined:
    Oct 23, 2012
    Posts:
    3
    Hi! Try increasing the length of the downward raycast. I paused the video at 0:38 and you can see an arc on the red downward rays. To me, that makes me think they're not touching the ground, which would make your PhysicsRotation be do nothing
     
  7. Mehd

    Mehd

    Joined:
    Apr 29, 2016
    Posts:
    79
    Thanks y'all for your ideas. I think I figured it out. The Lerp speed was actually very high. A feature needed to for the quarter, but dreadful when moving in the air. Hence, I just added a AerialRotationSpeed and I just select which speed to use based on aerial boolean.

    I'm implementing input rotation in the air, I'll let you guys know !

    Thanks to all of you !
     
    GoodByte likes this.
  8. GoodByte

    GoodByte

    Joined:
    Dec 14, 2013
    Posts:
    2
    Nice, good luck then with the rest of the project! Looks really good by the way
     
  9. Mehd

    Mehd

    Joined:
    Apr 29, 2016
    Posts:
    79
    Hey ! Here's an update ! (:)