Hello,
I’m trying to set collider data on a single entity but I get the error “InvalidOperationException: Adding/removing components or changing position/rotation/velocity/collider ECS data on dynamic entities during physics step”.
I looked through the example at https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/UnityPhysicsSamples/Assets/Demos/5.%20Modify/Scripts/ChangeColliderTypeAuthoring.cs, but I only need to update component data for one entity at a time, so I’d rather not create an entire new systembase class for that. Is there any way to schedule a specific function to run when a physics step is not? Below is my code:
entityManager.SetComponentData(meshEntity, new PhysicsCollider {
Value = output[0]
});
Where output[0] is a physicscollider blobassetreference.
The problem is that the BuildPhysicsWorld and ExportPhysicsWorld use the same Entity Query to get the physics related entities. If you change data yourself between these systems then the order of entities could be different and the export writes the data into incorrect components, or you make changes to the ECS data and the export overwrites you changes.
Instead of setting the ComponentData directly, you could create an EntityCommandBuffer from the EndFixedStepSimulationEntityCommandBufferSystem and have the data set after the fixed step has complete.
@steveeHavok
Okay so I’ve gone ahead and tried to set the physics collider in a system, but I’m still getting lots of the same errors.
using PCollider = Unity.Entities.BlobAssetReference<Unity.Physics.Collider>;
public struct PhysicsColliderHolder : IComponentData { public PCollider held; }
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[UpdateBefore(typeof(BuildPhysicsWorld))]
public class ApplyMeshColliderJobSystem : SystemBase {
protected override void OnUpdate() {
using (var commandBuffer = new EndFixedStepSimulationEntityCommandBufferSystem().CreateCommandBuffer()) {
Entities
.WithName("terrain_chunk")
.ForEach((Entity entity, ref PhysicsColliderHolder holder) => {
PhysicsCollider collider = new PhysicsCollider() {
Value = holder.held
};
commandBuffer.SetComponent(entity, collider);
commandBuffer.RemoveComponent(entity, typeof(PhysicsColliderHolder));
}).Run();
commandBuffer.Playback(EntityManager);
}
}
}
I’m also getting an Object Reference Not Set to Instance of Object error at var world = World.Unmanaged; in EntityCommandBufferSystem.CreateCommandBuffer();
I can’t find any examples of someone trying to set a collider at runtime, except for the example above which seems to just swap two existing collider. I tried directly modifying that code and it did not work so I’m a little lost here. If anyone has examples I can look at for how to do this properly that would be really helpful.
I also can’t seem to add a BlobAssetReference<Unity.Physics.Collider> to an entity even if it’s not in a PhysicsCollider struct. As you can see, I tried to add a new component public struct PhysicsColliderHolder : IComponentData { public PCollider held; } to get the generated collider into the system, but when I add this component to an entity I get the same physics step error. So on top of all this, I have no idea how to actually get the collider I want to add to an entity into the system, it’s quite the conundrum haha.
Alternatively, when I try to do the same thing outside of a system, I get all the same errors:
EntityCommandBuffer commandBuffer = new EndFixedStepSimulationEntityCommandBufferSystem().CreateCommandBuffer();
PhysicsCollider collider = new PhysicsCollider { Value = output[0] };
commandBuffer.SetComponent(meshEntity, collider);
commandBuffer.Playback(entityManager);
This is ideally what I’d like my code to be as it is much simpler for this solution than a System, but I still get the null object reference on World.Unmanaged and my console is still spammed with Physics Step errors.
PhysicsCollider collider = new PhysicsCollider { Value = output[0] };
EntityCommandBufferSystem ecbSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
EntityCommandBuffer buffer = ecbSystem.CreateCommandBuffer();
buffer.SetComponent(meshEntity, collider);
A few notes as an aside, many of the docs on EntityBufferSystems seem to be outdated. I messed around with EntityCommandBufferSystem.PostUpdateCommands a lot which only seemed to lead to EntityCommandBuffer not initialized errors, but I’m curious if anyone knows how to currently use this as it’s seemingly different than it is in the documentation.