Wednesday, September 18, 2013

Unity3D: How to Call Code from a Different GameObject

Something that gets asked all the time is how to call code in a script attached to a GameObject from a different GameObject in Unity3D. In Javascript or C#, the answer is pretty simple, but not necessarily intuitive at first glance. This post will provide a nice template that you can use to do exactly that.

First, you'll need at least two GameObjects in your scene, with a different script attached to each: one with some code you'll want to execute, and one that will execute the code in the other script.

So let's say I have a GameObject called "controllerObject" with a script called "controllerScript", which will do the calling, and a GameObject called "workerObject" that has a script called "workerScript", which has the code I want to execute. The hierarchy would look something like this:


In "workerScript", let's put some code in that just prints to the console.

C#

public void DoStuff ()
{
     print ("Remote method successfully called.");
}

Notice we've made this method public so that other code can see it. If you've got a private method, your controller can find the script, but it won't be able to call the method due to its protection level.

In "controllerScript", we're going to place the heart of this code. We're going to find the GameObject containing our worker script, then we're going to find the script and communicate with it.

C#

private void CallRemoteMethod ()
{
    private GameObject workerObject;
    private workerScript workerObjectScript;
   
    void Start ()
    {
        workerObject = GameObject.Find ("workerObject");
        workerObjectScript = (workerScript)workerObject.GetComponent (typeof (workerScript));
      
        CallRemoteMethod ();
    }
   
    private void CallRemoteMethod ()
    {
        workerObjectScript.DoStuff ();
    }    

}

This is a little more involved, so I'll break down what we're doing.

First, we're creating a couple of variables to contain the objects that we need to interact with: "workerObject" is the object that contains our worker script, and "workerObjectScript" is the worker script itself. In Start (), which will be executed one time when the scene starts, we first find the worker object by name, and then assign the script we're looking for to the "workerObjectScript" variable. Finally, we call "CallRemoteMethod ()", which executes the "DoStuff ()" method in the worker script.

Make sure that the scripts are attached to the appropriate GameObjects and press "Play". You'll see your console output, verifying that the method has been called.



You can use this template to call methods or check variables on any script on any object in the scene, provided that those methods and variables have the proper protection level. This technique can also be modified to work in many different ways. For instance, instead of finding the GameObject "workerObject" using the GameObject.Find () method, we could have created a public GameObject and simply dragged the worker object on to that field in the Inspector. However, the beauty in doing it entirely in code is that even if the calling is instantiated at run time, it can find the proper object and call code from it.

Unity 3D error: "Compute mesh inertia tensor failed"

This is error is almost always caused when you have a Mesh Collider on a plane. To get rid of it, remove the Mesh Collider and use a thin Box Collider instead.

Please note that in Unity 4.x, it is not sufficient to disable the Mesh Collider; you must remove it entirely.