Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Sendatsu_Yoshimitsu · Dec 07, 2014 at 09:03 AM · c#linq

Trouble with LINQ syntax: "Gameobject must be convertible to Component in order to use it as parameter T"

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[i].GetComponent<Room>();
         newRoom.name = sectorList[i].name;
         newRoom.location = sectorList[i].transform;

         List<Entity> entityList = new List<Entity>();
         GameObject[] myEntity = newRoom.location.GetComponentsInChildren<GameObject>().FirstOrDefault (n => n.tag == "Entity");

         for (int i = 0; i < myEntity.Length; i++){
             newRoom.entities.Add (myEntity[i].GetComponent<Entity>);
         }
         myRoom.Add (newRoom);
     }
     return myRoom;
 }
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Lunatix · Dec 07, 2014 at 10:47 AM

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();
Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Sendatsu_Yoshimitsu · Dec 07, 2014 at 11:12 AM 0
Share

I'm nearly certain this is a breathtakingly awesome implementation that massively simplifies what I was working on, but I'm having a bit of a problem getting it to recognize FindChildren: with GameObjectExtensions copied verbatim from your example (plus the using statements needed), each usage in my data class returns "Room.location does not contain a member 'FindChildren', and the best extension method overload `GameObjectExtensions.FindChildren(this UnityEngine.GameObject, System.Func)' has some invalid arguments"... do I need to be using a bool in each call after the tag's string?

avatar image Lunatix · Dec 07, 2014 at 11:21 AM 0
Share

Oh my god, I'm sorry, I missed a line in your code - don't use location, since it's a Transform, use the GameObject when calling the method!

I will alter my example to fit to your problem!

avatar image Sendatsu_Yoshimitsu · Dec 07, 2014 at 11:36 AM 0
Share

It's no problem at all! I assumed I had bungled something, as that's liable to be what happened about 99% of the time. :)

It works perfectly now, and is way cleaner than the way I was going about it- thank you so much!!

For future investigation on my part, you suggested using typing to replace the lists- could you expand a bit on what you mean? I use a lot of lists to move data, so this could potentially be a big optimization.

avatar image Lunatix · Dec 07, 2014 at 12:08 PM 0
Share

I just placed a hint that my optimized statement would replace the entire list, so everything which was added to the already existing list would be gone - if thats a problem, just use newRoom.entities.AddRange(entities);.

Lists are not that bad, an optimization would be to tell the list how big it will get when using it, for example, if you now you will add 1000 items, tell the constructor to reserve enough space.

avatar image Sendatsu_Yoshimitsu · Dec 07, 2014 at 12:46 PM 1
Share

Oh this is perfect, thank you so much for your help! :)

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

26 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Distribute terrain in zones 3 Answers

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

Multiple Cars not working 1 Answer

[Solved] How to LINQ to ArrayList all the Transform within a Range? 1 Answer

Confusion over LINQ syntax 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges