Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

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:
    122
    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:
    8,888
    MrKsi likes this.
  3. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    122
    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:
    122
    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:
    122
    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:
    122
    At the output I get this result:
     

    Attached Files:

  7. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    122
    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:
    122
    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:
    122
    Where are these dedicated DOTS users when I need them so badly?
     
  10. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    122
    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:
    122
    The only problem is that it will work the same way as in TearDown, that is, hanging objects may remain in the air