- Home /
Sequential GameObject Activation
This seems like the simplest thing but I can't figure it out for the life of me.
I have 400 unique GameObjects that I would like to Activate at different times during an animation. Each GameObject needs to be at very exact location and rotation so I believe .SetActive would be better than trying to Instantiate each one individually. It would also be nice to avoid writing a 400 item Hashtable or Dictionary.
I am simply trying to create a script that will:
Disable Current GameObject
Find next GameObject
Enable next GameObject
Here is my current attempt at naming each GameObject a number 1-400 and converting a variable back-and-forth between a String and an Int:
private var currentObject : int = 1;
function NextFrame () {
currentObject.ToString();
GameObject.Find("currentObject").SetActive (false);
int.Parse(currentObject) += 1;
GameObject.Find("currentObject").SetActive (true);
}
Using GameObject.Find each frame is a bad idea. Why don't you want to use a hashtable/dico ?
I agree with supercouge. If you don't want a dictionary, atleast store the Game Objects in a Generic List and access them that way.
In case you're wondering why your original script wasn't working, it is because the ToString-method only returns a representation of the object as a string, it doesn't change the type; currentObject remains an int even after calling its ToString(). Also, the parsing is unnecessary, since it is already an int.
Furthermore, you are trying to find GameObjects named "currentObject". the correct way would have been to call currentObject.ToString(); ins$$anonymous$$d.
An additional complication arises from the fact that each instance of the script (on the different GameObjects) keeps track of its own variables. Thus, adding one to currentObject in each script results in a currentObject that has a value of 2 in each instance of the script. This can be remedied by either accessing currentObject in the following script, or using a static variable.
supercouge - I wasn't planning to use GameObject.Find each frame, I plan to call the 'NextFrame' function every few seconds via the animation window. I don't have a problem with Hastables or Dictionaries if they can be populated automatically and referred to sequentially (each time I call the 'NextFrame' function the next GameObject is referenced). I am honestly not too familiar with them.
$$anonymous$$ Debnar - You gave me a great answer on how I would accomplish this using my idea and an array but you are a lot more experienced than me. Do you have a better approach that you might suggest?
Answer by DavidDebnar · Jul 10, 2013 at 01:57 PM
Here's a modified version of your method. First, the gameobjects tagged 'Animate' are stored in a list and then sorted by name. Then each tick, it does basically the same as your script, but uses the array to look the gameobjects up instead of the .Find method.
import System.Linq;
private var gameObjectList : GameObject[];
private var currentObject : int = -1;
function Start () {
gameObjectList = GameObject.FindGameObjectsWithTag("Animate").OrderBy(function(g){g.SetActive(false);return g.name;}).ToArray();
}
function NextFrame () {
gameObjectList[(currentObject++%gameObjectList.Length+gameObjectList.Length)%gameObjectList.Length].SetActive(false);
gameObjectList[currentObject].SetActive(true);
}
--David--
Thanks for the response! Your answer is very helpful.
I am unfamiliar with System.Linq apparently it is a part of the .net framework, according to my research. Everything else I understand except: OrderBy(function(g) g.name).
I set up all my GameObjects with the Animate tag and everything seems to be function except the script doesn't proceed to activate the second game object after disabling the first. So the first time function 'NextFrame' is called GameObject "0" is disabled but GameObject "1" is never set active.
I appreciate your help.
I've editted the code a bit, but also make sure, that all your gameobjects are active.
And as for Linq, it's used to do stuff like sorting with arrays/lists/dictionaries/etc.
All your help has been great, it works perfectly! I can't thank you enough for taking the time to help me out with this. I am going to include a special thanks to you in the credits of my project and a link to your answer.
Thanks!
Answer by TonyLi · Jul 10, 2013 at 01:49 PM
Try this:
var objectHolder : GameObject;
private var objects : Transform[];
private var current : int;
function Start() {
objects = objectHolder.GetComponentsInChildren(Transform) as Transform[];
for (var t : Transform in objects) {
t.gameObject.SetActive(false);
}
current = 0;
objects[current].gameObject.SetActive(true);
}
function NextFrame() {
objects[current].gameObject.SetActive(false);
current = (current + 1) % objects.Length;
objects[current].gameObject.SetActive(true);
}
Notes:
Put your 400 objects under a single game object in the hierarchy, and assign this object to the objectHolder property of the script.
The Start() function makes an array of all of the objects under the objectHolder, and activates only the first one.
The NextFrame() function just cycles through the array.
You should check bounds and check for null, but I omitted that for clarity.
Untested code, but it should get the idea across. [Edit: Still untested, but should probably work now. :-)]
Thanks for the fast response, I really appreciate it. I was unaware that an array could be filled automatically.
The script you suggested seems pretty straightforward but for some reason the screen turns grey at start and remains that way. All objects inside my 'objectHolder' are disabled properly on start but the first object (0 in the array) is never set active (same with the following objects). I'm not sure what is causing the script to freeze. When I disable the script in the inspector, the grey screen no longer appears and the rest of the game functions as intended.
I'm sure the answer is obvious, I apologize for my oversight.
Hence my note #5 (untested code) :-). I edited my answer. I wasn't thinking before. FindObjectsOfType grabbed all the objects in the whole scene, which turned off everything.
The edited version above uses GetComponentsInChildren() to get every Transform component in the objectHolder hierarchy (and just the objectHolder hierarchy, not the whole scene). Be aware that it also grabs objectHolder's transform, but I don't if that's a big deal for you or not.
Thank you again for taking the time to help me. Your approach to the problem really helped me understand what I was doing wrong in my attempts.
I wish I had enough rep to up-vote your answer! I will give thanks in the credits of my project and I hope it will raise awareness of your mad coding skillz :)
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
Why can't I save an array? 1 Answer
How do you display a saved name on the screen? 2 Answers
How to split string into two integers? 3 Answers