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.
  2. Join us on Thursday, June 8, for a Q&A with Unity's Content Pipeline group here on the forum, and on the Unity Discord, and discuss topics around Content Build, Import Workflows, Asset Database, and Addressables!
    Dismiss Notice

Feature Request CollisionFilter as a separate IComponentData

Discussion in 'Physics for ECS' started by scottjdaley, Mar 14, 2023.

  1. scottjdaley


    Aug 1, 2013
    I've been working with ECS for a couple of years now and I've run into several use cases where I want to change what an entity can collide with, either temporarily or permanently. It seems like something that should be relatively simple to do, but is surprisingly difficult.

    For context, here is what change collision filter system might look like:

    Code (CSharp):
    1. public partial struct ChangeCollisionFilterSystem : ISystem
    2. {
    3.     private NativeList<PhysicsCollider> _createdColliders;
    5.     [BurstCompile]
    6.     public void OnCreate(ref SystemState state)
    7.     {
    8.         state.RequireForUpdate<MyEntity>();
    10.         _createdColliders = new NativeList<PhysicsCollider>(Allocator.Persistent);
    11.     }
    13.     [BurstCompile]
    14.     public void OnDestroy(ref SystemState state)
    15.     {
    16.         foreach (PhysicsCollider collider in _createdColliders)
    17.         {
    18.             collider.Value.Dispose();
    19.         }
    20.         _createdColliders.Dispose();
    21.     }
    23.     [BurstCompile]
    24.     public void OnUpdate(ref SystemState state)
    25.     {
    26.         Entity entity = SystemAPI.GetSingletonEntity<MyEntity>();
    27.         var collider = SystemAPI.GetComponent<PhysicsCollider>(entity);
    28.         BlobAssetReference<Collider> colliderCopy = collider.Value.Value.Clone();
    29.         CollisionFilter filter = colliderCopy.Value.GetCollisionFilter();
    30.         filter.BelongsTo = 16;
    31.         colliderCopy.Value.SetCollisionFilter(filter);
    32.         PhysicsCollider newCollider = colliderCopy.AsComponent();
    33.         _createdColliders.Add(newCollider);
    34.         SystemAPI.SetComponent(entity, newCollider);
    35.     }
    36. }
    This code isn't super complex, but it highlights a couple of problem areas that new ECS users can easily run into.
    1. It is not obvious that SetCollisionFilter() is going to modify ALL entities using that particular collider. This makes sense because the baking systems use a blob asset store to deduplicate colliders, but this detail is hidden from the user. If you only want to modify one collider, you have to call Clone first.
    2. Calling Clone creates a new blob that must be disposed of when no longer needed. The comments for this function do call this out, but it is annoying to deal with. This problem is even more complicated when considering saving and loading the game and restoring the correct colliders.

    I understand the rationale for storing colliders as blobs. Colliders are sometimes primitive shapes but can also be large meshes. Storing this data outside of a component makes a lot of sense to save on memory. It isn't super common (at least for me) to have to change a collider shape and often there are better alternatives like swapping an entire prefab.

    However, the CollisionFilter is something I'm wanting to change a lot. For example, if I want the player to pick up an object, I may want to temporarily disable collision on the object, but still be collidable with cursor raycasts. It feels like I should be able to just modify an integer on a component somewhere. But instead I have to clone the entire collider and make sure I correctly handle the lifetime of it.

    Internally, a CollisionFilter only contains three integers. Even if it would increase the size of entities slightly, I feel like moving CollisionFilter to its own IComponentData (not in a blob) would reduce a lot of the complexity here. Abstractly, this also makes more sense to me. When I think of a "collider" I think of the physical shape and bounds of the object. A "collision filter" describes how that collider interacts with the world which is a separate concept from the collider itself.

    If it is too late to change something like this, an alternative suggestion would be to add a PhysicsCollisionFilterOverride component added that functions similarly to the existing PhysicsMassOverride, but for override collision filters instead of changing kinematic/dynamic. This PhysicsCollisionFilterOverride would simply contain a CollisionFilter inside of it, no blob required. This component would be optional, but if present the physics system would use the override collision filter for all physics calculations.

    I realize that there might be some internal complexity with both suggestions (especially considering stuff like compound colliders), but I hope that something like this is considered.

    toomasio, KANIYO, AverageCG and 7 others like this.
  2. Thygrrr


    Sep 23, 2013
    ABSOLUTELY! I've been calling for this as well, it makes no sense (or at least creates some major inconveniences) to not just have this a copyable data, but instead just baked hard into some opaque BlobAsset.

    I assume there may be some limitations with compound colliders.
    Last edited: Mar 15, 2023
    daniel-holz and IsaacsUnity like this.
  3. IsaacsUnity


    Unity Technologies

    Mar 1, 2022
    TL;DR: Work in Progress!

    Hey all, just wanted to share that we're hearing this loud and clear, there are some intricacies about collider and BlobAsset interactions we need to work out so that we can split out CollisionFilters and other related data components. In the most transparent manner, I think we have the right expertise on the team to figure out a solution, so do look forward to it! @daniel-holz @schembri-unity
    toomasio, KANIYO, Thygrrr and 5 others like this.
  4. scottjdaley


    Aug 1, 2013
    Thanks for the response @IsaacsUnity!
    KANIYO likes this.