My game is divided into rooms, and each room has a Room data class attached to it. Inside each room are interactable objects, each of which has an Entity class attached to it. When the game starts I’m attempting to use FindGameObjectsWithTag to gather a list of rooms, add each room’s Room class to a master list, then use linq to iterate through the children of each room to add every object that is a) a child of the current room, and b) has the “Entity” tag, to a separate list. However, this is currently producing an error, to wit “The type UnityEngine.GameObject' must be convertible to UnityEngine.Component’ in order to use it as parameter T' in the generic type or method UnityEngine.Component.GetComponentsInChildren()'”. Is this resolved with a simple syntax tweak, or am I going about this in a plain silly manner?
List GenerateRoomList(){
List<Room> myRoom = new List<Room> () ; //Initialize myRoom
GameObject[] sectorList = GameObject.FindGameObjectsWithTag ("Room"); //Find all rooms in game
for (int i = 0; i < sectorList.Length; i++) {
Room newRoom = sectorList*.GetComponent<Room>();*
_ newRoom.name = sectorList*.name;_ _ newRoom.location = sectorList.transform; List entityList = new List(); GameObject myEntity = newRoom.location.GetComponentsInChildren().FirstOrDefault (n => n.tag == “Entity”); for (int i = 0; i < myEntity.Length; i++){ newRoom.entities.Add (myEntity.GetComponent); } myRoom.Add (newRoom); } return myRoom; }*_
The error is in line 12: the class “GameObject” does not inherit “Component” - it can not be converted.
I have written two extensions for dealing with finding children - it seeks through the entire children tree and yields the results, one which returns all children and one which uses a predicate:
public static class GameObjectExtensions {
/// <summary>
/// Method which loops recursivly through all children of a game object matching the specified predicate.
/// </summary>
/// <param name="gameObject">The parent game object</param>
/// <param name="predicate">The predicate to use</param>
/// <returns>The enumerated children</returns>
public static IEnumerable<GameObject> FindChildren(this GameObject gameObject, Func<GameObject, bool> predicate) {
for (int n = 0; n < gameObject.transform.childCount; n++) {
var child = gameObject.transform.GetChild(n);
if (predicate(child.gameObject)) {
yield return child.gameObject;
}
foreach (var subChild in child.gameObject.FindChildren(predicate)) {
yield return subChild;
}
}
}
/// <summary>
/// Method which loops recursivly through all children of a game object.
/// </summary>
/// <param name="gameObject">The parent game object</param>
/// <param name="predicate">The predicate to use</param>
/// <returns>The enumerated children</returns>
public static IEnumerable<GameObject> FindChildren(this GameObject gameObject) {
for (int n = 0; n < gameObject.transform.childCount; n++) {
var child = gameObject.transform.GetChild(n); ;
foreach (var subChild in child.gameObject.FindChildren()) {
yield return subChild;
}
yield return child.gameObject;
}
}
}
Put this class in a file named “GameObjectExtensions.cs” and use it like your linq statement:
var entities = newRoom.gameObject.FindChildren(n => n.tag == "Entity");
foreach (var entity in entities) {
newRoom.entities.Add (entity.GetComponent<Entity>());
}
// You could simplify this by typing (replaces the list!):
newRoom.entities = newRoom.gameObject.FindChildren(n => n.tag == "Entity").Select(k => k.GetComponent<Entity>()).ToList();
// To deal with possible null values, use a Where statement:
newRoom.entities = newRoom.gameObject.FindChildren(n => n.tag == "Entity").Select(k => k.GetComponent<Entity>()).Where(c => c != null).ToList();