Search Unity

Adding Component to Certain Child Objects

Discussion in 'Scripting' started by Hypester, Jul 11, 2019.

  1. Hypester

    Hypester

    Joined:
    Jan 23, 2018
    Posts:
    17
    So, I'm working with a few assets, and my programming skills are weak, but I think this might be a general question.

    In short, the hierarchy for my character, with all its child objects, including one called RightHand and one called LeftHand is generated at runtime. My IK solution needs to add particular a component to the RightHand and LeftHand.

    Code (CSharp):
    1.     public void AddHandPosers()
    2.     {
    3.       children = GetComponentsInChildren(Transform);
    4.        foreach(Transform hands in children.transform){
    5.        if (object.name == "RightHand" || object.name =="LeftHand" ){ hands.AddComponent<HandPoser>();}}
    6.     }
    There's so much I'm learning, but I'm having trouble getting exactly how references work. Some example code could be very helpful. Thank you for your time.
     
  2. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    Hmmm. That code you posted shouldn't even compile, but it Looks as if you are on the right track. With small changes you can get it to run. The key is that you Access the variable that is containing the reference, here aChild. That reference, however, is a transform, and you want to add to the gameObject that this transform belongs to (note that Unity will allow this, but for purely educational reasons we'll go the correct way).

    Code (CSharp):
    1.  
    2. public void AddHandPosers()
    3. {
    4.     // a dirty Little secret in unity is that you can iterate Transform.
    5.     // this is the easiest way to iterate over all children of a Transform (not object, make
    6.     // sure you understand the difference)
    7.     foreach(Transform aChild in this.transform){
    8.     // make it a Habit to use parantheses to group expressions, otherwise they'll bite you
    9.     if ((aChild.gameObject.name == "RightHand") || (aChild.gameObject.name =="LeftHand") )
    10.        {
    11.           aChild.gameObject.AddComponent<HandPoser>();
    12.        }}
    13. }
    14.  
    15.  
    EDIT: As noted later by bgoldbeck:: this will only iterate the direct children, not the children's children!
    Cheers,
     
    Last edited: Jul 11, 2019
  3. bgoldbeck

    bgoldbeck

    Joined:
    May 15, 2019
    Posts:
    7
    Also, should note that this will loop through only the first level of children.
     
  4. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    Indeed! I now realize that the OP wanted to walk down the entire tree of objects. Welcome to recursion :) - it's not really difficult, but "to understand recursion, you need to understand recursion".
     
  5. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    So here's a recursive version that's scan for both hands. If it finds a Hand, it will no longer scan that object's children, so you must not make one Hand the child of another (which usually makes little sense anyway.)

    Code (CSharp):
    1. public void addHandPoseRecursively(Transform parent) {
    2.    // recursion: iterate all my children if I have them, using myself
    3.    foreach (Transform child in parent){
    4.       if ((child.gameObject.name == "RightHand") || (child.gameObject.name == "LeftHand")) {
    5.           child.gameObject.AddComponen<HandPoser>();
    6.           // shortcut: we assume that we do not have to continue searching this object's children.
    7.       } else {
    8.          addHandPoseRecursively(child);
    9.       }
    10.    }
    11. }
    12.  
    13. public void addHandPose(){
    14.     addHandPoseRecurssively(this.transform);
    15. }
    16.  
    Warning: code was written off the top of my head, may not compile, may cause the end of the world as you know it.
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    GetComponentsInChildren, which OP is using, is already recursive.

    @Hypetester, the only bugs you have are some syntax errors:

    Code (csharp):
    1.  
    2. // your version
    3. public void AddHandPosers()
    4. {
    5.     children = GetComponentsInChildren(Transform);
    6.     foreach(Transform hands in children.transform) {
    7.         if (object.name == "RightHand" || object.name =="LeftHand" )
    8.         {
    9.             hands.AddComponent<HandPoser>();
    10.          }
    11.      }
    12. }
    13.  
    14. // syntax fixed, variable names cleaned up:
    15. public void AddHandPosers()
    16. {
    17.     Transform[] children = GetComponentsInChildren<Transform>();
    18.     foreach(Transform child in children)
    19.     {
    20.        if (child.name == "RightHand" || child.name =="LeftHand" ) {
    21.            child.AddComponent<HandPoser>();
    22.         }
    23.     }
    24. }
     
  7. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    If your character is generated procedurally, then why don't you save appopriate referencec during the generation process to class variables? Or better, add those components to them when creating or even better, create them from prefabs already containing those components?