Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

GameObject.SetActive doesn't work in game build

Discussion in 'Scripting' started by Purple-Night-Owl, Jan 12, 2017.

  1. Purple-Night-Owl

    Purple-Night-Owl

    Joined:
    Oct 30, 2015
    Posts:
    83
    I'm not 100% sure why this isn't working but I've searched online for this issue. I've found a few possible solutions but I wanted to ask here first.
    I've made an avatar creator in Unity3D and it all works brilliantly in the Editor, except for this annoying error: GetComponent requires that the requested component 'GameObject' derives from MonoBehaviour or Component or is an interface. I found out where this is going wrong. My clothing objects appear with an assigned button click that's triggered using SetActive. Also, I used GetComponentInChildren<GameObject> to locate the object in question because it's a child of an object (specifically my avatar's body; the clothing objects are separated meshes).
    I think I must have done this GetComponent wrong because in my build none of the objects will show up when I click the buttons, but they worked fine in the editor. Is there something I've forgotten?
    Here's an example of a script that has a GetComponent method. Several scripts are similar to this depending on the object needed to show.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4.  
    5. public class Hairstyle1Button : MonoBehaviour {
    6.    
    7.     public GameObject hairstyle1;
    8.    
    9.     // Use this for initialization
    10.     void Start () {
    11.         hairstyle1 = GetComponentInChildren<GameObject> ();
    12.         hairstyle1.SetActive (false);
    13.        
    14.     }
    15.    
    16.     public void ShowObject(){
    17.  
    18.         hairstyle1.SetActive (!hairstyle1.activeInHierarchy);
    19.     }
    20.    
    21.     // Update is called once per frame
    22.     void Update () {
    23.        
    24.     }
    25. }
    Any help would be greatly appreciated. Thank you.
     
  2. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    GameObject is not a component, so you can't do GetComponent<GameObject>().

    You'll need to either find a specific component of the GameObject, find the GameObject by name, drag the reference directly to the variable in the inspector, or get a child by index. There's tons of ways to reference other objects.

    For a simple change you can probably do "transform.GetChild(0).gameObject"
     
  3. AndyGainey

    AndyGainey

    Joined:
    Dec 2, 2015
    Posts:
    216
    That looks awkward to me because a GameObject is technically not a Component, and so I would expect GetComponent<GameObject>() to fail. The documentation implies this, but it's not super clear about it. And the error message you provided suggests otherwise, but the message itself might be inaccurate.

    If you simply want the first child, I'd recommend using transform.GetChild(0).gameObject.
     
  4. Purple-Night-Owl

    Purple-Night-Owl

    Joined:
    Oct 30, 2015
    Posts:
    83
    Okay, thanks for all your suggestions so far. So I guess that you recommend changing line 11 to transform.GetChild(0).gameObject? I'll look into it.
    I found the original code from another forum. I used it because it seemed to work and I didn't know what the error meant, so thanks for letting me know that it wasn't a good statement to use. I'll see if I can change it (successfully).
     
  5. Deleted User

    Deleted User

    Guest

    I promote understanding, not just solutions. I want you to enjoy your time with Unity and it'll be more fun if you take the time to understand it. I really recommend not trying to make a game and just learning about the engine at first.

    A GameObject has no hierarchy, it is only a reference to a group of components. The Transform component is what knows who the children are. The error is suggestive of this, but may be difficult to understand if you haven't studied types a bit yet.

    (put this on a gameobject with some child empty gameobjects)
    Code (CSharp):
    1. public class QuickTest : MonoBehaviour {
    2.  
    3.     GameObject foo;
    4.     void Start ()
    5.     {
    6.         foo = GetComponentInChildren<Transform>().gameObject;
    7.         if (foo = this.gameObject) { Debug.Log("It's this one, doh"); }
    8.     }
    9. }
    10.  

    This works because all Components have a reference to their parent GameObject. You can see that if you ctrl-f gameObject on the Transform's page... https://docs.unity3d.com/ScriptReference/Transform.html

    However, if we look at the API... https://docs.unity3d.com/ScriptReference/Component.GetComponentInChildren.html unfortunately it includes the parent. This is the sort of thing they would probably change except it would break a bunch of stuff and confuse established users hindsight is 20/20. At least I hope so!

    There are a bunch of ways around this. We could go someTransform = this.transform.Find("name of child"), and then search using that transform. In fact, in general it might make more sense to have a Transform reference saved in your script to use for searching for stuff!

    Code (CSharp):
    1. public class QuickTest : MonoBehaviour {
    2.  
    3.     GameObject foo;
    4.     void Start ()
    5.     {
    6.         foo = GetComponentInChildren<Transform>().gameObject;
    7.         if (foo = this.gameObject) { Debug.Log("It's this one, doh"); }
    8.     }
    9.  
    10.     GameObject bar;
    11.     private void Awake()
    12.     {
    13.         bar = this.transform.GetChild(0).gameObject;
    14.         if (bar != this.gameObject) { Debug.Log("It's somebody else!"); }
    15.     }
    16.  
    17. }
    18.  
    Let's try to understand. Bar is a GameObject, so just like every equation, the other side needs to also be a GameObject. We start from this, which gives you a GameObject (bar = this; is OK)

    but then we look at its Transform, because we'd like to use Transform.GetChild(), which gives us the first child.

    But GetChild gives a Transform, and we want a GameObject, so we use that Transform's reference to a GameObject, .gameObject.

    Don't worry too much about it now, but notice if you click "class in UnityEngine / Inherits from:[link]" under the API page titles it takes you up to Object. The way Object-Oriented Programming works is essentially you have a basic thing and then you make more specific things, each of which includes the stuff their parent does. Inheritance is closely related to polymorphism, which is the idea that a parent can have some method and then children can override it and do different things. Those are the two important concepts you should think about as a new lone programmer, since the other "pillar" of OOP, encapsulation, is mostly concerned with keeping stuff from breaking because someone/something does unintended stuff to it.
     
  6. Purple-Night-Owl

    Purple-Night-Owl

    Joined:
    Oct 30, 2015
    Posts:
    83
    Thanks, JayMounes. I'm quite new to C# programming and I haven't learnt everything yet. I'm getting better but I'm not there yet. Child objects isn't something I've covered yet so this has been really useful. I've been studying C# for the last year or two and I have a better understanding of it than I did before but this is an area I haven't touched on yet. I'm really pleased how quickly I got responses. I'll take all your suggestions on board and work on my code, and do some more studying. I'm about halfway through this really good book that covers C# in Unity and it's been a big help. Thanks again, I really appreciate it.
     
  7. Fenikkel

    Fenikkel

    Joined:
    Sep 24, 2019
    Posts:
    20