Search Unity

AddForce and AddTorque in DOTS Physics

Discussion in 'Physics for ECS' started by maxzoech, Mar 17, 2020.

  1. maxzoech

    maxzoech

    Joined:
    Dec 23, 2013
    Posts:
    23
    Hi everyone!

    I'm new to DOTS physics but in classic PhysX one could easily add forces to a rigidbody. What is the equivalent for doing this in the new DOTS physics.

    Thanks in advance
     
  2. NotaNaN

    NotaNaN

    Joined:
    Dec 14, 2018
    Posts:
    325
    In the Unity.Physics.Extensions namespace, there is a 'PhysicsWorldExtensions' class and 'ComponentExtensions' class. Both of these classes contain methods to do common things such as apply impulses in a linear, angular, or linear and angular fashion.

    Here's a bit of sample code to help you get started:
    Code (CSharp):
    1.  
    2.  
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6. using Unity.Physics;
    7. using Unity.Physics.Extensions;
    8. using Unity.Entities;
    9. Unity.Mathematics;
    10.  
    11. /// <summary> Our simple impulse component. </summary>
    12. [System.Serializable]
    13. public struct ApplyImpulseOnKeyData : IComponentData
    14. {
    15.     public float Force;
    16.     public float3 Direction;
    17. }
    18.  
    19. /// <summary> Our simple system. </summary>
    20. [UpdateAfter(typeof(Unity.Physics.Systems.EndFramePhysicsSystem))]
    21. public class ApplyImpulseOnKeySystem : SystemBase
    22. {
    23.  
    24.     protected override void OnUpdate()
    25.     {
    26.         /// Get the physics world.
    27.         // You don't need to do this if you're going to use ComponentExtensions.ApplyLinearImpulse, but I have kept the code in to show you how to do it.
    28.         PhysicsWorld physicsWorld = World.DefaultGameObjectInjectionWorld.GetExistingSystem<Unity.Physics.Systems.BuildPhysicsWorld>().PhysicsWorld;
    29.  
    30.         Entities.WithoutBurst().ForEach(
    31.         (
    32.             Entity _entity,
    33.             ref PhysicsVelocity _physicsVelocity,
    34.             ref PhysicsMass _physicsMass,
    35.             in ApplyImpulseOnKeyData _applyImpulseOnKeyData) =>
    36.         {
    37.             if (Input.GetKey(KeyCode.Space))
    38.             {
    39.                 /// Get the entity's rigidbody index.
    40.                 // Again, you do not have to do this for ComponentExtensions.ApplyLinearImpulse, but I have kept it in as a nice example.
    41.                 int rigidbodyIndex = PhysicsWorldExtensions.GetRigidBodyIndex(physicsWorld, _entity);
    42.  
    43.                 /// Apply a linear impulse to the entity.
    44.                 PhysicsComponentExtensions.ApplyLinearImpulse(ref _physicsVelocity, _physicsMass, _applyImpulseOnKeyData.Direction * _applyImpulseOnKeyData.Force);
    45.  
    46.                 // There is an alternative method within PhysicsWorldExtensions that does the same thing but with different inputs.
    47.                 // It is recommended to use whichever is most applicable, but favor ComponentExtensions if possible.
    48.                 // Here is the method commented out, using all of the necessary information to get an identical effect as the method above!
    49.        
    50.                 /// PhysicsWorldExtensions.ApplyLinearImpulse(physicsWorld, rigidbodyIndex, _applyImpulseOnKeyData.Direction * _applyImpulseOnKeyData.Force);
    51.        
    52.                 // Remember to remove the ComponentExtensions.ApplyLinearImpulse version if you use this one!
    53.                 // You don't want to be applying the impulse TWICE, do you?
    54.  
    55.                 // Thanks SteveeHavok! :D
    56.             }
    57.         }).Run();
    58.     }
    59. }
    60.  
    61. /// <summary> Our simple authoring component. </summary>
    62. public class ApplyImpulseOnKeyAuthoring : MonoBehaviour, IConvertGameObjectToEntity
    63. {
    64.     public void OnEnable() { }
    65.  
    66.     public ApplyImpulseOnKeyData applyImpulseOnKeyData;
    67.  
    68.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    69.     {
    70.         dstManager.AddComponentData(entity, applyImpulseOnKeyData);
    71.     }
    72. }
    73.  
    Just place the above code in an empty script, attach that script to a GameObject with ConvertToEntity and the necessary PhysicsBody and PhysicsShape, and you should be good to go!


    EDIT 1: Forgot the Unity.Mathematics namespace. Added it.
    EDIT 2: Forgot to remove DisableAutoCreation attribute from the system. Removed it.
    EDIT 3: I've added an UpdateAfter so the system will update after physics, and not possibly sometime in-between it. Good cacth Stevee!
    EDIT 4: I have updated the script to use ComponentExtensions instead of PhysicsWorldExtensions, but I have left PhysicsWorldExtensions in as an option!
    EDIT 5: Cleaned up post and updated code.
     
    Last edited: Feb 27, 2021
    bb8_1, anarkiastd, Antypodish and 8 others like this.
  3. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Great answer. I do recommend concentrating on the ComponentExtensions functions as these work on the IComponentData structs rather than manipulating the data in the PhysicsWorld.
    PhysicsWorldExtensions are more relevant for simulation callbacks while ComponentExtensions are more relevant for ECS systems.

    Regardless you need to be clear about the ordering of your custom codes so that the likes of Build/ExportPhysicsWorld don't overwrite your changes.
     
  4. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Can you point to a basic example? I'm quite interested on this as well.
     
    NotaNaN likes this.
  5. NotaNaN

    NotaNaN

    Joined:
    Dec 14, 2018
    Posts:
    325
    See my updated answer. In it I'm using ComponentExtensions instead of PhysicsWorldExtensions now!

    The main difference between the two is that ComponentExtensions takes inputs that ECS systems can supply easily using the Entities.ForEach Lambdas. Things such as the PhysicsVelocity and PhysicsMass!

    PhysicsWorldExtensions.ApplyLinearImpulse—which is probably the one you are accustomed to using—requires you to pass in data that helps find the rigidbody you wish to apply the changes to, and then apply those changes.

    Needless to say, it is better to use ComponentExtensions when able. It's more efficient, and simpler. :p
     
    Last edited: Apr 10, 2020
    Antypodish and Edy like this.
  6. PragneshRathod

    PragneshRathod

    Joined:
    Feb 7, 2018
    Posts:
    7
    Last edited: Apr 14, 2020
    bb8_1, Sab_Rango and Edy like this.
  7. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
  8. Fluidmind

    Fluidmind

    Joined:
    Jan 10, 2020
    Posts:
    28
    I have a question on this - All these methods appear to take their vector as world space. Can I get a code example of how to apply a local to world translation for use with these functions? or can these be extended to take a Space parameter? Thanks.
     
    adammpolak and shotoutgames like this.
  9. PragneshRathod

    PragneshRathod

    Joined:
    Feb 7, 2018
    Posts:
    7
    Take Look

    https://forum.unity.com/threads/whats-the-math-behind-transform-transformpoint.107401/

     
  10. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    This post may also help with vector transforms.
     
  11. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,779
    Sorry for that little necro, but I think is pretty valid.

    Just heads up a bit, as
    ComponentExtensions
    is depreciated and replaced with
    PhysicsComponentExtensions
     
    bb8_1, Occuros and NotaNaN like this.