Search Unity

Prefab doesn't access its children colliders giving error: no collider attached

Discussion in 'Scripting' started by inz_przemyslaw_wozniak, Sep 18, 2014.

  1. inz_przemyslaw_wozniak

    inz_przemyslaw_wozniak

    Joined:
    Sep 12, 2014
    Posts:
    16
    I made two game objects, which are the same in shape, differs only in dimensions. I'd like to accurately (that's why I must use two colliders of exact shape, not one just to do the rought estimate - thanks these are simple enough to match what's offered by Unity primitives out of the box) tell, if the smaller one is PERFECTLY INSIDE bigger one. Each game object is made of cube and cylinder, which have their colliders. I thought that Unity will treat this two colliders as an overall collider of a prefab, so I wrote some simple code:

    void OnTriggerStay(Collider other)
    {
    if (other.gameObject.tag == "Pinhole")
    {
    if((other.gameObject.collider.bounds.Contains(this.collider.bounds.max)) && (other.gameObject.collider.bounds.Contains(this.collider.bounds.min)))
    other.gameObject.renderer.material.color = new Color(0, 238, 0);
    }
    }

    Which I attached to the smaller prefab (which can be moved, and I wrote a separate script for that too). When I run this, I got an error shown in the attached picture.

    How can I make a collider of the given shape (cube + cylinder) for my prefab? Or maybe I can access its children via code and check if one cube is inside of another and the same with cylinders = one object is inside another one? I'm open for multiple solutions, the key here is to acquire accurate measure to determine the containing of object.
     

    Attached Files:

  2. Krysalgir

    Krysalgir

    Joined:
    Aug 30, 2010
    Posts:
    95
    You could have your prefab with a certain script (say "RootElement") and each child with a script (say "Childelement").

    RootElement and ChildElement can have both OnTriggerEnter/Stay/Exit, but those function call another function that is only present in RootElement, say Rootelement::DealWithCollisionStay();

    Code (csharp):
    1.  
    2. RootElement : Monobehaviour {
    3.     void Awake() {
    4.         ChildElement[] = gameObject.FindelementsInChildren<ChildElement>();
    5.         foreach(ChildElement in childElement)
    6.             if(childelement != null) childElement.rootElement = this;
    7.     }  
    8.  
    9.     public void DealWithCollisionStay() {
    10.         // Whatever
    11.     }
    12.  
    13.     // In case there's also a collider on the root game object
    14.      void OnTriggerStay(Collider other) {
    15.         if(whatever you want is true)
    16.             DealWithCollisionStay();
    17.     }
    18. }
    19.  
    20. ChildElement : MonoBehaviour {
    21.     public rootElement rootElement = null;
    22.  
    23.     void OnTriggerStay(Collider other) {
    24.         if((whatever you want is true) && rootElement != null)
    25.             rootelement.DealWithCollisionStay();
    26.     }
    27. }
    28.  
    29.  
     
  3. inz_przemyslaw_wozniak

    inz_przemyslaw_wozniak

    Joined:
    Sep 12, 2014
    Posts:
    16
    This code is a little bit confusing to me... I think that you tried to write it more or less universal, but I'd appreciate the concrete solution, as I'm dealing with this kind of problem for the first time.

    I started to working on your Awake() function to rewrite it for my specific case. As I want to access the colliders of a cube and a cylinder, I assumed that my child element is a collider. I also noticed a typo in your code, that is FindelementsInChildren should be GetComponentsInChildren:

    Code (CSharp):
    1. void Awake() {
    2.         Collider[] colliders = gameObject.GetComponentsInChildren<Collider>();
    3.         foreach(Collider collider in colliders)
    4.             if(collider != null) childElement.rootElement = this;
    5.     }
    The last line is where I'm completely confused - childElement.rootElement = this ? It's like accessing parent from a child... Don't know how to deal with that.

    I stopped rewriting at that line. But from what I get, the code which I attached in my first post should go into DealWithCollisionStay() function (of course without the first line of it).

    Could you please help me rewrite the code to match my situation? It would me much easier for me to get it and reuse it later.
     
  4. inz_przemyslaw_wozniak

    inz_przemyslaw_wozniak

    Joined:
    Sep 12, 2014
    Posts:
    16
    I've managed to solve my problem by... simply adding EMPTY MESH COLLIDER to GameObject "pin". Crazy :)

    But I'm still interested in above code. Would be grateful if someone could explain how it should be rewritten ;)
     
  5. Krysalgir

    Krysalgir

    Joined:
    Aug 30, 2010
    Posts:
    95
    The part when I set the rootElement has to be on the custom class (ChildElement), not a Collider component, else
    1. it has no sense as a collider doesn;t have that attribute
    2. it will simply not work

    And childElement.rootElement = this is to set the value of the rootElement in the ChildElement with the current instance of the RootElement of your GameObject, so that they know who they refer to.