Search Unity

GetComponent(Script)

Discussion in 'Scripting' started by Locus, Jun 17, 2009.

  1. Locus

    Locus

    Joined:
    Jun 17, 2009
    Posts:
    15
    I have been trying to GetComponent of another GameObject inorder to call a method, I've tried everything I could think of but no sucess. I have 2 primitive spheres and I just want to call a method in Sphere2 from Sphere1. This is what I have now:

    var someObject : GameObject;

    function Update () {
    someO= someObject.Find("Player");
    print("someObject name: " + someO.name);
    someO.GetComponent(MoveSphere).DoSomething();
    }

    Sphere2 I tagged with the name: Player it doesn't print someO.name and it gives me a NullReferenceException for the last line. Can't you call another objects method?
     
  2. HiggyB

    HiggyB

    Unity Product Evangelist

    Joined:
    Dec 8, 2006
    Posts:
    6,183
    First off, welcome to the forums! :D

    Before answering, a quick tip: get comfy with using the [ code ]...[ /code ] blocks in your posts (remove those spaces) as it lets you format code a bit more nicely. I'll edit your post when I'm done so you can look at that as an example.


    Of course you can call methods on other objects :) A few points/questions:

    1. What exactly is someObject and have you assigned a value to that variable (via the Inspector) before testing this script?

    2. When calling Find() you can just use GameObject.Find(...), no need to use a current game object reference.

    3. If you're not seeing the name appear for someO.name then comment out the other code and sort things out. Perhaps you can error check the Find() return value against null to make sure it's finding something of that name.

    Here's my modified version of your code for testing:

    Code (csharp):
    1. function Update () {
    2.   someO = GameObject.Find("Player");
    3.   if (someO == null) {
    4.     print("No object found with that name!");
    5.   } else {
    6.     print("someObject name: " + someO.name);
    7.     someO.GetComponent(MoveSphere).DoSomething();
    8.   }
    9. }
    So step one is to verify that Find() is returning you something other than null. Make sure the name is identical, like look for leading/trailing space characters as you might use "Player" in the code above, but that will fail if the real object's name is " Player" (notice the space).
     
  3. Locus

    Locus

    Joined:
    Jun 17, 2009
    Posts:
    15
    I just figured it out before I looked back at the forum. I changed someObject.Find("Player") to Find("Sphere2") but in my frustration with earlier code I had actually taken out of the MoveSphere script and had put it in its own script, but putting it back of course worked.

    Sorry beginer's unluck. Thanks for your reply though.
     
  4. HiggyB

    HiggyB

    Unity Product Evangelist

    Joined:
    Dec 8, 2006
    Posts:
    6,183
    I'm just glad you sorted it out, no matter how you go there. :)
     
  5. MattFS

    MattFS

    Joined:
    Jul 14, 2009
    Posts:
    219
    hey, rather than start a new topic... this fits in with me :)

    Have similar problem

    Code (csharp):
    1.  
    2. GameObject go = GameObject.Find("GameManager");        
    3. print(go.name);                                    
    4. go.GetComponent(GameManagerScript).AdjustScore(true);
    Now, I'm assuming it finds it, because it prints the name ok.. but then next line (GetComponent) returns compile error CS0119

    If I put it in quotes, so:
    Code (csharp):
    1. go.GetComponent("GameManagerScript").AdjustScore(true);
    Then compile error 'UnityEngine.Component' does not contain a definition for 'AdjustScore'

    The name of the script is GameManagerScript.cs, when dragged onto a GameObject its component is called Game Manager Script (Script) (and for futility's sake I tried every combo!) ...and it contains a public function called AdjustScore(bool myBool)

    What have I missed! :)
     
  6. Broheim

    Broheim

    Joined:
    Jun 25, 2009
    Posts:
    3
    Hey i just had the same problem.
    I'm new to c sharp, but I think what you are looking for is:

    Code (csharp):
    1.  
    2. go = GameObject.Find("GameManager");
    3. goScript = (GameManagerScript)go.GetComponent(typeof(GameManagerScript));
    4. goScript.doSomething();
    5.  
    why do I always have to cast the scripts?
     
    RonaldPavon and krakendono like this.
  7. MattFS

    MattFS

    Joined:
    Jul 14, 2009
    Posts:
    219
    beauty, that did it ;)
     
  8. HiggyB

    HiggyB

    Unity Product Evangelist

    Joined:
    Dec 8, 2006
    Posts:
    6,183
    Just to provide some background: the reason the above works is that you have to specify the type when using GetComponent(). Without doing that the generic data type returned is Component and that's the base class without your custom functions. If instead you type the return value to your script then it can find your public functions/variables and not produce script errors.
     
  9. dgish

    dgish

    Joined:
    May 2, 2009
    Posts:
    10
    This works great if you're calling another C# script, but I can't find the right incantation for calling Javascript from C#. Says the type is undefined. For example, Rotator is an object with Rotator.js attached, and Unity says it is undefined:


    Code (csharp):
    1. GetComponent(typeof(Rotator))).rotateRate.z = 3;
     
  10. MatthewW

    MatthewW

    Joined:
    Nov 30, 2006
    Posts:
    1,356
  11. dgish

    dgish

    Joined:
    May 2, 2009
    Posts:
    10
    God bless you, sir! That was driving me insane!
     
  12. grojguy

    grojguy

    Joined:
    Jul 13, 2009
    Posts:
    35
    HiggyB, thanks very much for these kinds of posts, as it's really helpful to know the "why" .

    However, in this case your explanation is not crystal clear to me. Are you saying that the above typecasting is the proper way, or not? You say
    Do you mean without specifying the type? As far as I can tell, GetComponent requires a Type, and always returns a Component. So doing this in C# requires typecasting the result, yes?

    A more concise version of the above which worked for me (if you don't need to retain the Object reference)....

    Code (csharp):
    1. public GameManagerScript goScript;
    2.  
    3. void Start() {
    4. goScript = (GameManagerScript)GameObject.Find("GameManager").GetComponent(typeof(GameManagerScript));
    5. }
    6.  
    7. void Update() {
    8. goScript.doSomething();
    9. }
     
    unity_sCWsC7SSo1hy3Q likes this.
  13. HiggyB

    HiggyB

    Unity Product Evangelist

    Joined:
    Dec 8, 2006
    Posts:
    6,183
    Proper depends on your desired goal. If all you want is a reference to it as a generic Component then you do not need to specifically type cast I'd guess. With that in mind that's almost never really the case and therefore the "proper" way is to type cast as you almost always want access to the script, its specific variables and of course methods.


    If you want access to your script component's members (properties, methods) as opposed to only the base class component's members then yes (which is like 99.99% of the time).
     
  14. Lucas Meijer_old

    Lucas Meijer_old

    Joined:
    Apr 5, 2008
    Posts:
    436
    I implemented generic versions for the next version of Unity, for the c# users in need of some lovin'.

    Animation a = GetComponent<Animation>();

    note the lack of casting, compiler verified typesafety, and reduced amount of typing. Same for AddComponent<Animation>(), FindObjectsOfType<Whatever>(), and friends.

    If you can't wait, what I used to do myself is create a MyMonoBehaviour class that implements all these helper functions.

    Bye, Lucas
     
    LordDooms likes this.
  15. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Thats superb news :)
    Great addition
     
  16. krakendono

    krakendono

    Joined:
    Jun 5, 2016
    Posts:
    15
    thanks bro this helped
     
  17. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,092
    Please don't necro really old threads... this thread is from 2009, 11 years ago
     
  18. krakendono

    krakendono

    Joined:
    Jun 5, 2016
    Posts:
    15
    I just said thank you... -_-
     
  19. JPoenisch

    JPoenisch

    Joined:
    Mar 2, 2018
    Posts:
    4
    Don't use that anymore!

    As Lucas Meijer_old also posted 11 years ago there are generic version and you can/should just do

    Code (CSharp):
    1. goScript = go.GetComponent<GameManagerScript>();
    2. goScript.doSomething();
    or simply directly use
    Code (CSharp):
    1. goScript = FindObjectOfType<GameManagerScript>();
     
    Laz16 likes this.