Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Need some help converting C# to js

Discussion in 'Scripting' started by Griffo, Oct 17, 2016.

  1. Griffo

    Griffo

    Joined:
    Jul 5, 2011
    Posts:
    698
    Hi, I'd like to covert the C# script to .js but seem to be getting it wrong.

    Could someone please tell me what I'm doing wrong .. Cheers.

    From ..

    Code (CSharp):
    1. using UnityEngine;
    2. [System.Serializable]
    3. public class Bezier : System.Object
    4. {
    5.  
    6.     public Vector3 p0;
    7.     public Vector3 p1;
    8.     public Vector3 p2;
    9.     public Vector3 p3;
    10.     public float length=0;
    11.     public Vector3[] points;
    12.     // Init function v0 = 1st point, v1 = handle of the 1st point , v2 = handle of the 2nd point, v3 = 2nd point
    13.     // handle1 = v0 + v1
    14.     // handle2 = v3 + v2
    15.     public Bezier( Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, int _calculatePoints=0 )
    16.     {
    17.         this.p0 = v0;
    18.         this.p1 = v1;
    19.         this.p2 = v2;
    20.         this.p3 = v3;
    21.      
    22.         if(_calculatePoints>0) CalculatePoints(_calculatePoints);
    23.     }
    24.  
    25.     // 0.0 >= t <= 1.0 her be magic and dragons
    26.     public Vector3 GetPointAtTime( float t )
    27.     {
    28.         float u = 1f - t;
    29.         float tt = t * t;
    30.         float uu = u * u;
    31.         float uuu = uu * u;
    32.         float ttt = tt * t;
    33.      
    34.         Vector3 p = uuu * p0; //first term
    35.         p += 3 * uu * t * p1; //second term
    36.         p += 3 * u * tt * p2; //third term
    37.         p += ttt * p3; //fourth term
    38.      
    39.         return p;
    40.      
    41.     }
    42.     //where _num is the desired output of points and _precision is how good we want matching to be
    43.     public void CalculatePoints(int _num, int _precision=100)
    44.     {
    45.         if(_num>_precision) Debug.LogError("_num must be less than _precision");
    46.      
    47.         //calculate the length using _precision to give a rough estimate, save lengths in array
    48.         length=0;
    49.         //store the lengths between PointsAtTime in an array
    50.         float[] arcLengths = new float[_precision];
    51.      
    52.         Vector3 oldPoint = GetPointAtTime(0);
    53.      
    54.         for(int p=1;p<arcLengths.Length;p++)
    55.         {
    56.             Vector3 newPoint = GetPointAtTime((float) p/_precision); //get next point
    57.             arcLengths[p] = Vector3.Distance(oldPoint,newPoint); //find distance to old point
    58.             length += arcLengths[p]; //add it to the bezier's length
    59.             oldPoint = newPoint; //new is old for next loop
    60.         }
    61.      
    62.         //create our points array
    63.         points = new Vector3[_num];
    64.         //target length for spacing
    65.         float segmentLength = length/_num;
    66.      
    67.         //arc index is where we got up to in the array to avoid the Shlemiel error http://www.joelonsoftware.com/articles/fog0000000319.html
    68.         int arcIndex = 0;
    69.      
    70.         float walkLength=0; //how far along the path we've walked
    71.         oldPoint = GetPointAtTime(0);
    72.      
    73.         //iterate through points and set them
    74.         for(int i=0;i<points.Length;i++)
    75.         {
    76.             float iSegLength = i * segmentLength; //what the total length of the walkLength must equal to be valid
    77.             //run through the arcLengths until past it
    78.             while(walkLength<iSegLength)
    79.             {
    80.                 walkLength+=arcLengths[arcIndex]; //add the next arcLength to the walk
    81.                 arcIndex++; //go to next arcLength
    82.             }
    83.             //walkLength has exceeded target, so lets find where between 0 and 1 it is
    84.             points[i] = GetPointAtTime((float)arcIndex/arcLengths.Length);
    85.          
    86.         }
    87.      
    88.      
    89.     }
    90. }
    To ..

    Code (JavaScript):
    1. #pragma strict
    2.  
    3. import UnityEngine;
    4.  
    5. var p0 : Vector3;
    6. var p1 : Vector3;
    7. var p2 : Vector3;
    8. var p3 : Vector3;
    9.  
    10. var length : float=0;
    11. var points : Vector3[];
    12.  
    13. // Init function v0 = 1st point, v1 = handle of the 1st point , v2 = handle of the 2nd point, v3 = 2nd point
    14. // handle1 = v0 + v1
    15. // handle2 = v3 + v2
    16. //              ----------------------------
    17. function Bezier(v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, _calculatePoints: int)
    18. {
    19.     _calculatePoints=0;
    20.  
    21.     this.p0 = v0;
    22.     this.p1 = v1;
    23.     this.p2 = v2;
    24.     this.p3 = v3;
    25.  
    26.     if(_calculatePoints>0) CalculatePoints(_calculatePoints);
    27. }
    28. //              ----------------------------
    29. // 0.0 >= t <= 1.0 her be magic and dragons
    30. //public Vector3 GetPointAtTime( float t )
    31. function GetPointAtTime(t : float)
    32. {
    33.     var u : float = 1f - t;
    34.     var tt : float = t * t;
    35.     var uu : float = u * u;
    36.     var uuu : float = uu * u;
    37.     var ttt : float = tt * t;
    38.  
    39.     var p : Vector3 = uuu * p0; //first term
    40.     p += 3 * uu * t * p1; //second term
    41.     p += 3 * u * tt * p2; //third term
    42.     p += ttt * p3; //fourth term
    43.  
    44.     return p;
    45. }
    46. //              ----------------------------
    47. //where _num is the desired output of points and _precision is how good we want matching to be
    48. function CalculatePoints(_num: int)
    49. {
    50.     var _precision : int = 100;
    51.  
    52.     if(_num>_precision) Debug.LogError("_num must be less than _precision");
    53.  
    54.     //calculate the length using _precision to give a rough estimate, save lengths in array
    55.     length=0;
    56.     //store the lengths between PointsAtTime in an array
    57.     var arcLengths : float[] = new float[_precision];
    58.  
    59.     var oldPoint : Vector3 = GetPointAtTime(0);
    60.  
    61.     for(var p : int=1; p<arcLengths.Length; p++)
    62.     {
    63.         var newPoint : Vector3 = GetPointAtTime(p/_precision); //get next point
    64.         arcLengths[p] = Vector3.Distance(oldPoint,newPoint); //find distance to old point
    65.         length += arcLengths[p]; //add it to the bezier's length
    66.         oldPoint = newPoint; //new is old for next loop
    67.     }
    68.  
    69.     //create our points array
    70.     var points : Vector3[] = new Vector3[_num];
    71.     //target length for spacing
    72.     var segmentLength : float = length/_num;
    73.  
    74.     //arc index is where we got up to in the array to avoid the Shlemiel error http://www.joelonsoftware.com/articles/fog0000000319.html
    75.     var arcIndex : int = 0;
    76.  
    77.     var walkLength : float=0; //how far along the path we've walked
    78.     oldPoint = GetPointAtTime(0);
    79.  
    80.     //iterate through points and set them
    81.     for(var i : int=0; i<points.Length; i++)
    82.     {
    83.         var iSegLength : float = i * segmentLength; //what the total length of the walkLength must equal to be valid
    84.         //run through the arcLengths until past it
    85.         while(walkLength<iSegLength)
    86.         {
    87.             walkLength+=arcLengths[arcIndex]; //add the next arcLength to the walk
    88.             arcIndex++; //go to next arcLength
    89.         }
    90.         //walkLength has exceeded target, so lets find where between 0 and 1 it is
    91.         points[i] = GetPointAtTime(arcIndex/arcLengths.Length);
    92.     }
    93. }
    94. //              ----------------------------
    All I'm after is a way to place the flight points of the bezier cure evenly along the curve, I have my own code that I generate a flight path made up of a random amount of bezier curves.

    But in the above code that does what I'm after, so if I convert it I'll edit the part I want and add it to my script..
     
    Last edited: Oct 17, 2016
  2. AlucardJay

    AlucardJay

    Joined:
    May 28, 2012
    Posts:
    328
    EDIT: INCORRECT. uJS doesn't take optional default parameters. Jump to the next comment.
    --------------------------------------------------------------------------------------------------------------------------
    I only scanned quickly, and one thing stood out. The default parameter in the class constructor is not implemented.
    Code (csharp):
    1. // C#
    2. public Bezier( Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, int _calculatePoints=0 ) {...}
    3.  
    4. // uJS
    5. function Bezier( v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, _calculatePoints: int = 0 ) {...}
    and don't forget to remove your 'fix' at line 19 (_calculatePoints=0;)

    as you have not specified the desired result and the current result, not sure if that's the only problem. Anyway, good luck, hope it resolves the problem.
     
    Last edited: Oct 20, 2016
  3. Griffo

    Griffo

    Joined:
    Jul 5, 2011
    Posts:
    698
    Hi @alucardj

    Thanks for the input, is he default parameter in the class constructor is not implemented? I say that because in line 17 I thought I'd done that, and if

    Code (JavaScript):
    1. _calculatePoints: int = 0
    Is added at the end it gives an error, so thats why I put it at line 19 ..

    I sort have gave up with that script and decided to go down another route .. But still would like a good solution to spreading the points of a bezier curve out evenly along the path ..
     
  4. AlucardJay

    AlucardJay

    Joined:
    May 28, 2012
    Posts:
    328
    Firstly, sorry for the incorrect comment. Admittedly I just assumed uJS would handle optional parameters, turns out it doesn't :/

    After a search and some reading, this seemed the best approach : http://answers.unity3d.com/questions/56502/creating-function-with-default-arguments.html
    creating another class, and then passing a populated instance of that class to the parameter in the class constructor .... crazy

    another way would be to have 2 class constructors :
    Code (csharp):
    1.  
    2. function Bezier( v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3 )
    3. {
    4.    //_calculatePoints : int = 0; // default value
    5.   this.p0 = v0;
    6.   this.p1 = v1;
    7.   this.p2 = v2;
    8.   this.p3 = v3;
    9.   //if(_calculatePoints>0) CalculatePoints(_calculatePoints); // value is known to be zero, no need for this line
    10. }
    11.  
    12. function Bezier( v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, _calculatePoints: int )
    13. {
    14.   this.p0 = v0;
    15.   this.p1 = v1;
    16.   this.p2 = v2;
    17.   this.p3 = v3;
    18.   if ( _calculatePoints > 0 ) CalculatePoints( _calculatePoints ); // not using default value of zero, perform check
    19. }
    20.  
    Now I look harder at the code, all the _calculatePoints condition is checking if there are any points on the curve to calculate. If _calculatePoints is zero, then there are no points to calculate, do nothing!
    So you still have to remove line 19 ( _calculatePoints=0; ) , as this is basically saying 'no points on the curve, do nothing'
     
    Last edited: Oct 20, 2016
  5. AlucardJay

    AlucardJay

    Joined:
    May 28, 2012
    Posts:
    328
    OK, solved it. The problem was dividing integers by integers was giving truncated results.
    Code (csharp):
    1. //var newPoint : Vector3 = GetPointAtTime(p/_precision); //get next point
    2. var newPoint : Vector3 = GetPointAtTime( parseFloat(p) / parseFloat(_precision) ); //get next point
    3. -- and --
    4. //points[i] = GetPointAtTime( arcIndex / arcLengths.Length );
    5. points[i] = GetPointAtTime( parseFloat(arcIndex) / parseFloat(arcLengths.Length) );
    Also added a return type to the GetPointAtTime function
    Code (csharp):
    1. function GetPointAtTime(t : float) : Vector3
    So just a couple more considerations with conversion :
    Code (csharp):
    1. parsing as float or int
    2. // C#
    3. (float)myVar
    4. //uJS
    5. parseFloat(myVar)
    6.  
    7. returning a value from a function
    8. // C#
    9. Vector3 Foobar()
    10. { return val; }
    11. //uJS
    12. function Foobar() : Vector3
    13. { return val; }
    Here's the full uJS class, tested and working :
    Code (csharp):
    1. #pragma strict
    2.  
    3. @System.Serializable
    4. public class Bezier extends System.Object
    5. {
    6.    var p0 : Vector3;
    7.    var p1 : Vector3;
    8.    var p2 : Vector3;
    9.    var p3 : Vector3;
    10.  
    11.    var length : float=0;
    12.    var points : Vector3[];
    13.  
    14.    // Init function v0 = 1st point, v1 = handle of the 1st point , v2 = handle of the 2nd point, v3 = 2nd point
    15.    // handle1 = v0 + v1
    16.    // handle2 = v3 + v2
    17.    //  ----------------------------
    18.    function Bezier(v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, _calculatePoints: int)
    19.    {
    20.      this.p0 = v0;
    21.      this.p1 = v1;
    22.      this.p2 = v2;
    23.      this.p3 = v3;
    24.  
    25.      if(_calculatePoints>0) CalculatePoints(_calculatePoints);
    26.    }
    27.    //  ----------------------------
    28.    // 0.0 >= t <= 1.0 her be magic and dragons
    29.    //public Vector3 GetPointAtTime( float t )
    30.    function GetPointAtTime(t : float) : Vector3
    31.    {
    32.      var u : float = 1f - t;
    33.      var tt : float = t * t;
    34.      var uu : float = u * u;
    35.      var uuu : float = uu * u;
    36.      var ttt : float = tt * t;
    37.  
    38.      var p : Vector3 = uuu * p0; //first term
    39.      p += 3 * uu * t * p1; //second term
    40.      p += 3 * u * tt * p2; //third term
    41.      p += ttt * p3; //fourth term
    42.  
    43.      return p;
    44.    }
    45.    //  ----------------------------
    46.    //where _num is the desired output of points and _precision is how good we want matching to be
    47.    function CalculatePoints(_num: int)
    48.    {
    49.      var _precision : int = 100;
    50.  
    51.      if(_num>_precision) Debug.LogError("_num must be less than _precision");
    52.  
    53.      //calculate the length using _precision to give a rough estimate, save lengths in array
    54.      length=0;
    55.      //store the lengths between PointsAtTime in an array
    56.      var arcLengths : float[] = new float[_precision];
    57.  
    58.      var oldPoint : Vector3 = GetPointAtTime(0);
    59.  
    60.      for(var p : int=1; p<arcLengths.Length; p++)
    61.      {
    62.        var newPoint : Vector3 = GetPointAtTime( parseFloat(p) / parseFloat(_precision) ); //get next point
    63.        arcLengths[p] = Vector3.Distance(oldPoint,newPoint); //find distance to old point
    64.        length += arcLengths[p]; //add it to the bezier's length
    65.        oldPoint = newPoint; //new is old for next loop
    66.      }
    67.  
    68.      //create our points array
    69.      points = new Vector3[_num];
    70.      //target length for spacing
    71.      var segmentLength : float = length/_num;
    72.  
    73.      //arc index is where we got up to in the array to avoid the Shlemiel error http://www.joelonsoftware.com/articles/fog0000000319.html
    74.      var arcIndex : int = 0;
    75.  
    76.      var walkLength : float=0; //how far along the path we've walked
    77.      oldPoint = GetPointAtTime(0);
    78.  
    79.      //iterate through points and set them
    80.      for(var i : int=0; i<points.Length; i++)
    81.      {
    82.        var iSegLength : float = i * segmentLength; //what the total length of the walkLength must equal to be valid
    83.        //run through the arcLengths until past it
    84.        while(walkLength<iSegLength)
    85.        {
    86.          walkLength+=arcLengths[arcIndex]; //add the next arcLength to the walk
    87.          arcIndex++; //go to next arcLength
    88.        }
    89.        //walkLength has exceeded target, so lets find where between 0 and 1 it is
    90.        points[i] = GetPointAtTime( parseFloat(arcIndex) / parseFloat(arcLengths.Length) );
    91.      }
    92.    }
    93. }
    and the test script I used (attach to an empty gameObject in a new scene) :
    Code (csharp):
    1. #pragma strict
    2.  
    3. var p0 : Vector3 = Vector3.zero;
    4. var p1 : Vector3 = Vector3.one;
    5. var p2 : Vector3 = new Vector3( 5, 4, 2 );
    6. var p3 : Vector3 = new Vector3( 8, 1, 0 );
    7.  
    8. var numPoints : int = 10;
    9.  
    10. var showInitialPoints : boolean = true;
    11.  
    12. function Start()
    13. {
    14.    if ( showInitialPoints ) ShowInitialPoints();
    15.  
    16.    var bezier : Bezier = new Bezier( p0, p1, p2, p3, numPoints );
    17.  
    18.    for ( var i : int = 0; i < bezier.points.Length; i ++ )
    19.    {
    20.      var go : GameObject = GameObject.CreatePrimitive( PrimitiveType.Sphere );
    21.      var tx : Transform = go.transform;
    22.    
    23.      tx.position = bezier.points[ i ];
    24.      tx.localScale = Vector3.one * 0.05;
    25.    }
    26. }
    27.  
    28. function ShowInitialPoints()
    29. {
    30.    ShowInitialPointAtPosition( p0 );
    31.    ShowInitialPointAtPosition( p1 );
    32.    ShowInitialPointAtPosition( p2 );
    33.    ShowInitialPointAtPosition( p3 );
    34. }
    35.  
    36. function ShowInitialPointAtPosition( pos : Vector3 )
    37. {
    38.    var go : GameObject = GameObject.CreatePrimitive( PrimitiveType.Sphere );
    39.    var tx : Transform = go.transform;
    40.    tx.position = pos;
    41.    tx.localScale = Vector3.one * 0.15;
    42. }
    Hope this now works for what you have planned. All the Best
     
  6. Griffo

    Griffo

    Joined:
    Jul 5, 2011
    Posts:
    698
    @alucardj
    WOW! Thanks for that really appreciated .. I'll take a look at using it later and I'll get back to you.
     
    AlucardJay likes this.
  7. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Someone's gotta be a jerk and suggest that you switch over to C# instead, if not for the intrinsic benefits of using a (debatably?) better language, then simply because it's far more popular, better supported, and easier to debug. If you keep on this route, you're going to continue to run into situations like this where you need to convert code from one language to another, again and again- I've never had to do the reverse.

    Today, I'm the jerk. Cheers.
     
    Kiwasi, Griffo and AlucardJay like this.
  8. AlucardJay

    AlucardJay

    Joined:
    May 28, 2012
    Posts:
    328
    Heh, I didn't want to be that jerk today, so thank you :D
     
    Griffo likes this.
  9. Griffo

    Griffo

    Joined:
    Jul 5, 2011
    Posts:
    698
    @Lysander
    I know I should have made that decision when I decided to go with .js sometime ago, I've grown to regret that decision.

    I've told myself after this project I'll go over to C#

    I already know some C# and have done a lot of converting in the past so shouldn't be to much of a hardship.
     
  10. Griffo

    Griffo

    Joined:
    Jul 5, 2011
    Posts:
    698
    Hi @alucardj
    Your code works great, but if I up the number of points, say to 100 for a smoother curve spaces start to show in the curve, I've attached a picture to show you whats going on, would you know why? Thanks.


    Screen Shot_00.jpg
     
  11. AlucardJay

    AlucardJay

    Joined:
    May 28, 2012
    Posts:
    328
    Beginning of the function CalculatePoints :
    Code (csharp):
    1. //where _num is the desired output of points and _precision is how good we want matching to be
    2. function CalculatePoints(_num: int)
    3. {
    4.     var _precision : int = 100;
    5.     if(_num>_precision) Debug.LogError("_num must be less than _precision");
    6. ....
    this was another optional parameter in the C# version
    Code (csharp):
    1. public void CalculatePoints(int _num, int _precision=100)
    So you'll have to work out how you want to handle this, via: global variable; duplicate function with second parameter; hard-coded value.

    probably go with a global variable that gets assigned when an instance of the class is created, e.g. :
    Code (csharp):
    1. var p3 : Vector3;
    2. var precision : int;
    3.  
    4. function Bezier( v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, _calculatePoints: int, precision: int )
    5. {
    6.    ....
    7.    this.p3 = v3;
    8.    this.precision = precision;
    9.  
    10.    if ( _calculatePoints > 0 ) CalculatePoints( _calculatePoints );
    11. }
    or you could be really bodgy :
    Code (csharp):
    1. function CalculatePoints(_num: int)
    2. {
    3.    // replace
    4.    //var _precision : int = 100;
    5.    //if(_num>_precision) Debug.LogError("_num must be less than _precision");
    6.    // with
    7.    var _precision : int = ( _num < 100 ? 100 : _num ); // if over 100, use numPoints
    8.    if(_num>9000) Debug.LogError("_num is over 9000!"); // waaay too many points
    9.    ....
    10. }
    What you implement is your personal choice.
     
    Griffo likes this.