Get all used scene-gameobjects of an prefab?

Hi,

ive got a scene in which im using a cube as a prefab and then attached "Cube.cs"-script. Now ive added several cubes to my scene.

Although ive got an "MainController.cs" where i have an (Input.GetKeyDown(KeyCode.Space))-Event. If im pressing that key, i would like to know how i can set all my cubes-objects to there specific startposition/rotation. Heres my "Cube.cs":

private Vector3 startPosition;  
private Quaternion startRotation;

void Awake(){
startPosition = transform.position;
startRotation = transform.rotation;
}
public void SetToStartTransform()
    {
        transform.position = startPosition;
        transform.rotation = startRotation;
        collider.isTrigger = false;
        rigidbody.useGravity = false;
        rigidbody.isKinematic = true;
    }

How can i set all my cubes to there start-transformation? Is there a function to catch all my objects from that prefab? Thanks for your help..

UPDATE: I get it done with the following code:

GetComponentsInChildren(typeof(GUI_Cubes));

But it would be great to hear if there exists other possibilites.. Whats with "SendMessage"? I couldnt get it done with that. Does that work?

(Even though your question title mentions "all instances of a prefab", the body of your question seems to indicate you're actually interested in getting all instances of a certain type of script - which is often a similar result, but in a more useful form, because you get the scripts you're interested in rather than the gameobjects to which the scripts are attached. So I'm proceeding on that assumption!)

Yes as you mentioned, if all your cubes are parented to a certain object, you can use

Cube[] allCubes = (Cube[])GetComponentsInChildren(typeof(Cube));

Alternatively, since you're working in c#, you can use the less verbose generic version:

Cube[] allCubes = GetComponentsInChildren<Cube>();

Other ways to collect together groups of objects which share a certain script are:

// this finds all references to Cube component instances,
// regardless of their position in the hierarchy
Cube[] allCubes = (Cube[])FindObjectsOfType(typeof(Cube));

Or yet another way would be to have the cube class be responsible for tracking instances of itself, and make a static function which passes the call out to every instance. I quite like using this method because it removes the need for any other object to concern itself with collecting together all instances of cubes, and it neatly packages up the "instance behaviour" and "instance manager" concepts into a single script:

private Vector3 startPosition;  
private Quaternion startRotation;

void Awake(){
    startPosition = transform.position;
    startRotation = transform.rotation;
    Register();
}

void OnEnable() {
    UnRegister();
}

void OnDisable() {
    UnRegister();
}

public void Reset()
{
    transform.position = startPosition;
    transform.rotation = startRotation;
    collider.isTrigger = false;
    rigidbody.useGravity = false;
    rigidbody.isKinematic = true;
}

// -- static cube manager functions (still part of same script)

private static List<Cube> cubes;

private static void Register(Cube cube) {
    if (!instances.Contains(cube)) {
        instances.Add(cube);
    }
}

private static void UnRegister(Cube cube) {
    if (instances.Contains(cube)) {
        instances.Remove(cube);
    }
}

private static void ResetAll() {
    foreach (Cube cube in cubes) {
        cube.Reset();
    }
}

Once you have this in place, you can reset all cubes from any other script, simply by calling the static function on the Cube class itself, like this:

Cube.ResetAll();

For a number of reasons, I generally avoid using SendMessage where possible.

  • It hides errors until runtime (eg, a function name typo).
  • It relies on runtime reflection to find the actual function (slower)
  • It prevents the more advanced script editors (like visual studio) from linking the specified function name to the actual function.

SendMessage is a way to broadly call a function on a script somewhere without having to get a reference to the script itself.

gameObject.SendMessage("Test");

will attempt to call a function named Test() on every component on that object

gameObject.BroadcastMessage("Test");

will attempt to call a function named Test on every component on that object and its children.

(and finally)

gameObject.SendMessageUpwards("Test");

will do the same as above, but try to call the Test function on every parent (and all ancestors) of that object

They are VERY SLOW, so don't use them in any performance critical parts of your scripts, however they can be good tools in your scripting arsenal.

Also, in response to your main question, your problem seems to be notifying the main "MyController" script of the cubes starting positions. That can be solved in numerous ways, a few lines added to the Start could suffice:

var controller : MyController = GameObject.Find("GameObjectScriptIsAttachedTo").GetComponent(MyController);
controller.AddMe(this);