Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Rotate object based on velocity

Discussion in 'Scripting' started by compyler, May 17, 2023.

  1. compyler

    compyler

    Joined:
    Mar 30, 2020
    Posts:
    94
    Hello!

    In my game I have a GameObject (called Ball) that has a RigidBody. I want to roll the ball over the ground. Unfortunately I assigned the floor a PhysicsMaterial with friction = 0 (which I cant change cause I already created 100+ levels).
    Since the friction is 0 the ball only slides over the floor without any rotation. I want to fake the rotation as purely graphics effect. Therefore I added a childobject "BallGeometry" that holds the ball geometry (MeshRenderer).
    I made a screenshot to show the hierarchy:


    Currently the ball just slides forward along the forward axis (blue). To fake a rotation I now want to rotate the "BallGeometry" child object around its local Right-Axis (right arrow) based on the rigidbody's velocity.
    By only manipulating "BallGeometry" I don't interfere with the physics of the RigidBody (which is placed on root "Ball").

    I tried this code:
    Code (CSharp):
    1. float moveSpeed = rigidBody.velocity.magnitude;
    2.         if(moveSpeed > 0.001f) {
    3.             ballGeometryTransform.rotation = Quaternion.LookRotation(rigidBody.velocity);
    4.         }
    With this code the ball is always aligned with its velocity (i.e. if the ball is pushed to the left, BallGeometry forward axis points to the left) but the ball is not spinning at all.

    Does anyone know how I could extend to code to make the ball rotate around its local "right" axis based on the rigidbody's velocity?
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,862
    Well
    Quanternion.LookRotation
    isn't going to work at all. That gives you a rotation that looks in particular direction, which isn't what you want at all.

    This seems like a good use for Vector3.Cross to give you a direction that is perpendicular to the direction it's heading in. The Cross product of it's velocity and 'up' should give you this.

    So firstly I wouldn't make the ball a child of the rigidbody. Make them siblings, and code the mesh to simply match the rigidbody's position every frame. Then you can use that axis to rotate the ball.

    I would read CatLikeCoding's page on this which describe how to work out how much to rotate the ball by: https://catlikecoding.com/unity/tutorials/movement/rolling/
     
  3. compyler

    compyler

    Joined:
    Mar 30, 2020
    Posts:
    94
    I think I have solved it!

    I compute a right vector via cross product and then use the circular arc equation to map from velocity to rotation.

    In case some encounters the problem in the future here is my code:
    Code (CSharp):
    1. Vector3 ballDir = rigidBody.velocity.normalized;
    2. ballRightDir = Vector3.Cross(Vector3.up, ballDir);
    3.        
    4. float dist = rigidBody.velocity.magnitude * Time.fixedDeltaTime;
    5. float alpha = (dist * 180.0f) / (Mathf.PI * 0.37f);
    6. ballGeometryTransform.Rotate(ballRightDir, alpha, Space.World);