Search Unity

Modifying PhysicsShape's CollisionFilter at runtime

Discussion in 'Physics for ECS' started by Cerzi, May 1, 2020.

  1. Cerzi

    Cerzi

    Joined:
    Dec 28, 2014
    Posts:
    12
    I'm trying to simple change the CollisionFilter (in particular, the BelongsTo) of an entity with PhysicsShape at runtime. However I noticed that PhysicsShape doesn't appear to be a component in and of itself, but rather just an authoring script that does a lot of things. As such I can't make out how the source code of PhysicsShapeAuthoring is actually applying component data to an entity, and thus can't figure out how I would do this at runtime.

    The only component I can see that might be relevant is PhysicsCustomTags, but this just has a single value rather than the 2+ values I'd expect for collision data
     
  2. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    This post talks about tweaking the Material in the PhysicsCollider component but it applies to the CollisionFilter as well.
     
  3. Cerzi

    Cerzi

    Joined:
    Dec 28, 2014
    Posts:
    12
    The trouble with this method seems to be that it changes the collider for every entity that used it, as the collider itself is referenced by all instances of the entity prefab.

    In my particular use case I have two teams which both share the same prefabs, and I'd like to be able to convert the prefab and then set the collisionfilter based on the team post-instantiation.

    As far as I can tell I need to create a copy of the collider in the blob asset store with the different collision filter, and then select that, but it's somewhat unclear exactly how to do this.
     
  4. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    If I'm not mistaken, in the PhysicsShape component, you can enable "Force Unique" and that'll make your colliders independent from each other. That way you can modify them individually when spawning them

    I guess an optimisation in your case would be to not ForceUnique, but instead manually create one unique collider per team with the right material assigned. But I'm not currently sure how to create a Collider copy
     
    Last edited: May 10, 2020
  5. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    This isn't tested but you can clone the collider something like this :

    Code (CSharp):
    1.     public static BlobAssetReference<Collider> CloneCollider(BlobAssetReference<Collider> collider)
    2.     {
    3.         unsafe
    4.         {
    5.             var clonePtr = (Collider*)UnsafeUtility.Malloc(collider.Value.MemorySize, 16, Allocator.Temp);
    6.             UnsafeUtility.MemCpy(clonePtr, collider.GetUnsafePtr(), collider.Value.MemorySize);
    7.  
    8.             var clone = BlobAssetReference<Collider>.Create(clonePtr, collider.Value.MemorySize);
    9.             UnsafeUtility.Free(clonePtr, Allocator.Temp);
    10.  
    11.             return clone;
    12.         }
    13.     }
     
    Augin likes this.
  6. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
  7. teasully

    teasully

    Joined:
    Nov 26, 2016
    Posts:
    17
    This seems to do the trick:
    Code (CSharp):
    1. static void SetCollisionFilter(Entity entity, uint belongsTo, uint collidesWith)
    2. {
    3.   var collider = EntityManager.GetComponentData<PhysicsCollider>(entity);
    4.   Assert.IsTrue(collider.Value.Value.CollisionType == CollisionType.Convex);
    5.  
    6.   unsafe
    7.   {
    8.     var header = (ConvexCollider*)collider.ColliderPtr;
    9.     var filter = header->Filter;
    10.  
    11.     filter.BelongsTo = belongsTo;
    12.     filter.CollidesWith = collidesWith;
    13.  
    14.     header->Filter = filter;
    15.   }
    16. }