Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

please have a look and tell me what seems to be the problem here ?

Discussion in 'Scripting' started by samshosho, Jan 21, 2012.

  1. samshosho

    samshosho

    Joined:
    Apr 12, 2010
    Posts:
    370
    Code (csharp):
    1. var waypointContainer : GameObject;
    2. private var waypoints : Array;
    3. private var currentWaypoint : int = 0;
    4.  
    5. function GetWaypoints () {
    6.     // Now, this function basically takes the container object for the waypoints, then finds all of the transforms in it,
    7.     // once it has the transforms, it checks to make sure it's not the container, and adds them to the array of waypoints.
    8.     var potentialWaypoints : Array = waypointContainer.GetComponentsInChildren( Transform );
    9.     waypoints = new Array();
    10.    
    11.     for ( var potentialWaypoint : Transform in potentialWaypoints ) {
    12.         if ( potentialWaypoint != waypointContainer.transform ) {
    13.             waypoints[ waypoints.length ] = potentialWaypoint;
    14.         }
    15.     }
    16. }
    17. function NavigateTowardsWaypoint () {
    18.     // now we just find the relative position of the waypoint from the car transform,
    19.     // that way we can determine how far to the left and right the waypoint is.
    20.     var RelativeWaypointPosition : Vector3 = transform.InverseTransformPoint( Vector3(
    21.                                                 waypoints[currentWaypoint].position.x,
    22.                                                 transform.position.y,
    23.                                                 waypoints[currentWaypoint].position.z ) );
    24. }
    This code is giving an error on xcode and the game freezes, while it works just fine in the editor.
    This is the error...


    Can someone tell me why is this giving a problem ?!?!?!?!?!?!
    While it works just fine in the editor... as long as i don't include the following lines at the begging of the script file.
    Code (csharp):
    1. #pragma strict
    2. #pragma implicit
    3. #pragma downcast
    Thanks in advance...
     
  2. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Firstly - I would cast potentialWaypoints as a Transform[] and not an Array.
     
  3. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    iOS requires #pragma strict for your scripts.

    This is actually a good idea for all projects, as it can prevent you creating unknowingly slow code, that relies on reflection to access simple members.

    The reason iOS requires it, is because that unknowingly slow code actually generates new code while it's running, and the iPhone does not allow dynamic code generation in any form. It must all be statically linked, which prevents people from inserting extra code after the App Approval process.

    The problem lies with Array. It is what's known as a type-less container. Unlike List<MyClass> or SomeClass[] you can put anything you want into the same container. This also causes issues because when you get something out of it, for example: waypoints[currentWaypoint].position.x, you cannot guarantee with any safety to the compiler that what you are getting from that Array is a Transform.

    I suggest either using Transform[] rather than an Array, or System.Collections.Generic.List.<Transform>. They allow you to specify a type that it must be and makes access and retrieval much faster.

    But on any other errors, put #pragma strict (and #pragma downcast) in all your scripts and fix the errors listed or else it won't run on iOS.
     
  4. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Also, even if you're using #pragma strict or C#, directly using Reflection is compatible with iOS, while Reflection.Emit is not.
     
  5. samshosho

    samshosho

    Joined:
    Apr 12, 2010
    Posts:
    370
    Thanks for all the replies...
    Here is what i changed, but still a strange error shows up in the editor now, after uncommenting the #pragma and the other two...

    Code (csharp):
    1. var waypointContainer : GameObject;
    2. private var waypoints : Transform[];
    3. private var currentWaypoint : int = 0;
    4.  
    5. function GetWaypoints () {
    6.     // Now, this function basically takes the container object for the waypoints, then finds all of the transforms in it,
    7.     // once it has the transforms, it checks to make sure it's not the container, and adds them to the array of waypoints.
    8.     var potentialWaypoints : Transform[] = waypointContainer.GetComponentsInChildren( Transform );
    9.     //waypoints = new Array();
    10.    
    11.     for ( var potentialWaypoint : Transform in potentialWaypoints ) {
    12.         if ( potentialWaypoint != waypointContainer.transform ) {
    13.             //print("potentialWaypoint.position = "+potentialWaypoint.position);
    14.             waypoints[ waypoints.length ] = potentialWaypoint;
    15.         }
    16.     }
    17. }
    Even though, it should take the casted potentialWaypoints as Transform[] and put the waypoints that are in the Container, but it gives an error... here it is...


    This is a Transform and that is a Transform... then what seems to be the problem !
     
  6. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    Replace:
    Code (csharp):
    1. waypointContainer.GetComponentsInChildren( Transform );
    with:
    Code (csharp):
    1. waypointContainer.GetComponentsInChildren.<Transform>();
    The reason being that casting a container ([], Array, List, etc...) is not as easy as casting a single object. When casting a single object, the underlying code has to check 1 item(the item being casted) to see if it's a valid cast. To cast a container to a different type, you would have to check each individual element, and depending on the number of items, could make a seemlingly harmless little cast take a LOT of time. For this reason C# and JS don't let you cast an entire array.

    Looking at the GetComponentsInChildren Docs:
    http://unity3d.com/support/document...tComponentsInChildren.html?from=MonoBehaviour

    In this case the original GetComponentsInChildren call returns the lowest possible common type available (Component), whereas the <> version will actually return the type you asked for(T, where T is whatever you put in the <> brackets). What it's telling you is that you cannot take a group of components and cast them to Transforms, because of the above mentioned casting of containers issue.

    The function call in code may be obvious, because you know you asked for Transforms, but from a moment to moment perspective, the program has no real consistent way to know that every single object inside of that Component[] is actually also a Transform, and so the cast is invalid.
     
  7. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    That's why C# rules :D But JS doesn't have the generic version of that method, thus it can't be used.

    I think the error might lie here:
    Code (csharp):
    1.  
    2. var potentialWaypoints : Transform[] = waypointContainer.GetComponentsInChildren( Transform )
    3.  
    Try this instead:
    Code (csharp):
    1.  
    2. var potentialWaypoints : Transform[] = waypointContainer.GetComponentsInChildren( Transform ) as Transform[];
    3.  
    If you still have issues, please tell us the exact line of code that is giving the error.
     
  8. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    JS does have that version of the function, as they both reference the same UnityEngine.dll that contains it.
    This used to be the case because there didn't exist the Generics syntax, but since 3.0 all generic UnityEngine functions are available in both languages.

    All functions are available in all languages(That's sort of .NETs thing), with the only exception being no syntax exists to be able to call it. Since JS has syntax for Generics, then Generics are able to be called (unsure if they can be declared though, as I don't know the syntax).

    In JS the syntax is the added . before the <>

    Edit: Because I'm generally rough using JS, I wrote a quick test:
    Code (csharp):
    1.  
    2. #pragma strict
    3.  
    4. var transforms : Transform[];
    5.  
    6. function Update ()
    7. {
    8. transforms = GetComponentsInChildren.<Transform>();
    9. }
    10.  
    Works for me.
     
    Last edited: Jan 22, 2012
  9. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Oh, thanks for the clarification Ntero, I didn't know it had been implemented in JS too :)
     
  10. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    I also looked up the casting an entire array. That's something JS can do that C# can't.

    Looks like JS, just goes through and performs the as operation for each element in the array (a quick test says non-transforms come out as null in the Array).
     
  11. samshosho

    samshosho

    Joined:
    Apr 12, 2010
    Posts:
    370
    Thank you so much, the casting in this way <Transform> , did help, i had no idea you can do that in JS.
    But i had problems after that, with NullRefrence...

    Here is what i did, to get rid of the null reference ...

    Code (csharp):
    1. var waypointContainer : GameObject;
    2. private var waypoints : Transform[];
    3. private var currentWaypoint : int = 0;
    4.  
    5. function GetWaypoints () {
    6.     // Now, this function basically takes the container object for the waypoints, then finds all of the transforms in it,
    7.     // once it has the transforms, it checks to make sure it's not the container, and adds them to the array of waypoints.
    8.     //var potentialWaypoints : Array = waypointContainer.GetComponentsInChildren( Transform );
    9.     var potentialWaypoints: Transform[] = waypointContainer.GetComponentsInChildren.<Transform>();
    10.     waypoints = waypointContainer.GetComponentsInChildren.<Transform>();
    11.     //waypoints = new Array();
    12.     var n: int = 0;
    13.     for ( var potentialWaypoint : Transform in potentialWaypoints ) {
    14.         if ( potentialWaypoint != waypointContainer.transform ) {
    15.             //print("potentialWaypoint.position = "+potentialWaypoint.position);
    16.             //var curwaypoint : Transform [] = potentialWaypoints[n];
    17.             print("potentialWaypoints = "+potentialWaypoints[n].position);
    18.             waypoints[ n ] = potentialWaypoint;
    19.             n++;
    20.         }
    21.     }
    22. }
    if i didn't put this line of code ...

    Code (csharp):
    1. waypoints = waypointContainer.GetComponentsInChildren.<Transform>();
    this line gives NullReference error...

    Code (csharp):
    1. waypoints[ n ] = potentialWaypoint;
    so finally got it to work, but first you have to put something inside waypoints, then call it's index number and rearrange the list of Transforms.

    Thanks to all that shared their thoughts....
     
  12. samshosho

    samshosho

    Joined:
    Apr 12, 2010
    Posts:
    370
    BTW, i am trying to create an AI for a car game, that's similar to UnitySteer... but with a different approach , so far i got the cars to pickup the waypoints from a container, then put an overlab detection sphere to detect close obstacles and steered away ... also i put a system to check with the waypoints ahead and see if there is a big deviation (sharp turn) coming up, thus slowing down eventually to make a smooth turn...