I assume what I want to do should be easy, but I’m not quite sure how to go about it. What I want to do is instantiate a prefab in a certain pattern, and assign a different value to a property of that object each time it is instantiated. From what I’m seeing in my Javascript books, it seems to me that I might need to define a function or a class, creating “dummy” properties to start off with, and then fill in useful values as my prefab is instantiated. However, I’m not sure how to make the instantiated prefab itself inherit these values.
Think about it like this, perhaps: I will instantiate a prefab five times, and want each of these to be “numbered” somehow, so that I can only do something to them if they “are” the right number.
Also, I tried using a for/in statement for an Array, and it didn’t work properly. However, changing this to be a standard “for” loop allowed correct behavior. Still, I get an error, even though things look alright on screen. Here are the important bits. Any ideas?
This does not work (all instantiated prefabs are created in the same place):
var dot : GameObject;
var Elements : Vector3[];
function Start () {
for (var element in Elements){
placement = (Elements[element]);
Instantiate(dot, placement, Quaternion.identity);
}
}
This works. The error I get is “IndexOutOfRangeException: Array index is out of range.”:
var dot : GameObject;
var Elements : Vector3[];
function Start () {
for (n=0; n<=Elements.length; n++){
placement = (Elements[n]);
Instantiate(dot, placement, Quaternion.identity);
}
}
extending what I said: have a static int and increment it every Start.
Then have a normal int that is assigned to the current value of the static variable.
This is something I was thinking about, but I don’t know how to “attach” that “normal” integer to each instance of the prefab. I’ve tried creating a variable to hold such a value, but it hasn’t worked so far. I did something like:
There are several different ways, actually. One way is just to give each object a different name:
function Start() {
for (i = 0; i < 5; i++) {
var myObject = Instantiate(something);
myObject.name = i.ToString();
}
}
I’ve done this fairly often…if you just need one unique variable per object, and you don’t need the name for anything else, it seems like the simplest method. Probably not the fastest, though, since you’re dealing with strings.
var dot : GameObject;
var Elements : Vector3[];
function Start () {
for (var element in Elements){
placement = (Elements[element]);
Instantiate(dot, placement, Quaternion.identity);
}
}
The problem with this is that “element” is not a integer; it’s a Vector3 since “Elements” is an array of Vector3s. With a foreach loop, you don’t have an index counter. Every iteration through the loop, the next item in the array “Elements” is assigned to “element”.
Use this instead:
for (var element in Elements){
Instantiate(dot, element, Quaternion.identity);
}
And this:
var dot : GameObject;
var Elements : Vector3[];
function Start () {
for (n=0; n<=Elements.length; n++){
placement = (Elements[n]);
Instantiate(dot, placement, Quaternion.identity);
}
}
The problem with this is that “n” is exceeding the number of items in the array, hence the error you’re getting. Since numbering starts at 0, you want to change it to “n < Elements.length”.
Excellent, Eric. Thanks a bunch. I’m having some success now.
However, I’m having some difficulty actually using the named instances of the prefab in conditional statements. How would I change the following so that it becomes useful? Is there some sort of “un-String-ify” function, like the ToString() Eric brought to my attention?
There’s also parseFloat. Careful with that one…if you have a string like “378.482”, it might interpret the result differently depending on the user’s regional settings.
Do you have any suggestions for where I can go for a list of this stuff? I LOVE the Script Classes Index, but I have yet to find a similarly nice non-Unity-specific Javascript reference.
I need to “practice” a bit before I can utilize the massive power of that, but thank you now for the fun I will have later!
As for now, this new problem is REALLY bugging me. I have instanced my prefabs, and named them procedurally. To start off with, only ONE item should be blue. This code work fine inside of Unity, but upon building, the second to last prefab that is instanced becomes blue for no good reason! This is highly simplified code to what I really want to do, but I think it’s the most concise I can make it in order to display the problem.
Create a prefab object, any shape. Put this script on it.
var thing = 1;
function Update() {
if (parseInt(name) == thing) {
renderer.material.color = Color.blue;
}
if (parseInt(name) > thing) {
renderer.material.color = Color.green;
}
}
Then, create an empty, or whatever, and attach this script on that in order to get these prefabs placed in the scene:
var thingy : GameObject;
var thingies : Vector3[];
private var placement : Vector3;
function Start () {
for (count=0; count<thingies.length; count++) {
placement = thingies[count];
var thingo = Instantiate(thingy, placement, Quaternion.identity);
thingo.name = (count+1).ToString();
}
}
If this works out for you like it does for me, you will have 1 Blue object in Unity, and 2 when you build the game. I don’t want that second one!
Hmmm…unfortunately I can’t see why that would fail. Well, you can try another method of assigning a variable to the objects; I’d suggest the method Marble outlined. If you don’t want to deal with classes right now, you can set up a variable in the objects’ scripts and assign it from the other script:
for (count=0; count<thingies.length; count++) {
placement = thingies[count];
var thingo = Instantiate(thingy, placement, Quaternion.identity);
var thingoScript : thingoScriptName = thingo.GetComponent(thingoScriptName);
thingoScript.thingVar = count+1;
}
And then the objects’ script, which I’m referring to here as thingoScriptName (obviously you’d use the actual name of the script there), would have:
var thing = 1;
var thingVar : int;
function Update() {
if (thingVar == thing) {
//etc.
This way thingVar gets assigned a unique value when the object is instantiated. Note that thingVar can’t be a private variable if you want to access it from other scripts like that.
Thanks again, Eric. This method is new enough to me that I am getting something out of it, but it’s not so crazy that it’s going over my head, given my current experience.
However, I get the same buggy, unusable results. I am going to try creating a new project and using these scripts in it. If it worked for you, it might work for me. I’ve had weird things happen with Unity that became fixed upon building, but this is the first time it’s been the other way around. Not good.
I have been working on this project for a while now without that weirdness reappearing. I am now at a point where I have the two scripts working together flawlessly, but I want to trigger new scripts only at certain points.
I believe that “function Start() {}” will come in handy, but I don’t know how to make a script be “asleep” until I want it to do whatever is in “function Start() {}”. I tried wrapping up some code into a function, like so, hoping to be able to Invoke said function, but that didn’t work.
function doWheniSaySo() {
function Start() {//do stuff}
function Update() {//do even better stuff}
}
Edit: I was just thinking, maybe I should use “Instantiate” to place an object, with the script I want to call attached to it, into a scene. It seems a bit weird to make a prefab that will only be instanced one time, but that’s all I’ve got right now. :idea: