- Home /
Invalid Cast error when my format seems the same as the script reference example?
Here is the example of "GetComponentsInChildren" from the Unity Script Reference:
var hingeJoints : HingeJoint[];
hingeJoints = gameObject.GetComponentsInChildren(HingeJoint);
for (var joint : HingeJoint in hingeJoints) {
joint.useSpring = false;
}
Here is what I have in my script:
private var colliders : MeshCollider[];
function Awake ()
{
colliders = gameObject.GetComponentsInChildren(MeshCollider);
}
And I am getting an Invalid Cast error for that. (I have also tried making it more generically just "Collider" as opposed to "MeshCollider", but still the same error.)
What gives?
EDIT: Ok, here's my JS workaround that I came up with before I saw Jessy's edit/addition below... (are we doing essentially the same thing?)
private var colliders : MeshCollider[]; private var tempCol : Array;
function Awake () { tempCol = new Array();
for (var col : MeshCollider in gameObject.GetComponentsInChildren(MeshCollider)) tempCol.Push(col); colliders = tempCol.ToBuiltin(MeshCollider); }
Also, I figure doing it this way is OK performance-wise for me, since I do it once in the Awake() function, but I don't think it would be good to do it in an Update()...
Lots of editing performed. Check that out, then let me know ASAP if you report the bug. I'll do it otherwise.
best way would be with generics (his last suggestion), using an Array is going to be slower and heavier on the garbage collector. js version is GetComponentsInChildren.<$$anonymous$$eshCollider>()
That's what I'm saying in this answer, and the other one. That generic form doesn't work. It just results in the error: "Internal compiler error. See the console log for more information. output was:BCE0011: An error occurred during the execution of the step 'Boo.Lang.Compiler.Steps.EmitAssembly': 'Object reference not set to an instance of an object'." Does this not happen for you, $$anonymous$$ike?
Answer by Jessy · Feb 17, 2011 at 05:44 PM
http://answers.unity3d.com/questions/39864/invalidcastexception-in-a-code-from-script-reference
It's a good question, but was already asked, so I voted to close this; I believe the answers ought to be collected in one place.
As for your edit, that works, but I consider the Array class obsolete, now that UnityScript supports generics. Also, your script requires the use of dynamic typing. It doesn't matter, because it's a small bit of code running once, but you should at least know how to do better. (Using #pragma strict at the top of your scripts will help you write efficient code.) A couple more general tip: there's no point in using gameObject because GetComponentsInChildren is also a method of Component. And there's no reason to define a temporary variable outside of a function, if its scope is only within the function.
So, your code, with a List instead of a Unity Array:
private var colliders : MeshCollider[];
function Awake () { var colliderList = new List.<MeshCollider>();
for (var component in GetComponentsInChildren(MeshCollider)) colliderList.Add(component as MeshCollider); colliders = colliderList.ToArray(); }
But this kind of thing is why Array.ConvertAll exists. I don't know if it's faster or slower, but I like the look of it better:
colliders = System.Array.ConvertAll(
GetComponentsInChildren(MeshCollider),
function (component) component as MeshCollider
);
Here are pages that might be helpful to you, if you don't know what that code means yet: http://unity3d.com/support/documentation/Manual/MonoUpgradeDetails.html
The syntax for lambda expressions is different in C#, but this example is less verbose than the MSDN's.
Finally, if you want optimum performance, you probably should just not bother with a List or ConvertAll, and implement the conversion yourself:
var colliderComponents = GetComponentsInChildren(MeshCollider);
colliders = new MeshCollider[colliderComponents.Length];
for (var i = 0; i < colliders.Length; ++i)
colliders[i] = colliderComponents[i] as MeshCollider;
I don't think that looks any better or worse than the List method.
But the best thing to do, would be to report the useless error that stops this ideal code from compiling:
colliders = GetComponentsInChildren.<MeshCollider>();
And man, I've written so much here, now, that this question probably shouldn't be closed anymore. :-P
Right on, thanks for the quick response. Since I don't really know C# I guess I will have to figure out some other way around this...
BTW - slowly making my way through your shader tutorials, Jessy, thanks for those.
Your answer
Follow this Question
Related Questions
InvalidCastException: Cannot cast from source type to destination type. 3 Answers
"Cannot cast from source type to destination type"- instantiating 4 Answers
InvalidCastException: Cannot cast from source type to destination type. 4 Answers
"Cannot cast from source type to destination type" 2 Answers
InvalidCastException: Cannot cast from source type to destination type. 1 Answer