Search Unity

Question AddForce at Local position and Rotate Around Local Y Axis

Discussion in 'Physics' started by GR4MPI, Mar 10, 2023.

  1. GR4MPI

    GR4MPI

    Joined:
    Feb 24, 2023
    Posts:
    1
    To better understand my problem i will first describe what i want to do.

    Objective:
    I want to make a drone with four motors that add downward force. The motors will be controlled by input from the gamepad.
    The LeftStick forward/backward will control all motors up/down.
    The LeftStick left/right will control the rotation around the vertical axis left/right.
    The RightStick left/right/forward/backward control the tilt left/right/forward/backward.

    My implementation:
    - Motors are represented by AddForceAtPosition(force, point) where point is position of drone +- offset (offset indicates if motor is FrontRight, FrontLeft, RearRight, RearLeft)
    - Moving LeftStick forward/backward adds force using AddForceAtPosition at all 4 motor positions
    - Moving LeftStick left/right adds torque using AddRelativeTorque
    -Moving RightStick left adds force using AddForceAtPosition to 2 motors on Right side
    -Moving RightStick right adds force using AddForceAtPosition to 2 motors on Left side
    -Moving RightStick forward adds force using AddForceAtPosition to 2 motors on Rear side
    -Moving RightStick backward adds force using AddForceAtPosition to 2 motors on Front side

    The problem:
    First lets begin with what works (or i think it works as i want):
    - flying up and down using LeftStick(forward/backward)
    - rotating to the left and right using LeftStick(left/right)
    - tilting forward/backward/left/right using RightStick

    What dont work:
    - when i rotate drone using LeftStick(left/right) and then move RightStick forward, the drone tilts towards world forward axis instead of the drones forward axis.

    So my question is, how can i make the drone tilt in directions of its axis instead of the world axis ?
    And I also want to ask if the other functions (which i think work as i want) really work as i want or if it is just a coincidence.

    My code:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    3.  
    4. public class Motors : MonoBehaviour
    5. {
    6.     public Rigidbody rb;
    7.     public Gamepad gamepad = Gamepad.current;
    8.     public float strength = 10f;
    9.     public float strengthRotations = 5f;
    10.     public float rotationSpeed = 10f;
    11.     public float maxSpeed = 50f;
    12.  
    13.     // Update
    14.     void FixedUpdate()
    15.     {
    16.         if (rb.velocity.magnitude > maxSpeed)
    17.         {
    18.             rb.velocity = rb.velocity.normalized * maxSpeed;
    19.         }
    20.  
    21.         LeftStickInputActions(gamepad.leftStick.ReadValue().y, gamepad.leftStick.ReadValue().x);
    22.         RightStickInputActions(gamepad.rightStick.ReadValue().y, gamepad.rightStick.ReadValue().x);
    23.  
    24.     }
    25.  
    26.     void LeftStickInputActions(float InputThrottle, float InputRotation)
    27.     {
    28.         Vector3 FrontLeft = GetPosition(1.0f, 1.0f);
    29.         rb.AddForceAtPosition(strength * rb.transform.up * InputThrottle, FrontLeft);
    30.         Vector3 FrontRight = GetPosition(1.0f, -1.0f);
    31.         rb.AddForceAtPosition(strength * rb.transform.up * InputThrottle, FrontRight);
    32.         Vector3 RearLeft = GetPosition(-1.0f, 1.0f);
    33.         rb.AddForceAtPosition(strength * rb.transform.up * InputThrottle, RearLeft);
    34.         Vector3 RearRight = GetPosition(-1.0f, -1.0f);
    35.         rb.AddForceAtPosition(strength * rb.transform.up * InputThrottle, RearRight);
    36.  
    37.         rb.AddRelativeTorque(rb.transform.up * rotationSpeed * InputRotation);
    38.     }
    39.  
    40.     void RightStickInputActions(float InputDrive, float InputSteer)
    41.     {
    42.        
    43.         if (InputDrive > 0)
    44.         {
    45.             Vector3 RearRight = GetPosition(-1.0f, -1.0f);
    46.             rb.AddForceAtPosition(strengthRotations * rb.transform.up * InputSteer * -1, RearRight);
    47.             Vector3 FrontRight = GetPosition(1.0f, -1.0f);
    48.             rb.AddForceAtPosition(strengthRotations * rb.transform.up * InputSteer * -1, FrontRight);
    49.         }
    50.         if(InputDrive < 0)
    51.         {
    52.             Vector3 RearLeft = GetPosition(-1.0f, 1.0f);
    53.             rb.AddForceAtPosition(strengthRotations * rb.transform.up * InputSteer, RearLeft);
    54.             Vector3 FrontLeft = GetPosition(1.0f, 1.0f);
    55.             rb.AddForceAtPosition(strengthRotations * rb.transform.up * InputSteer, FrontLeft);
    56.         }
    57.         if (InputSteer > 0)
    58.         {
    59.             Vector3 FrontLeft = GetPosition(1.0f, 1.0f);
    60.             rb.AddForceAtPosition(strengthRotations * rb.transform.up * InputDrive * -1, FrontLeft);
    61.             Vector3 FrontRight = GetPosition(1.0f, -1.0f);
    62.             rb.AddForceAtPosition(strengthRotations * rb.transform.up * InputDrive * -1, FrontRight);
    63.         }
    64.         if (InputSteer < 0)
    65.         {
    66.             Vector3 RearRight = GetPosition(-1.0f, -1.0f);
    67.             rb.AddForceAtPosition(strengthRotations * rb.transform.up * InputDrive, RearRight);
    68.             Vector3 RearLeft = GetPosition(-1.0f, 1.0f);
    69.             rb.AddForceAtPosition(strengthRotations * rb.transform.up * InputDrive, RearLeft);
    70.         }
    71.         rb.angularVelocity = Vector3.zero;
    72.         rb.freezeRotation = true;
    73.         rb.freezeRotation = false;
    74.     }
    75.  
    76.     Vector3 GetPosition(float offsetX, float offsetZ)
    77.     {
    78.         Vector3 position = rb.transform.position;
    79.         position.x += offsetX;
    80.         position.z += offsetZ;
    81.         return position;
    82.     }
    83. }
    84.  
     
  2. leebissessar5

    leebissessar5

    Joined:
    Nov 15, 2022
    Posts:
    48
    Using an offset is kind of flawed since that assumes the drone has no rotation. You'd have to rotate the offsets based on its current rotation.

    Why not parent empty GameObjects on the position of each propeller? By doing that, you could refer to their Transforms in your script and use their positions in AddForceAtPosition().

    And again, don't overwrite velocities and angular velocities since that erases existing physics information about the object. If you need limits, simply saturate the propeller speeds or forces using Mathf.Clamp().

    You should use AddTorque() instead since you have transform.up inside of AddRelativeTorque. Other than that, not seeing other issues in the code.
     
    Last edited: Mar 18, 2023