Search Unity

Unity DOTS how do I change the Motion Type in Physics Body when two objects collide?

Discussion in 'Physics for ECS' started by MrKsi, Sep 6, 2022.

  1. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    Greetings, I ran into such a problem there is a wall that consists of many cubes, when I hit a sphere, I began to detect collisions and apply force to the object I encountered, but the joke is that the object I'm adjusting to has Motion Type Kinematic and I need to change it again to Dynamic when the sphere collided and cube. How do I do this? How do I get an instance of the Physics Body object to change the Motion Type in a collision?
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,497
    MrKsi likes this.
  3. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    I have several code scripts that I can demonstrate.
    First, spawn spheres in hybrid rendering:

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Mathematics;
    3. using Unity.Transforms;
    4. using UnityEngine;
    5.  
    6. public class Shoot : MonoBehaviour
    7. {
    8.     public GameObject Bullet;
    9.     public Transform PointSpawn;
    10.     public Camera Cam;
    11.  
    12.  
    13.     private Entity _sphereEntity;
    14.     private EntityManager _entityManager;
    15.     private BlobAssetStore _blobAssetStore;
    16.     private GameObjectConversionSettings _conversionSettings;
    17.  
    18.  
    19.     private void Start()
    20.     {
    21.         EntityObjectSetup();
    22.     }
    23.  
    24.     private void EntityObjectSetup()
    25.     {
    26.         _entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
    27.         _blobAssetStore = new BlobAssetStore();
    28.         _conversionSettings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, _blobAssetStore);
    29.         _sphereEntity = GameObjectConversionUtility.ConvertGameObjectHierarchy(Bullet, _conversionSettings);
    30.     }
    31.  
    32.  
    33.     private void Update()
    34.     {
    35.         if (Input.GetMouseButtonDown(0))
    36.         {
    37.             var entity = _entityManager.Instantiate(_sphereEntity);
    38.             var translation = new Translation
    39.             {
    40.                 Value = new float3(PointSpawn.transform.position.x, PointSpawn.transform.position.y, PointSpawn.transform.position.z)
    41.             };
    42.             var entityECS = new BulletECS()
    43.             {
    44.                 Direction = Cam.transform.forward,
    45.                 IsSpawned = false,
    46.                 Speed = 70,
    47.             };
    48.             _entityManager.SetComponentData(entity, entityECS);
    49.             _entityManager.SetComponentData(entity, translation);
    50.         }
    51.     }
    52.  
    53.     private void OnApplicationQuit()
    54.     {
    55.         _blobAssetStore.Dispose();
    56.     }
    57. }
    58.  
     
  4. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    Secondly, applying the physics of linear momentum to the sphere is here:
    P.S. There is also the code responsible for applying collisions to the cube
    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Mathematics;
    3. using Unity.Physics;
    4. using Unity.Physics.Extensions;
    5.  
    6. public class PhysicsECS : ComponentSystem
    7. {
    8.     protected override void OnUpdate()
    9.     {
    10.         Entities.ForEach
    11.             (
    12.         (ref PhysicsVelocity velocity, ref PhysicsMass physicsMass,ref BulletECS shoot) =>
    13.         {
    14.             if (!shoot.IsSpawned)
    15.             {
    16.                 var forceVector = (float3)shoot.Direction * shoot.Speed;
    17.                 velocity.ApplyLinearImpulse(physicsMass, forceVector);
    18.                 shoot.IsSpawned = true;
    19.             }
    20.         });
    21.  
    22.         Entities.ForEach
    23.            (
    24.        (ref PhysicsVelocity velocity, ref PhysicsMass physicsMass, ref FragmentECS fragment) =>
    25.        {
    26.            if (fragment.IsDelected)
    27.            {
    28.                var forceVector = (float3)fragment.Direction * fragment.Speed;
    29.                velocity.ApplyLinearImpulse(physicsMass, forceVector);
    30.                fragment.IsDelected = false;
    31.            }
    32.        });
    33.     }
    34. }
     
  5. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    Thirdly, these are the components that are on the sphere on the cube fragment:

    Code (CSharp):
    1. using Unity.Entities;
    2. using UnityEngine;
    3. [GenerateAuthoringComponent]
    4. public struct BulletECS : IComponentData
    5. {
    6.     public Vector3 Direction;
    7.     public int Speed;
    8.     public bool IsSpawned;
    9. }
    10. using Unity.Entities;
    11. using UnityEngine;
    12.  
    13. [GenerateAuthoringComponent]
    14. public struct FragmentECS : IComponentData
    15. {
    16.     public Vector3 Direction;
    17.     public int Speed;
    18.     public bool IsDelected;
    19. }
    20.  
     
  6. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    At the output I get this result:
     

    Attached Files:

  7. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    All I have to do is change the Motion Type on collision here:
    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Entities;
    3. using Unity.Jobs;
    4. using Unity.Physics;
    5. using Unity.Physics.Systems;
    6. using UnityEngine;
    7.  
    8. public class CollisionECS : JobComponentSystem
    9. {
    10.     private BuildPhysicsWorld buildPhysicsWorldSystem;
    11.     private StepPhysicsWorld stepPhysicsWorldSystem;
    12.     private EndSimulationEntityCommandBufferSystem commandBufferSystem;
    13.  
    14.     protected override void OnCreate()
    15.     {
    16.         buildPhysicsWorldSystem = World.GetExistingSystem<BuildPhysicsWorld>();
    17.         stepPhysicsWorldSystem = World.GetExistingSystem<StepPhysicsWorld>();
    18.         commandBufferSystem = World.GetExistingSystem<EndSimulationEntityCommandBufferSystem>();
    19.     }
    20.  
    21.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    22.     {
    23.         var collision = new CollisionJob()
    24.         {
    25.             fragment = GetComponentDataFromEntity<FragmentECS>(),
    26.             component = GetComponentDataFromEntity<BulletECS>(),
    27.         };
    28.         JobHandle jobHandle = collision.Schedule(
    29.            stepPhysicsWorldSystem.Simulation,
    30.            ref buildPhysicsWorldSystem.PhysicsWorld,
    31.            inputDeps);
    32.         commandBufferSystem.AddJobHandleForProducer(jobHandle);
    33.         return jobHandle;
    34.     }
    35.  
    36.     private struct CollisionJob : ICollisionEventsJob
    37.     {
    38.         public ComponentDataFromEntity<BulletECS> component;
    39.         public ComponentDataFromEntity<FragmentECS> fragment;
    40.         public void Execute(CollisionEvent collisionEvent)
    41.         {
    42.             if (component.HasComponent(collisionEvent.EntityB))
    43.             {
    44.                 if (fragment.HasComponent(collisionEvent.EntityA))
    45.                 {
    46.                     var fragmentUpdate = fragment[collisionEvent.EntityA];
    47.                     var bullet = component[collisionEvent.EntityB];
    48.                     fragmentUpdate.Direction = bullet.Direction;
    49.                     fragmentUpdate.Speed = bullet.Speed;
    50.                     fragmentUpdate.IsDelected = true;
    51.                     fragment[collisionEvent.EntityA] = fragmentUpdate;
    52.                     Debug.Log($"Collision between entities { collisionEvent.EntityA.Index } and { collisionEvent.EntityB.Index }");
    53.                 }
    54.             }
    55.         }
    56.     }
    57. }
    How do I do that? If with a regular Rigidbody I could make isKinematic false?
     
  8. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    Okay, since, as usual, no one knows the answers to my questions on this forum, I'll tell you how I did it: After looking through what types of data hybrid rendering uses, I came across PhysicsGravityFactor and PhysicsMass.InverseMass, I forcibly change these parameters in the PhysicsECS class and it works, but not quite correctly as I would like because Kinematic body it has only a direction and is completely frozen, so now I'm going to try to redo it into layers to improve the result

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Mathematics;
    3. using Unity.Physics;
    4. using Unity.Physics.Extensions;
    5.  
    6. public class PhysicsECS : ComponentSystem
    7. {
    8.     protected override void OnUpdate()
    9.     {
    10.         Entities.ForEach
    11.             (
    12.         (ref PhysicsVelocity velocity, ref PhysicsMass physicsMass,ref BulletECS shoot) =>
    13.         {
    14.             if (!shoot.IsSpawned)
    15.             {
    16.                 var forceVector = (float3)shoot.Direction * shoot.Speed;
    17.                 velocity.ApplyLinearImpulse(physicsMass, forceVector);
    18.                 shoot.IsSpawned = true;
    19.             }
    20.         });
    21.  
    22.         Entities.ForEach
    23.            (
    24.        (ref PhysicsVelocity velocity, ref PhysicsMass physicsMass,ref PhysicsGravityFactor f, ref FragmentECS fragment) =>
    25.        {
    26.            if (fragment.IsDelected)
    27.            {
    28.                f.Value = 2.0f;
    29.                physicsMass.InverseMass = 2.0f;
    30.                var forceVector = (float3)fragment.Direction * fragment.Speed;
    31.                velocity.ApplyLinearImpulse(physicsMass, forceVector);
    32.                fragment.IsDelected = false;
    33.            }
    34.        });
    35.     }
    36. }
     
  9. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    Where are these dedicated DOTS users when I need them so badly?
     
  10. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    In general, I achieved the result I needed, I just needed to change the value of Iteria to unfreeze the objects, thanks to Vyacheslav for this post:https://forum.unity.com/threads/from-kinematic-to-dynamic-after-a-collision.859819/
    See my final version:

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Mathematics;
    3. using Unity.Physics;
    4. using Unity.Physics.Extensions;
    5.  
    6. public class PhysicsECS : ComponentSystem
    7. {
    8.     protected override void OnUpdate()
    9.     {
    10.         Entities.ForEach
    11.             (
    12.         (ref PhysicsVelocity velocity, ref PhysicsMass physicsMass,ref BulletECS shoot) =>
    13.         {
    14.             if (!shoot.IsSpawned)
    15.             {
    16.                 var forceVector = (float3)shoot.Direction * shoot.Speed;
    17.                 velocity.ApplyLinearImpulse(physicsMass, forceVector);
    18.                 shoot.IsSpawned = true;
    19.             }
    20.         });
    21.  
    22.         Entities.ForEach
    23.            (
    24.        (ref PhysicsVelocity velocity,ref PhysicsCollider physicsCollider,ref PhysicsGravityFactor f, ref PhysicsMass physicsMass, ref FragmentECS fragment) =>
    25.        {
    26.            if (fragment.IsDelected)
    27.            {
    28.                physicsMass.InverseMass = 3.0f;
    29.                physicsMass.InverseInertia = 4.0f;
    30.                f.Value = 5.0f;
    31.                fragment.IsDelected = false;
    32.            }
    33.        });
    34.     }
    35. }
     
  11. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    The only problem is that it will work the same way as in TearDown, that is, hanging objects may remain in the air