Referencing Specific Script Instances

Okay, I understand how I can use FindObjectOfType to get the first active instance of a script object in the running scene.

What I can’t figure out is how I talk to or reference a specific instance of a script. Say for instance, the generic “missile” script attached to a “missile” prefab that is being instanced each time my player fires a missile. What is the best practice in Unity for accessing the “missile” script on a specific missile instance?

The best way is to store the instance somewhere when you instantiate it. This way you will not have to search for it when you need it again.

Alternatively tou can use FindObjectsOfType (note plural), which returns all objects of a certain type and then loop through the results:

function GetMissileInstanceByName(i_Name : String) {
   for(var instance : MyMissile in FindObjectsOfType(MyMissile) ) {
      if(i_Name == instance.name) {
         return instance;
      }
   }
   return null; // not found
}

You will probably have to add something to the MyMissile instances so you can tell them from each other. Or use the name property like I did in the example above.

I would like to point out that FndObjectsOfType is pretty slow for large scenes - It’s a much better bet to do a GetComponent (MyMissile) on the missile just when you spawn it.

I think Freyr’s first suggestion and Nick’s second are what I’m after.

In Director, I usually just create a global that points to each instance of a parent script (apologizes for all of the odd Directorese here) that I create.

What is the best-practice for doing this in Unity (using GetComponent)?

TIA

To elaborate: You have a missile prefab, and a launcher that shoots them out.

Let’s assume you want to spawn a missile, then tell it to detonate in 5 seconds.

You gunlauncher script:

var missile : GameObject;

function Fire () {
  var clonedGameObject;
  clonedGameObject = Instantiate (missile);
  var newMissile;
  newMissile = clonedGameObject.GetComponent (Missile);
  newMissile.detonateTimeout = 5;
}

This is a classic use case: we call instantiate to create a copy of something - this returns the new copy. Then we use GetComponent on that to get to the actual missile instance.

But we can do better:

var missile : Missile;

function Fire () {
  var newMissile;
  newMissile = Instantiate (missile);
  newMissile.detonateTimeout = 5;
}

A bit of magic is going on here: Instantiate can take a ptr to any component inside a game object. It will still clone the entire game object, BUT it will return the matching component in the new copy. So if we KNOW we want to clone a missile, we can just make the source variable be of type missile, and the Instantiate call will give us back the missile component of the new copy - hence saving us for all the GetComponent stuff.

Awesome, Nich!

I’m assuming that (in your second example) the line that reads:

var missile : Missile;

… is set in the Properties Panel to point to the missile prefab, right?

Exactly. Same in the first example.

The difference is that in the first example it would reference a GameObject, so when you Instantiate that, you get a GameObject back.

in the Second example, it references a specific component inside a GameObject. When you Instantiate that, you get the instantiated component back (even though the entire GO hierarchy is instantiated)

Thanks again, Nich!

What a clean and efficient way to reference objects and their subcomponents. I love it. And, of course, Unity does all the garbage cleanup when I Destroy the objects too, I assume.

Maybe you’re getting tired of hearing this by now, but you guys have really done a great job with Unity.

I don’t think any of us will get tired of that :slight_smile:

d.

I could post somthing similar on sunday mornings, so you could work through all the time?! Wait wait wait i ll have to leave… :arrow:

No, :wink: its really awesome how fast one get professional and direct response here on unity forum. I found this thread extremely helpful. Thanks!

Cool, that saves a bit of typing. If I keep learning tips like that, I’m pretty sure I can get my games down to 1 line of code. :wink:

–Eric

Now THERE’S a good community challenge… make the coolest game you can with ONE line of code :smile: Meaning, one semicolon.

The script could be attached to multiple objects, but ONE script and ONE line of code. Possible?

function Update() { IntenselyUglyCodeWithGobsOfParentheses; }

I think you could maybe make an interesting interactive “toy” but not a true game.

It sure would be interesting to be proven wrong though.

System.Diagnostics.Process.Start("open","file:///Applications/Chess.app");

What do I win?

Infamy.

Ping pong. See the attached web player.

function Update () { transform.Translate(0, 0, Input.GetAxis("Horizontal") * Time.deltaTime * 20); }

I am pretty sure you could also do a rolling marble game with 1 line of code. Actually there are probably a lot of games you can do with 1 line of code.

20035–648–$pong_122.zip (9.88 KB)

Technically though, these are just “toys”, aren’t they?

A game needs to have defined “win” and “lose” states. Put differently, a game has to have at least one goal and must be able to tell you when you’ve reached it.

Otherwise, you’ve just created an entertaining activity, or digital toy.

Ok… how about attaching this to a cube:

function OnMouseDown() { print("You win!"); }

This makes a “will you be able to click on the cube or will you eventually get bored” game, doesn’t it? 8)

sure save the ‘player’ the hassle of all that pressing the mouse, sore fingers and all that. heres your classic can you load the game game:

function Start() { print("You win!"); }

And that brings us to the concept of “good” games versus “bad” games.

:wink: