Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Convert Rigidbody.AddForceAtPosition to Unity Physics.

Discussion in 'Physics for ECS' started by Filtiarn_, May 2, 2020.

  1. Filtiarn_

    Filtiarn_

    Joined:
    Jan 24, 2013
    Posts:
    173
    I'm writing a buoyancy system for Unity Physics by converting a rigidbody one I got.

    I'm not sure how to convert this. I can't find anything on how to add force at position.
    Code (CSharp):
    1.  // apply drag relative to water
    2.         var forcePosition = _rb.position + _forceHeightOffset * Vector3.up;
    3.         _rb.AddForceAtPosition(Vector3.up * Vector3.Dot(Vector3.up, -velocityRelativeToWater) * _dragInWaterUp, forcePosition, ForceMode.Acceleration);
    4.         _rb.AddForceAtPosition(transform.right * Vector3.Dot(transform.right, -velocityRelativeToWater) * _dragInWaterRight, forcePosition, ForceMode.Acceleration);
    5.         _rb.AddForceAtPosition(transform.forward * Vector3.Dot(transform.forward, -velocityRelativeToWater) * _dragInWaterForward, forcePosition, ForceMode.Acceleration);
     
  2. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
    Unity.Physics.Extensions has some extension methods for applying impulses. To apply forces, use force * deltaTime to get impulse
    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Entities;
    3. using Unity.Jobs;
    4. using Unity.Physics.Extensions;
    5. using Unity.Transforms;
    6.  
    7. [UpdateBefore(typeof(BuildPhysicsWorld))]
    8. public class ImpulseAtPointSystem : SystemBase
    9. {
    10.     protected override void OnUpdate()
    11.     {
    12.         Entities.ForEach((DynamicBuffer<ImpulseAtPoint> impulses, ref PhysicsVelocity velocity, in PhysicsMass mass, in Translation translation, in Rotation rotation) =>
    13.         {
    14.             NativeArray<ImpulseAtPoint> impulseArray = impulses.AsNativeArray();
    15.             for (int i = 0; i < impulseArray.Length; i++)
    16.             {
    17.                 velocity.ApplyImpulse(mass, translation, rotation, impulseArray[i].Impulse, impulseArray[i].Point);
    18.             }
    19.             impulses.Clear();
    20.         }).ScheduleParallel();
    21.     }
    22. }
     
  3. Filtiarn_

    Filtiarn_

    Joined:
    Jan 24, 2013
    Posts:
    173
    Thanks.

    I did this.

    Code (CSharp):
    1. //Do Physics
    2.                 if (_inWater)
    3.                 {
    4.                     forces.Clear();
    5.                     forces.Add(Vector3.up * Vector3.Dot(Vector3.up, -velocityRelativeToWater) * _dragInWaterUp);
    6.                     forces.Add(localToWorld.Right * Vector3.Dot(localToWorld.Right, -velocityRelativeToWater) * _dragInWaterRight);
    7.                     forces.Add(localToWorld.Forward * Vector3.Dot(localToWorld.Forward, -velocityRelativeToWater) * _dragInWaterForward);
    8.  
    9.                     var forcePosition = position + _forceHeightOffset * Vector3.up;
    10.  
    11.                     for (int i = 0; i < forces.Count; i++)
    12.                         AddForceAtPosition(ref physicsMass, ref translation,ref rotation, ref physicsVelocity, PhysicsWorldExtensions.GetRigidBodyIndex(physicsWorld, entity), forces[i],forcePosition, ForceMode.Acceleration);
    13.                 }
    14.  
    15.   private void GetImpulseFromForce(ref PhysicsMass mass, float3 force, UnityEngine.ForceMode mode, float timeStep, out float3 impulse, out PhysicsMass impulseMass)
    16.         {
    17.             var unitMass = new PhysicsMass { InverseInertia = new float3(1.0f), InverseMass = 1.0f, Transform = mass.Transform };
    18.  
    19.             switch (mode)
    20.             {
    21.                 case UnityEngine.ForceMode.Force:
    22.                     // Add a continuous force to the rigidbody, using its mass.
    23.                     impulseMass = mass;
    24.                     impulse = force * timeStep;
    25.                     break;
    26.                 case UnityEngine.ForceMode.Acceleration:
    27.                     // Add a continuous acceleration to the rigidbody, ignoring its mass.
    28.                     impulseMass = unitMass;
    29.                     impulse = force * timeStep;
    30.                     break;
    31.                 case UnityEngine.ForceMode.Impulse:
    32.                     // Add an instant force impulse to the rigidbody, using its mass.
    33.                     impulseMass = mass;
    34.                     impulse = force;
    35.                     break;
    36.                 case UnityEngine.ForceMode.VelocityChange:
    37.                     // Add an instant velocity change to the rigidbody, ignoring its mass.
    38.                     impulseMass = unitMass;
    39.                     impulse = force;
    40.                     break;
    41.                 default:
    42.                     impulseMass = mass;
    43.                     impulse = float3.zero;
    44.                     break;
    45.             }
    46.         }
    47.  
    48.  
    49.  
    50.         private void AddForceAtPosition(ref PhysicsMass physicsMass, ref Translation translation,ref Rotation rotation, ref PhysicsVelocity velocity, int entityIndex, float3 force, float3 position, ForceMode mode = ForceMode.Force)
    51.         {
    52.  
    53.            GetImpulseFromForce(ref physicsMass,force, mode, deltaTime, out float3 impulse, out PhysicsMass impulseMass);
    54.            velocity.ApplyImpulse(impulseMass, translation, rotation, impulse, position);
    55.         }
    56.  
     
    RaveOnTheGrave likes this.