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)?
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.
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)
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 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.
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.