Search Unity

Rolling rigidbody while staying level to surface normals

Discussion in 'Physics' started by h0nka, Jun 2, 2020.

  1. h0nka

    h0nka

    Joined:
    Apr 7, 2013
    Posts:
    109
    Hi

    I am working on a hovercraft type racing game. I have a rigidbody on my craft which I yaw with AddTorque around the y-axis. To keep the craft level to the surface i additionally add torque on the x and z axes to rotate it to match the surface normal below the craft. However, I would very much like (purely as an animation/effect) to have the craft roll about +/-20 degrees when i yaw to get a leaning effect. When I try to implement this the craft continously jumps and jitters will rolling, so I am thinking the the leveling out torque is fighting the rolling torque.

    I know how to achieve this effect without physics, by simply parenting an object to yaw, and have the child do the roll effect around its own axis, but this sort of parenting does not work with rigidbodies.

    This is the kind of effect i want to achieve:



    And here is the code so far:

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using UnityEngine;
    4.  
    5. [RequireComponent(typeof(Rigidbody))]
    6. public class EngineController : MonoBehaviour
    7. {
    8.     public float Speed { get { return _rb.velocity.magnitude; } }
    9.  
    10.     public InputManager InputManager;
    11.     public float MaxForce;
    12.     public float YawEffect = 1f;
    13.     public float RollLevelEffect = 1f, PitchLevelEffect = 1f;
    14.     public Transform[] HoverPoints;
    15.     public float HoverHeight = 2.0f;
    16.     public float HoverForce = 9.0f;
    17.  
    18.     private Rigidbody _rb;
    19.     private float _thrust;
    20.     private float _rollInput, _yawInput, _pitchInput;
    21.  
    22.     private void Awake()
    23.     {
    24.         _rb = GetComponent<Rigidbody>();
    25.     }
    26.  
    27.     private void Update()
    28.     {
    29.         SetInput();
    30.  
    31.         Debug.Log("velocity: " + _rb.velocity.magnitude);
    32.     }
    33.  
    34.     private void SetInput()
    35.     {
    36.         float inLeft = InputManager.VerticalLeft;
    37.         float inRight = InputManager.HorizontalRight;
    38.  
    39.         _thrust = 2f + inLeft;
    40.         _yawInput = inRight;
    41.     }
    42.  
    43.     private void FixedUpdate()
    44.     {
    45.         Hover();
    46.         CalculateTorque();
    47.         CalculateForce();
    48.     }
    49.  
    50.     private void CalculateTorque()
    51.     {
    52.         Vector3 roll = _rollInput * RollLevelEffect * transform.forward;
    53.         Vector3 pitch = _pitchInput * PitchLevelEffect * transform.right;
    54.         Vector3 yaw = _yawInput * YawEffect * transform.up;
    55.  
    56.         Vector3 torque = Vector3.zero;
    57.         torque += roll;
    58.         torque += yaw;
    59.         torque += pitch;
    60.  
    61.         _rb.AddTorque(torque, ForceMode.VelocityChange);
    62.     }
    63.  
    64.     private void CalculateForce()
    65.     {
    66.         Vector3 force = Vector3.zero;
    67.         force += transform.forward * MaxForce * _thrust;
    68.  
    69.         _rb.AddForce(force, ForceMode.Acceleration);
    70.     }
    71.  
    72.     private void Hover()
    73.     {
    74.         RaycastHit hit;
    75.  
    76.         float pitchAngle = 0f;
    77.         float rollAngle = 0f;
    78.  
    79.         for (int i = 0; i < HoverPoints.Length; i++)
    80.         {
    81.             if (Physics.Raycast(HoverPoints[i].position, -transform.up, out hit, Mathf.Infinity))
    82.             {
    83.                 float force = HoverForce;
    84.  
    85.                 if (hit.distance > HoverHeight)
    86.                     force *= 0.2f;
    87.  
    88.                 _rb.AddForceAtPosition(Vector3.up * force * (HoverHeight - hit.distance), HoverPoints[i].position);
    89.  
    90.                 pitchAngle += Vector3.SignedAngle(-HoverPoints[i].up, -hit.normal, HoverPoints[i].right) * Mathf.Deg2Rad;
    91.                 rollAngle += Vector3.SignedAngle(-HoverPoints[i].up, -hit.normal, HoverPoints[i].forward) * Mathf.Deg2Rad;
    92.  
    93.                 // THE FAKE ROLL EFFECT!
    94.                 rollAngle += -_yawInput * 45f * Mathf.Deg2Rad;
    95.  
    96.                 Transform child = HoverPoints[i].GetChild(0);
    97.            
    98.                 if (child != null)
    99.                     child.transform.position = hit.point;
    100.             }
    101.         }
    102.  
    103.         pitchAngle /= HoverPoints.Length;
    104.         rollAngle /= HoverPoints.Length;
    105.  
    106.         _pitchInput = pitchAngle;
    107.         _rollInput = rollAngle;
    108.     }
    109. }
    110.  
    Does anyone have a suggestion?

    Thanks
     
    Last edited: Jun 2, 2020
  2. h0nka

    h0nka

    Joined:
    Apr 7, 2013
    Posts:
    109
    Never mind. Some code simplification solved it. The hoverforces actually managed to level out the hovercraft just fine.