- Home /
Can not add PhysicsCollider at runtime Unity in ECS
I'm trying to use UnityPhysics ECS system on gameObject, my goal is sync gameObject's position with entity translation and to add PhysicsCollider to gameObject to interact with other entities. My steps. 1. Create plane gameobject.
Add CopyTransformFromGameObjectProxy.
Add PhysicsCollider to created entity from gameobject.
Change entity's collider by get collider from cached entity.
Thanks from helping.
[UpdateBefore(typeof(BuildPhysicsWorld))]
public class AddingPhysicsSystem : SystemBase
{
EntityQueryDesc _queryEntityCacheDsc;
EntityQueryDesc _queryEntityHybricDsc;
EntityCommandBuffer _entityCommandBuffer;
EntityManager _entityManager;
protected override void OnCreate()
{
base.OnCreate();
_queryEntityCacheDsc = new EntityQueryDesc()
{
All = new ComponentType[] { typeof(EntityCacheTag) }
};
_queryEntityHybricDsc = new EntityQueryDesc()
{
All = new ComponentType[] { typeof(Transform) },
None = new ComponentType[] { typeof(HybridEntityTag) }
};
_entityCommandBuffer = World.DefaultGameObjectInjectionWorld.GetExistingSystem<EndSimulationEntityCommandBufferSystem>().CreateCommandBuffer();
_entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
}
protected override unsafe void OnUpdate()
{
// get cached entity
EntityQuery _entityQuery = GetEntityQuery(_queryEntityCacheDsc);
var cachedEntity = _entityQuery.ToEntityArray(Allocator.Temp)[0];
// get collider preset
var collider = _entityManager.GetComponentData<PhysicsCollider>(cachedEntity);
// get gameObject entity with CopyTransfromFromGameObjectProxy component
_entityQuery = GetEntityQuery(_queryEntityHybricDsc);
var hybridEntities = _entityQuery.ToEntityArray(Allocator.Temp);
// add PhysicsCollider at runtime to gameObject entity
for (int i = 0; i < hybridEntities.Length; i++)
{
_entityCommandBuffer.AddComponent(hybridEntities[i], new PhysicsCollider());// not working
_entityCommandBuffer.AddComponent(hybridEntities[i], new Translation());
_entityCommandBuffer.AddComponent(hybridEntities[i], new Rotation());
_entityCommandBuffer.AddComponent(hybridEntities[i], new LocalToWorld());
_entityCommandBuffer.AddComponent(hybridEntities[i], new HybridEntityTag());
_entityCommandBuffer.SetComponent(hybridEntities[i],collider); // not working
Debug.Log(_entityManager.GetComponentData<PhysicsCollider>(hybridEntities[i]).ColliderPtr->Type.ToString()); // get error message ArgumentException: A component with type:PhysicsCollider has not been added to the entity.
}
}
}
$$anonymous$$ove EntityQuery _entityQuery = GetEntityQuery()
call to OnCreate
(this needs to be done once, not every frame). $$anonymous$$ake for (int i = 0; i < hybridEntities.Length; i++)
loop a Job
because iterating over NativeArrays and Dots data outside jobs is very slow.
Answer by NT_Ninetails · Dec 01, 2020 at 02:30 PM
to make a collider you can use the methods in the Unity.Physics namespace. find the Collider you want to create and add the corresponding Geometry.
BlobAssetReference<Unity.Physics.Collider> box = Unity.Physics.BoxCollider.Create(new BoxGeometry {
Center = float3.zero,
BevelRadius = 0.05f,
Orientation = quaternion.identity,
Size = new float3(1,1,1)
});
After that you can create a new Unity.Physics.PhysicsCollider setting the Value to our previously created collider.
PhysicsCollider physicsCollider = new PhysicsCollider { Value = box};
if (box.IsCreated)
{
commandBuffer.SetComponentData(entity, physicsCollider);
}
//or
PhysicsCollider physicsCollider = new PhysicsCollider { Value = box};
if (box.IsCreated)
{
entityManager.SetComponentData(entity, physicsCollider);
}