Is it possible to create compound collider with each child collider attached to corresponding entity

In physics demo, the compound collider is added to single entity, and the render mesh is combined adding to the same entity too for rendering.
But for my situation, I need to create compound collider with each child collider attached to corresponding entity.
Is there any API to do this?

Short answer is probably no! All child colliders are moving together within the compound collider so there is only really one entity with transform needed. Can I ask what your usecase/situation is?

1 Like

Thx for replying! Maybe you’re right. My usecase is a building game, spaceship. each block could be separatedly built onto, and also destroied.

In situation of one block connecting two other blocks is destroied. The two remaining blocks should be turned into individual rigidbodies. This could be easily done in gameObject mode. just adding a rigidbody component. However in ECS mode it need to rebuild the compound collider manually.

Moreover, the block that being destroied should be disable rendering. I also need to maintain a mapping manually and find which entity this collider is mapping to then destroy that rendering entity.

Honestly, ECS is really not coding friendly. It is more suitable for Prefab, but not enough support for procedural generating gameplay.

Also I’ve tried to using fixjoint instead of compound collider,
but you know, the fixed joint is not really fixed. it would causing annoying spring effect.
Another idea is keep every block kinematic, but the whole ship won’t response to collision properly.
So I don’t know what to do. Maybe better to give up on ECS. just gameobject.

same problem but different detail, i use compound to implement character “lift a rock and hold” thing, but many query methods (CollisionType.Composite/CollisionType.Terrain) still remain not implemented. i stuck here and can’t find a workaround (fixed joint not apply this situation either)

Hi stevee, is there and progress or any solution to this, after a year…?

you would need to rebuild the compound collider and also build a new box collider for the individual dynamic bodies that got separated. This is fairly fast in ECS from what i tested
You can also have a duplicated set of individual entities that become activated and ready to fall and then just rebuild the compound collider only.

Actually, I looked at this issue last week. I added a RenderEntity variable to the ChildCollider struct and updated the conversation pipeline to add the Entity handle. At least that way you have a reference to the graphics representation when you call something like GetLeaf using a ColliderKey from a Ray or Collider cast.
It has yet to be passed review but should make it into a release early in the new year. If I get a chance I’ll post a patch you can apply locally for Unity Physics (though you’ll need to wait for the release to get the Havok Physics version as it involves data structure changes).

3 Likes

That’s great. I will wait for the release.

1 Like

I’m also making a building game and ran into this exact issue, looking forward to the update

This makes me very happy, as it has been bothering me for a long time !

That said, @steveeHavok what was the reason for calling it "Render"Entity? In my case, the corresponding entities are not always rendered.
I understand that calling it Entity and renaming Entity → RootEntity is an issue for in the short term incurring upgrading pains, but I think that RenderEntity could lead to misunderstandings by first-time users in the future.

1 Like

Hi there, i’m also working on a spaceship building game where i ran into similar issues. What i did to solve it:
Each “ship grid block” is treated as its own entity, but the collider is used to build a compound collider for the spaceship. To figure out which block is being targeted (to interact with it or remove it from the ship), i store the collider leaf index of each “grid block entity”. When casting a ray that hits the compound collider, i extract the sub key of the collider hit, and then search the block on the ship for this key. When the compund collider is reconstructed, i store the collider index key (the index of a single collider that represents the entity in the compound collider) in each entity that belongs to the ship.

Here’s two partial code snippets on how i did this, maybe this can help someone. Note that the code is a whole mess and i’m just using it for POC purposes, but it still manages to run smoothly when operating on grids with 1000+ blocks:
Code example

//generated a new compound collider for a grid, stores the collider keys to each block
private void rebuildGridCollider(Entity gridEntity) {
        var blobList = new NativeList<CompoundCollider.ColliderBlobInstance>(1, Allocator.Persistent);

        uint i = 0;
        float weight = 0;
        Entities.ForEach((int entityInQueryIndex, ref PlacedGridBlockTag gridTag) => {
            if (gridTag.gridParent != gridEntity) return;
            gridTag.colliderIndexKey = i++;
            weight += gridTag.mass;
            blobList.Add(new CompoundCollider.ColliderBlobInstance() {
                Collider = gridTag.colliderRef,
                CompoundFromChild = new RigidTransform(gridTag.localRotation, gridTag.localPosition)
            });
        }).WithBurst().Run();

        //grid destroyed
        if (i == 0)
        {
            EntityManager.DestroyEntity(gridEntity);
            blobList.Dispose();
            return;
        }

        Debug.Log("colliders: " + blobList.Length);

        BlobAssetReference<Collider> toConstruct = BlobAssetReference<Collider>.Null;

        Job.WithBurst().WithCode(() => { toConstruct = CompoundCollider.Create(blobList); }).Run();

        EntityManager.SetComponentData(gridEntity, new PhysicsCollider {Value = toConstruct});
        var centerOfMass = toConstruct.Value.MassProperties;
        EntityManager.SetComponentData(gridEntity, PhysicsMass.CreateDynamic(centerOfMass, weight));

        blobList.Dispose();
    }

//finds the hit block key from the ship's compound collider, indeyKey is the key that is stored in the above method:
private Entity RaycastToGridBlock(float3 RayFrom, float3 RayTo, int layer, out float3 hitPos, out float3 hitNormal,
        out uint indexKey) {
        var physicsWorldSystem = World.DefaultGameObjectInjectionWorld
            .GetExistingSystem<Unity.Physics.Systems.BuildPhysicsWorld>();
        var collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld;
        indexKey = 0;

        RaycastInput input = new RaycastInput() {
            Start = RayFrom,
            End = RayTo,
            Filter = LayerToFilter(layer)
        };

        bool haveHit = collisionWorld.CastRay(input, out var hit);
        if (haveHit)
        {
            hitPos = hit.Position;
            hitNormal = hit.SurfaceNormal;
            Entity e = physicsWorldSystem.PhysicsWorld.Bodies[hit.RigidBodyIndex].Entity;

            var hitCollider = collisionWorld.Bodies[hit.RigidBodyIndex].Collider;

            unsafe
            {
                var isCompound = (CompoundCollider*) hitCollider.GetUnsafePtr();
                hit.ColliderKey.PopSubKey(isCompound->NumColliderKeyBits, out indexKey);
                //Debug.Log(indexKey);
            }

            return e;
        }

        hitPos = float3.zero;
        hitNormal = float3.zero;
        return Entity.Null;
    }
3 Likes

Generally the use-case problems were related to the graphics representation feeding into the physics representation but having no path back to graphics from a physics query. I’m happy to rename this before it is shipped if you have a better term, though ‘RootEntity’ sounds more confusing to me. ‘ShapeEntity’ was an initial term I considered. Would ‘ShapeEntity’ be prefered?

1 Like

I think you’re right about the naming of RootEntity (I was also considering ParentEntity, but went for root, as parent is used in the code, and the top parent is usually the root). But I suspect we are not talking about the same thing.

I am assuming you mean this, just to make sure I understand:
Simple collider:

  • Entity method → entity
  • ShapeEntity → entity
    CompoundCollider collider:
  • Entity → root entity.
  • ShapeEntity → child entity

I convoluted two separate issues in my above post and may not have been clear – separating 1:1 child collider-entity and child-collider → “root” entity readers, and naming of “root” entity. (In simple colliders, “root” entity would == entity)

In regard to the first issue, I think it best (long term) for the API, when the Entity reader refers to the 1:1 corresponding entity of the original collider, in a simple collider or in a compound collider. At least that least violates my personal expectations.
As to the naming, perhaps CompoundEntity is better – this signals that we are wanting to accessing the special case, as opposed to the normal Entity case.

Just to be extra clear what I mean:
Simple collider:

  • Entity method → entity
  • ?Entity → entity
    CompoundCollider collider:
  • Entity → child entity.
  • ?Entity → root entity

I hope what I mean is clearer now…?

P.S: I know the above hinges very much on what people generally expect when they type eg. hit.Entity – I suspect for people who use compound colliders, it’s what entity actually was hit.

1 Like

In the Bullet Physics API, there’s something called User Pointer for use case like this, maybe we can call it UserEntity?

The expectation from a physics query should be to get the Entity associated with the Body. Generally you want to manipulate that Body by applying impulses etc. If you also get a ColliderKey then a child collider within that body is specifically involved, but a lot of the time you won’t care. That said, we need to make it easy to get the extra details if you care and need them for your own logic.

In re-evaluating things based on this conversion, I can just have a ChildCollider.Entity member. It does not need to be ChildCollider.ShapeEntity or ChildCollider.RenderEntity!

Only read this if you don't care about the Shape/Render naming reasons, which largely stem from Edit Time concerns. So the only problem I'm addressing here is that child entities are wrapped into a CompoundCollider with no runtime association back to the original child Entity (i.e. the one at Edit Time that had a Physics Shape Authoring component on it). Hence the 'ShapeEntity' idea. I also had 'RenderEntity' as the Mesh Renderer is the component used to test whether a Mesh on a child node is included in calculating the Convex Hull of a Physics Shape on a parent node. This is a similar issue. where one single Physics Collider is associated with multiple Meshes at edit time, though at runtime the original hierarchy of entities that went into the Convex Hull can still easily be retrieved. So, due to the importance of the Mesh Renderer in the Convex Hull case I used the name 'RenderEntity' in the CompoundCollider Child case.

Excuse my rubbishness with youtube but this might help rather than typing more:
https://www.youtube.com/watch?v=XCmWkafqtQw

4 Likes

Thanks @steveeHavok for this answer, and the video!

Regarding expectations, I was coming at it from my more special case. I almost exclusively use Physics for raycast queries, where I usually want the collider’s original entity (material properties of what was hit, does a projectile penetrate and so on and so forth and also virtual colliders to simulate holes or for selection, usually without graphical representations).

From the video, it looks like my case(s) should be covered, and in an elegant way if I got that correctly (Entity for the child collider will be available if an authoring component is added). So I am looking forward to the next release! :slight_smile:

P.S: No youtube rubbishness detected.

1 Like

Just to be clear, Entity for the Child Collider will be available regardless. So your spaceship armor use-case will work out of the box. The extra authoring component in the video is only needed where an associated graphical representation was in a different branch of the hierarchy.

2 Likes

Thanks for the clarification, @steveeHavok

@steveeHavok hi, I cant find any “render entity” in “Child Collider” in unity.physics 6.0, is it cancelled or will be added in any version in furture?