- Home /
InvalidCastException in Javascript
The error I get is this:
InvalidCastException: Cannot cast from source type to destination type. TestOffMeshLinkActivation.Start () (at Assets/Scripts/TestOffMeshLinkActivation.js:13)
The code:
private var m_OML1 : OffMeshLink;
private var m_OML1Renderers : Renderer[];
function Start()
{
var list : GameObject[];
list = GameObject.FindGameObjectsWithTag("OML1");
m_OML1 = list[0].GetComponent(OffMeshLink);
m_OML1Renderers = list[0].GetComponentsInChildren(Renderer);
}
The error happens on the line where it does GetComponentsInChildren. As far as I can tell, my code is exactly like the example here: http://unity3d.com/support/documentation/ScriptReference/GameObject.GetComponentsInChildren.html
I must be missing something silly, or I don't really understand how GetComponentsInChildren is supposed to work.
The FindGameObjectsWithTag is functioning, because I'm able to use the m_OML1 object with no trouble.
Update: GetComponentsInChildren(Renderer) is returning something of type Component[]. Why is that? Shouldn't it be of type Renderer[]?
Answer by iggy · Jun 01, 2011 at 09:34 PM
**GetComponentsInChildren(Renderer)**returns Component[]
**GetComponentsInChildren. ()** //without spaces, i had to enter spaces because of this HTML text decoderreturns Renderer[]
Are you saying the example at the following URL is incorrect?
http://unity3d.com/support/documentation/ScriptReference/GameObject.GetComponentsInChildren.html
I'm in Javascript, so I can't use the version with greater-than and less-than signs.
This answer
http://answers.unity3d.com/questions/12911/what-are-the-syntax-differences-in-c-and-javascrip.html
Says this:
// In Javascript, the "GetComponent" function returns an object, which is automatically cast by Javascript to the correct type
var someScript : ExampleScript = GetComponent(ExampleScript);
@almo: the example in that URL is correct. As iggy said, it returns Component[]. And the code iggy wrote--`GetComponentsInChildren.()`--is Javascript, and wouldn't compile in C# (which would be GetComponentsInChildren<Renderer>()
). Your code isn't like the example; you're trying to cast Component[] to Renderer[].
Ok, I get the GetComponentsInChildren.<Renderer>()
syntax now. Thanks! But I still don't see the difference between the code I posted and the example at the URL. I have private var m_O$$anonymous$$L1Renderers : Renderer[];
and m_O$$anonymous$$L1Renderers = list[0].GetComponentsInChildren(Renderer);
The example has var hingeJoints : HingeJoint[];
and hingeJoints = gameObject.GetComponentsInChildren(HingeJoint);
@almo: oops, yeah, I missed that part. In fact, that example in the docs is wrong and won't work. It should use hingeJoints = gameObject.GetComponentsInChildren.<HingeJoint>();
ins$$anonymous$$d.
Answer by perchik · Jul 31, 2013 at 04:52 PM
Actually the docs a̶r̶e̶n̶'̶t are wrong. For Javascript you don't have to use the angle brackets and pass in a type. The reason the documentation version is almost right is the following line :
for (var joint : HingeJoint in hingeJoints)
That line takes each Component item from hingeJoints
and implicitly casts them into the HingeJoint type.
The documentation clearly says
GetComponentsInChildren(type: Type): Component[];
which means the function returns an array of Components. Javascript allows you to cast on the fly, which makes it very sloppy and prone to errors, but the documentation is correct.
Revision
Revised after all the comments on my answer.
The documentation is wrong, but not for the reasons argued. The documentation has the line var hingeJoints : HingeJoint[];
which breaks, because it tries to implicitly convert an array of components to HingeJoint[]. If you changed it to var hingeJoints;
it would work exactly right.
I made a dummy scene to illustrate why the rest of it works. TestObject has "test.js" on it, and three children, a,b,c, with Mesh Renderers on them.
test.js:
#pragma strict
function Start () {
var renders = gameObject.GetComponentsInChildren(MeshRenderer); //Component[]
for(var renderer:MeshRenderer in renders){ //implict cast on this line
Debug.Log(renderer.name);
}
}
When I click play, it prints out a, b, c to the log (so it is finding each of the renderers correctly).
The reason this works is implicit casting. If I were to explicitly cast everything, it would look like this:
#pragma strict
function Start () {
var renders:Component[];
renders = gameObject.GetComponentsInChildren(MeshRenderer);
for(var comp:Component in renders){ //get each object as a component
var renderer : MeshRenderer;
renderer= comp as MeshRenderer; //cast the component to a MeshRenderer
Debug.Log(renderer.name);
}
}
I'm not saying this is the right way. I'm definitely not advocating for this because it's incredibly sloppy and implicit type casting causes lots of problems (as noted). All I am saying is that the syntax of passing a type through parentheses works and you don't have to use the generic version.
Impossible.
$$anonymous$$y script was causing an error when I used
(...)
ins$$anonymous$$d of
<...>()
No, the docs are really not correct. Did you actually try it? It will fail, even without #pragma strict, which disallows casting on the fly. (And all example code needs to be compliant with #pragma strict, since it's forced in many cases—iOS etc.—and can't be considered optional. Not to mention the standard script template for JS includes #pragma strict by default. Which is irrelevant since the example code is just plain wrong regardless. ;) )
using javascript on ios with pragma strict
I stumbled often on this problem
everything works fine with <..>() and does not work with (...)
I store the renders as a var. If you wanted to be explicit, you could do this:
var renders:Component[];
renders = gameObject.GetComponentsInChildren($$anonymous$$eshRenderer);
for(var renderer:$$anonymous$$eshRenderer in renders){
Debug.Log(renderer.name);
}
Line 1 creates renders as an array of Components
Line 2 Get all of the $$anonymous$$eshRenderer components and stores it as a component array
Line 3 says for each $$anonymous$$eshRenderer in the renders array do something. This is where the implicit conversion is, because each item in renders is a Component, but I implicitly cast it to a $$anonymous$$eshRenderer, which is exactly how the Documentation page does it