Universal external collider Best Practice

**Main problem:**

I have a complex object with structure:

__MiniBossObject __> BasicUnitPrefab > VisualPrefab > > SomeColliders

When I do raycasts I can’t get MainObject. I want MiniBossObject to act like Facade for all its complex child objects structure.

MiniBossObject have no colliders or rigitbody, only components/interfaces for facade representation of main functional.

BasicUnitPrefab have rigitbody and have different component that handle all complex logic (no colliders either).

VisualPrefab handle all animations and visual, his child objects have colliders. Some Random Scripts do a raycast to find a MainObject, but I always get visual prefab object or something else.

All I found is:

1. Use Rigitbody2D

I can remove rigitbody from BasicUnitPrefab and create it in MiniBossObject. By far, it looks like the easiest solution. But I really don’t want rigit body to be on MainObject. And what if some objects have no rigitbody…

usage: health = RaycastCollider.attachedRigidbody.GetComponent< IHealth>()

2. Use custom interface IExternalCollider

I can create an interface that always refers to MainObject. This interface will have only one field GameObject MainComponent, and all objects with colliders should have this interface. It looks better than rigitbody

usage: health = RaycastCollider .GetComponent< IExternalCollider>() .GetComponent< IHealth>()

3. Use foreach loop

When someone does a raycast, they always should check all parent objects of the collider. I can wrap this in come helper method. But it looks kind of messy and random…

usage: health = HelperStaticClass.CheckAllParentsFor< IHealth>(RaycastCollider)

4. Dinamicly remove colliders from visualObjects and draw it on MainObject

I really don’t know is it a good or clean solution something tell me that this solution smells bed in long run (but I haven’t try this one yet)

usage: health = RaycastCollider .GetComponent< IHealth>() // that what I want, but I am not shure about redraw colliders logic

**Final thoughts**

External collider looks like a common thing to have. How it’s done on other projects? When you have a client, that will work with your prefab, you don’t really want you logic to be: “ATTENTION! Use this logic, or else it won’t work!!!”. If I could override gameObject field of collider it will solve the problem


I think rigitBody or custom interface looks like the cleanest solution, but maybe i’m missing something… It still requires client to do additional logic with ALL raycast in the game for my gameObject to work Properly. Please help me with your thought or experience. I simplified my example so it looks like I can just put all BasicUnitPrefab logic in MiniBossObject. But in real project, all BasicUnitPrefabs are different and have different components. I have a constructor for mini-bosses in the editor, where you use different components to create custom BasicUnitPrefabs for mini-boss behaviour and then just save it in prefab. When you spawn mini-boss with prefab, spawner wraps this messy object in clean facade MiniBossObject

In real project mini-boss prefab structure looks like this:







So in this logic, I can create different type of BasicUnitPrefab like UnitForAirCombat or UnitForGroundCombat, that can have no common interfaces. But because I will have __MiniBossObject __ that will work like facade, Client will work with my part of a game without need to know how every BasicUnitPrefab works (and I can have many types of prefabs with different behaviur without rising complexity of a progect)

But colliders in unity can only give you gameObject that contain these colliders or nearest rigitbody in heirarchy. As I undertand you cannot override gameObject property of collider :frowning: And this ruin my plan of facade pattern

My current Solution is to use ExternalCollider2D component in main object. It basically finds all Collider2D components and add ExternalCollider2D to them with new rootGameObject (which is equal to MainGameObject). So when I client do raycast, he needs this construction:

health = raycastCollider.TryGetComponent<ExternalCollider2D >(out externalCollider) 
?  externalCollider.GetComponent< IHealth>() 
: raycastCollider.GetComponent< IHealth>()

This is simplify version of component (without helpers and other stuff)…

public class ExternalCollider2D : MonoBehaviour  {
        public GameObject ExternalRootGameObject {
              get => _externalRootGameObject ? _externalRootGameObject : gameObject;
              private set => {
                  _externalRootGameObject= value;
                  foreach (var externalCollider in ExternalColliders) {
                      externalCollider.ExternalRootGameObject = value;

        public List<ExternalCollider2D> ExternalColliders { get; private set; } = new List<ExternalCollider2D>();

        private GameObject _externalRootGameObject;

        public ExternalCollider2D AddExternalCollider(GameObject externalCollider)  {
              var visualColliders = externalCollider.GetComponentsInChildren<Collider2D>();
              return this;
        public ExternalCollider2D AddExternalCollider(Collider2D component)   {
              if (component.TryGetComponent<ExternalCollider2D>(out var externalCollider)) {
                    externalCollider.ExternalRootGameObject = ExternalRootGameObject;
            else  {
                    externalCollider = component.gameObject.AddComponent<ExternalCollider2D>();
                    externalCollider.ExternalRootGameObject = ExternalRootGameObject;
            return this;