Calling a function in one script from a function in another

Sorry for posting what I’m sure has already been answered because it’s so basic, but I couldn’t find anything in the documentation or through searching the forums. (side question: anyone know how to get the forum search function to match an exact phrase instead of just individual words? Quotes don’t seem to make any difference)

Anyway, I’m trying to call a function in one script from a function in another script. (they could be combined, but I’m trying to get the basic proceedure figured out) Both scripts are attached to empty objects and placed in the scene.

Script A:
function Update(){
if(Input.GetButton(“Fire1”))
{
PrintThis();
}
}

Script B:
public function PrintThis(){
print(“print test message”);
}

So of course when I run the game I get the “Unknown identifier: ‘PrintThis’” error. Any hints or links to previous posts on this would be greatly appreciated. Thanks.

Check the documentation on the “Send Message” and “Broadcast Message” commands, they’ll do what you need.

Much more accurate though is to have a variable of the gameObject to which the script is attached, then use yourObjectHere.GetComponent(“NameOfTestScript”).TestThisScript();

I’m in the LERPZ 3D tutorial and having a similar problem. I’ve set a really high value for the jump height, and I’d like to dynamically alter the camera distance so LERPZ stays in the screen. I’ve tried;

Debug.Log(NearCamera.GetComponent(“SpringFollowCamera”).distance);

But it returns “unknown identifier NearCamera”

I can use
var cam: Camera = Camera.current;
cam.fieldOfView = 95;
yield new WaitForSeconds (6);
cam.fieldOfView =60;

To pan out and then back. But I’d like to figure out how I can access the distance variable.

Thanks for any help!

I’ve also tried to put

var newcam: Camera;

at the top of my script. When I do this, the inspector offers a drop down with the cameras in the scene (NearCamera and FarCamera) but when I try to select either, the combo box jumps back to ‘none.’

Unfortunately I too am getting an “Unknown identifier: ‘xxxxx’” error.

I have Script A on gameObject A, and I’m looking for a value from a variable in Script B on gameObject B.

So far from what I’ve read of GetComponent() in the docs, it talks of accessing scripts from within another script, of which both scripts are on the same object.

Do you not access scripts from other objects with GetComponent()?

original code add static to it so static function then you can access in other scripts

It’s very simple to accomplish, essentially you need to establish a link with that object. Here’s how you set it up.

// Variable to cache our target game object

private var ForeignObject: GameObject;

// Variable to cache the target script.  Yes it's a type of ForeignScript
// because in Javascript, each script is actually a -class- definition.

private var ForeignScript: ForeignScript;

function Start() {

// Cache the Foreign Object
ForeignObject = GameObject.Find("ForeignObject");	

// Cache the Foreign Script

ForeignScript = ForeignObject.GetComponent("ForeignScript");

}

Now at this point you now have a link to the game object and the script you’re wanting to call a function in. So you can…

// Access it's public variables

ForeignScript.playerLives -= 1;

// Call a function contained in the script

// With SendMessage (propagates to ALL components on the object be aware)
ForeignObject .SendMessage ("ForeignFunction");

// Or directly!

ForeignScript.ForeignFunction(parameter);

*** Note, I would -not- suggest making things static as someone previously suggested. You’ll run into BIG problems this way if you’re not careful. Your static variables will be initialized when the game is started, even before the scene containing the script is loaded! Destroy and recreate that game object and the values will be -persistant- causing you much debugging grief.

I’ve only found it useful to do that on a general ‘settings’ singleton object loaded in scene 0.

I got it to swallow my code after I last posted here, as upon submitting, I remembered that the Lerpz 3D Tut had a place where LevelStatus was being called from the ThirdPersonStatus script…so that fixed that!

Funny enough now, I’m getting a NullReferenceException which I’m starting to believe has to do with the fact that the MouseLook was written in C#(from what I’ve read elsewhere). I won’t hijack this thread with that problem, but now I’m wrapped up in trying to get the JS version of the MouseLook on the wiki to work on the iPhone, seeing if that fixes the Null error…sigh.

Hey, sorry for the late reply.

Thanks for all the help. Looks like I have several methods to try. I’m surprised that what seemed like such a simple thing involves so much, but thanks to all your explanations it’s finally starting to make sense.

here is the easiest of all the methods.

if you want to access a function like this

function RGBSlider (screenRect : Rect, rgb : Color) : Color {
	rgb.r = GUI.HorizontalSlider (screenRect, rgb.r, 0.0, 1.0);
	screenRect.y += 20; // <- Move the next control down a bit to avoid overlapping
	rgb.g = GUI.HorizontalSlider (screenRect, rgb.g, 0.0, 1.0);
	screenRect.y += 20; // <- Move the next control down a bit to avoid overlapping
	rgb.b = GUI.HorizontalSlider (screenRect, rgb.b, 0.0, 1.0);
	return rgb;
}

tak that for an example then to make it so you can access it in another script do this (add static to the front of the function)

static function RGBSlider (screenRect : Rect, rgb : Color) : Color {
	rgb.r = GUI.HorizontalSlider (screenRect, rgb.r, 0.0, 1.0);
	screenRect.y += 20; // <- Move the next control down a bit to avoid overlapping
	rgb.g = GUI.HorizontalSlider (screenRect, rgb.g, 0.0, 1.0);
	screenRect.y += 20; // <- Move the next control down a bit to avoid overlapping
	rgb.b = GUI.HorizontalSlider (screenRect, rgb.b, 0.0, 1.0);
	return rgb;
}

so to call it in another script do this (this is an easy way to access variables in your script to from another script (I only use this method because I think it is the easiest))

function OnGUI {
    script(script = name of the script where your variable/function is).RGBSlider( Rect (10,10,10,10), Color.white)
}

Interesting. That method seems rather simple. Any thoughts on Quietus’s concerns that making a function static can cause other problems?

Only use static for something that you want to be accessible project-wide. i.e., if you have a generic function that you want to be available to all scripts, make it a static function. Also, static functions have to be self-contained and they can’t reference any outside variables. So to say “I only use this method because I think it is the easiest” is completely wrong…static functions have a particular purpose and limitations, and can’t and shouldn’t be used whenever you feel like it because it’s “easier”.

Similarly, SendMessage and BroadcastMessage have particular uses. Those are more abstract, and when I first started using Unity I didn’t really understand them for a while. Some useful things about them is that you don’t need to know the name of the objects you’re sending messages to, and you can have it so that the objects don’t necessarily need to have a function by that name, so the message is just ignored (that’s the DontRequireReceiver option…personally I wish it was the default, since I use that far more often than the default RequireReceiver).

An example might be a series of boss enemies. Let’s say these are big enemies with a number of turrets. You’d have the base object for the enemy, which has a common script used for all of them. As children, let’s say the first boss has four turret objects, with a script on them with a “Fire” function which fires lasers. Then the main script would do “BroadcastMessage(“Fire”);” every so often. Say the turrets can be disabled by the player…the main script on the boss doesn’t change at all; you can still just do BroadcastMessage and any surviving turrets will fire. Now say the next boss has eight turrets…again, the main script doesn’t change at all. And then say the third boss has turrets that fire missiles instead of lasers, and maybe they have a reload time or something, so the script name is different and the Fire function is different too. Well, the main boss script is still completely unchanged; you’re still doing “BroadcastMessage(“Fire”);” and everything is still just working.

The disadvantage with Send- and BroadcastMessage is they have more overhead, so again they should be used when appropriate, not “just because”. In the right circumstances, they can be extremely useful though.

Probably the most common method of accessing other scripts is by using GetComponent. As Quietus described, it’s quite simple: get a reference to the object in some way (a public var with drag’n’drop, GameObject.Find(), or whatever). Then do GetComponent(ScriptName). The only thing I would add is, do (ScriptName) rather than (“ScriptName”) when possible, because it’s faster.

–Eric

Having a problem with this too.

Object A

function Start () {
	var cube = GameObject.Find("Cube");
	cube.GetComponent(MainGame).DoSomething();
}

Object B: it’s a cube with the MainGame script attached to it

function DoSomething() {
	Debug.Log("doing stuff");
}

But I keep getting "“DoSomething” is not a member of UnityEngine.Component’

If I get rid of the GetComponent part in Object A and switch with cube.transform.Translate(0, 1, 0); then that works fine so I know it’s finding the GameObject okay. But I don’t know why it won’t recognize DoSomething

You’re using Unity iPhone or else you have #pragma strict on, so you can’t use dynamic typing. As the error says, “DoSomething” isn’t a member of Component; it’s a member of MainGame. Therefore you have to specify the type instead of letting unity figure it out on the fly:

(cube.GetComponent(MainGame) as MainGame).DoSomething();

–Eric

Thanks! That worked perfect.