Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 /
  • Help Room /
avatar image
0
Question by Bazzalisk · Nov 06, 2015 at 05:22 PM · c#

Cannot cast Source from Type

Hey guys I've just run into an error I havn't encountered before, I've been dabbling in Unity-c# for a little while so hopefully getting stuck on this isn't too noobie.

What I'm trying to do is fill my 'public static Tile_Levels[] tilesAll;' with all children Tile_Levels that are children to the transform this script is attached to. The error is occurring on the foreach loop between Tile_Levels in transform.

 void ProcessTiles(){
         
         tilesAll = new Tile_Levels[numberOfTiles];
         int TileNo = 0;
 
         foreach (Tile_Levels childtile in transform)
         {
                 tilesAll[TileNo] = childtile;
             TileNo ++;
         }
         
         AssignMines ();
     }

Thankyou for your time, if I havn't given enough information just ask for what you want!

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

2 Replies

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

Answer by Glurth · Nov 06, 2015 at 05:40 PM

It looks like you are trying to iterate (foreach) through the transform itself, which is NOT an array, list or other collection. That being said, it does CONTAIN a collection of children, an important distinction (IS vs HAS).

perhaps something like this is what you are looking for?...

 ...
 Tile_Levels[] tileLevelChildrenArray=transform.GetComponentsInChildren< Tile_Levels >();
 foreach(Tile_Levels childtile in tileLevelChildrenArray)
 ...

The GetComponentsInChildren will find all children that contain a component of type "Tile_Levels". (I'm making the assumption this class is a MonoBehavior, a.k.a. "a component".) The results will put into an array, which you CAN iterate through.

Edit: looking at your code a bit more, you may not even WANT a foreach loop after calling GetComponentsInChildren, since it looks like THAT is why you were looping... not sure though.

Comment
Add comment · Show 8 · 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 Bazzalisk · Nov 07, 2015 at 09:24 AM 0
Share

Thank you, that did solve my problem, as you can probably see I don't use foreach loop every much. I'm sorry to ask you further for help but I'm now getting an error from the actual loop part from my foreach and I don't know how to fix it. I'm getting error Array index is out of range because of tileNo, I've tried changing it to other things and using the arrays.length but still isn't working, If you dont want to/cant solve this then I'll accept your answer anyway, thank you!

avatar image Glurth Bazzalisk · Nov 07, 2015 at 05:02 PM 0
Share

" I'm getting error Array index is out of range because of tileNo"

I'm not quite sure WHY you are using a loop in this situation, but I'll be happy to explain the error. The "index" it is reffering to is the number you are putting inside the brackets. "out of range" means than the index you are feeding it is TOO LARGE for the actuall array. dont forget, you specified exactly how large the array was when you created it, in this line:

 tilesAll = new Tile_Levels[numberOfTiles];

so, if you try to "index" the array with a number that is equal to or larger than "numberOfTiles", it will spit out an "out of range" error.

The next logical question is obviously: How do I know how large to make the array? that depends on how you are going to use it, but in this situation, you I think you want to use the size of the array you are going to iterate through with the foreach:

    ....
     Tile_Levels[] tileLevelChildrenArray=transform.GetComponentsInChildren< Tile_Levels >();
     numberOfTiles = tileLevelChildrenArray.Length;  //use the Length member. all arrays have this.
     tilesAll = new Tile_Levels[numberOfTiles];
     ....

also, FYI: if you prefer for(;;) to foreach(), this is "pretty much"(but NOT exactly) equivalent for a full array iteration

 int max= array.Length;
 for(int i=0;i<max;i++) 
 {
   currentElement = array[i];
   ....
 }

and

 foreach(ElementType currentElement  in array)
 {
    ....
 }

avatar image Bazzalisk · Nov 07, 2015 at 07:45 PM 0
Share

Okay, thank you so much for your help again, I really appreciate it, I'm learning... slowly. I just have one more issue... sorry. Logically, in my $$anonymous$$d everything should be working however when I try call the stored Tile_Levels element in the array from a child of the object, I get Null returned. The children of $$anonymous$$anager_Levels all have Tile_Levels attached as I'm sure you can tell, but when the children call "print ($$anonymous$$anager_Levels.tilesAll[1]);" in start() I get null return. I think this may be because the start() function on Tiles_Levels finishes it's call before $$anonymous$$anager_Levels assigns the elements to the array but i have no idea how to go about fixing that. I'm sorry if this is really messy and for being so clueless, I really am trying to learn. Thank you again, very much. Here's my script for $$anonymous$$anager_Levels incase it helps.

 public class $$anonymous$$anager_Levels : $$anonymous$$onoBehaviour {
 public static Tile_Levels[] tilesAll;
 
 void Start () {
         ProcessTiles ();
             }
 
     void ProcessTiles(){
 
         numberOfTiles = transform.childCount;
         tilesAll = new Tile_Levels[numberOfTiles];
         Tile_Levels[] tileLevelChildrenArray = transform.GetComponentsInChildren< Tile_Levels >();
 
         for (int tilesProcessed = 0; tilesProcessed < numberOfTiles; tilesProcessed++) {
             Tile_Levels processingtile = tileLevelChildrenArray[tilesProcessed];
             processingtile.ID = tilesProcessed;
             tilesAll[tilesProcessed] = processingtile;
         }
         
         Assign$$anonymous$$ines ();
     }
 


 
 
avatar image Glurth Bazzalisk · Nov 07, 2015 at 08:17 PM 0
Share

Hmm, afraid I'm not really clear on the new issue, in particular, this line confuses me: " when I try call the stored Tile_Levels element in the array from a child of the object, I get Null returned."

Still, I think this may warrant a new question, at this point.
FYI: Though I have not used it, I think there is a way on the site to notify users, when you post a question. Feel free to notify to ask for help.

avatar image Statement Bazzalisk · Nov 07, 2015 at 08:47 PM 0
Share
 numberOfTiles = transform.childCount;

This return the number of transform children and is not guaranteed to be the same as the number of components (it return all components on this game object, then children gameobjects, then grandchildren, and so on). If you have a child without a Tile_Levels component, you'll go out of bounds. Also if you have a child with more than one Tile_Levels component, you won't get every component.

avatar image Statement · Nov 07, 2015 at 08:35 PM 0
Share

I'll slide in slightly off topic and vanish just as quick.

"... which is NOT an array, list or other collection."

No, but foreach operates on IEnumerable, which arrays, lists and other collections ARE, and is what foreach require.

"... an important distinction (IS vs HAS)"

Well, this is analogous to say that the List HAS an array, and IS not the array... or that a certain Collection HAS a List that HAS an array. It doesn't matter how it it stores the data (arrays, linked lists, trees, whatever), they all IS-a IEnumerable, just like Transform.

Transform IS an IEnumerable so I don't think it's folly to attempt to use foreach on a transform.

 public class Transform : Component, IEnumerable

The problem is that it doesn't specify the type so a cast has to be performed from System.Object to the type you wish to use. It just happens to be that Transform will yield Transform components and no other components - resulting in a cast failure at runtime.

avatar image Glurth Statement · Nov 08, 2015 at 03:02 PM 0
Share

OH! I had no idea transform was enumberable! (love this site- thank you!) What order does it enumerate them?

avatar image Statement Glurth · Nov 10, 2015 at 03:22 PM 0
Share

Same as GetChild(0) to GetChild(N - 1).

Note that calling foreach will create an enumerator object for the enumeration.

 public IEnumerator GetEnumerator()
 {
     return new Transform.Enumerator(this);
 }

I don't know if that object is immediately discarded by the runtime, but if it isn't, then it means it'll make an allocation every time it enters the foreach (because foreach call GetEnumerator), generate garbage (since it was only used for the loop) and may cause the garbage collector to collect garbage, stalling the game until garbage collection is complete. If performance is a real concern (hobbyists need not concern unless they want to do it for practice/fun), it is more efficient to access each child with GetChild(i) in a good old for loop because:

  • You don't allocate an object on the heap

  • You won't risk waking up the garbage collector

  • You won't have to pay the overhead of the method calls to increment and retrieve the next object

However, IEnumerables are nice to use for quick prototyping, especially with LINQ and such. I typically don't care about NOT using enumerators until I actually have a performance problem.

avatar image
0

Answer by Statement · Nov 07, 2015 at 08:45 PM

You already get an array from GetComponentsInChildren so you don't need to create a new array.

 void ProcessTiles()
 {
     tilesAll = transform.GetComponentsInChildren<Tile_Levels>();
 
     for (int i = 0; i < tilesAll.Length; ++i)
     {
         tilesAll[i].ID = i;
     }
 
     AssignMines();
 }
Comment
Add comment · 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

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

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Press M to enlarge the minimap 1 Answer

Slerp rotation issue when calling a lot 0 Answers

Car from Unity's standard assets giving me of null reference errors 0 Answers

Create a Prefab directly inside a GameObject (not SetParent or transform.parent) 0 Answers

error CS0266 Cannot implicitly convert type `float' to `int'. An explicit conversion exists (are you missing a cast?) 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