(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.