You don’t need to keep a list of receivers.
First you know the receivers are among the children, second you can use a tag for your fx objects.
Then you can implement this
public HashSet<GameObject> GetChildrenByTag(string tag) {
var hset = new HashSet<GameObject>();
for(int i = 0; i < transform.childCount; i++) {
var go = transform.GetChild(i).gameObject;
if(go.CompareTag(tag)) hset.Add(go);
}
return hset;
}
(This works ok if you don’t have dozens or more of children.)
Now you can use this set to do whatever
var hset = GetChildrenByTag("fx");
foreach(var childObject in hset) {
var listener = childObject.GetComponent<Listener>();
if(listener != null) listener.Notify(...);
}
GetComponentsInChildren would also work if X components was something that only lived on your fx objects.
You can also make it so that the message itself declares the intended audience, so that only valid listeners respond etc.
You can also make your own version of GetComponentsInChildren so that it supports tags as well.
public Component[] GetComponentsInChildren<Listener>(string tag) {
var list = new List<Component>(this.GetComponentsInChildren<Listener>());
for(int i = list.Count - 1; i >= 0; i--) {
if(!list[i].gameObject.CompareTag(tag)) list.RemoveAt(i);
}
return list.ToArray();
}
Of course, this should be a generic method so that all kinds of components are supported
public Component[] GetComponentsInChildren<T>(string tag, bool activeOnly = false) where T : Component {
var list = new List<Component>(this.GetComponentsInChildren<T>());
for(int i = list.Count - 1; i >= 0; i--) {
if(!activeOnly || list[i].gameObject.activeSelf) {
if(!list[i].gameObject.CompareTag(tag)) list.RemoveAt(i);
}
}
return list.ToArray();
}
There are literally hundreds of ways to do this, many of which are simple, but the best one depends on your exact needs and I cannot possibly list them all.
If there were many children objects, for example, this kind of naive approach wouldn’t be optimal any more, and I’d personally implement a decent event notification system, to which the objects would subscribe when spawned, and unsubscribe once they’re gone.
Then you can broadcast stuff into the “air” so to speak, and the intended audience would react by some internal logic. No physical connections between the objects are required. That way even if you had hundreds of children, just one or two of them would actually actively receive the message, because the rest of them didn’t even need to subscribe to anything.
And so on. Events are btw natively supported by C# in a sense there is a high-level vocabulary to set it up, and it will fill in the boilerplate for you (and the common logic, for example keeping the list of all subscribers is something you don’t have to do, you just “add” a subscriber to a declared event and the magic happens).