Script translation

Could anyone translate this script from C# to JS? If this is too hard/would take to long for the community, tell me roughly what I need to do.

using UnityEngine;
using System.Collections;

public class SimpleCity : MonoBehaviour
{
    public Transform player;

    public Transform[] blocks;
    public Transform[] bases;
    public Transform[] floors;
    public Transform[] roofs;

    public int blockXNum = 10;
    public int blockZNum = 10;
    public float blockSpan = 10f;

    public int buildingXNum = 4;
    public int buildingZNum = 2;
    public float buildingSpan = 10f;

    GameObject cityRoot;

    int numBlocks;
    int numBuildings;

    float[] cardinals = { 0, 90, 180, 270 };

    bool building;

    void Start()
    {
        StartCoroutine(Generate());
    }

    IEnumerator Generate()
    {
        building = true;

        GameObject gPlayer = GameObject.FindGameObjectWithTag("Player");

        if (gPlayer)
            gPlayer.SetActiveRecursively(false);

        if (cityRoot)
            Destroy(cityRoot);

        cityRoot = new GameObject("CityRoot");

        float blockXSize = buildingXNum * buildingSpan;
        float blockZSize = buildingZNum * buildingSpan;

        float blockXOffset = (((blockXNum - 1) * blockSpan) + ((blockXNum - 1) * blockXSize)) * 0.5f;
        float blockZOffset = (((blockZNum - 1) * blockSpan) + ((blockZNum - 1) * blockZSize)) * 0.5f;

        Vector3 blockPos = new Vector3(-blockXOffset, 0, -blockZOffset);

        for (int x = 0; x < blockXNum; ++x)
        {
            for (int z = 0; z < blockZNum; ++z)
            {
                CreateBlock(blockPos);
                blockPos.z += blockZSize + blockSpan;
                yield return new WaitForEndOfFrame();
            }

            blockPos.x += blockXSize + blockSpan;
            blockPos.z = -blockZOffset;
        }

        if (player)
        {
            if (gPlayer)
            {
                gPlayer.SetActiveRecursively(true);
                gPlayer.transform.position = new Vector3(0f, 1f, 0f);
                gPlayer.transform.rotation = Quaternion.identity;
            }
            else
            {
                Transform p = (Transform)Instantiate(player, new Vector3(0f, 1f, 0f), Quaternion.identity);

                if (p)
                {
                    Camera.main.transform.position = new Vector3(0f, 1.5f, 0f);
                    Camera.main.transform.rotation = Quaternion.identity;
                    Camera.main.transform.parent = p;
                }
            }
        }

        building = false;
    }

    void CreateBlock(Vector3 position)
    {
        Transform block = null;

        if (blocks.Length > 0)
        {
            block = (Transform)Instantiate(blocks[Random.Range(0,blocks.Length)], position, Quaternion.identity);
            block.name = "Block" + ++numBlocks;
        }
        else
        {
            block = new GameObject("Block" + ++numBlocks).transform;
            block.position = position;
        }
        
        block.parent = cityRoot.transform;

        float blockXScale = ((buildingXNum * buildingSpan) + blockSpan) * 0.1f;
        float blockZScale = ((buildingZNum * buildingSpan) + blockSpan) * 0.1f;

        block.localScale = new Vector3(blockXScale, 1, blockZScale);

        float buildingXOffset = ((buildingXNum - 1) * buildingSpan) * 0.5f;
        float buildingZOffset = ((buildingZNum - 1) * buildingSpan) * 0.5f;

        Vector3 buildingPos = new Vector3(position.x - buildingXOffset, 0, position.z - buildingZOffset);

        for (int x = 0; x < buildingXNum; ++x)
        {
            for (int z = 0; z < buildingZNum; ++z)
            {
                CreateBuilding(buildingPos, block);
                buildingPos.z += buildingSpan;
            }

            buildingPos.x += buildingSpan;
            buildingPos.z = position.z - buildingZOffset;
        }

        block.gameObject.AddComponent("CombineChildren");
    }

    void CreateBuilding(Vector3 position, Transform block)
    {
        Vector3 curPosition = position;

        ++numBuildings;

        Transform c_parent = null;

        if (bases.Length > 0)
        {
            Transform b = (Transform)Instantiate(bases[Random.Range(0, bases.Length)], curPosition, Quaternion.AngleAxis(cardinals[Random.Range(0,cardinals.Length)], Vector3.up));
            b.name = "Base" + numBuildings;
            b.parent = block;
            c_parent = b;
        }

        if (floors.Length > 0)
        {
            int numFloors = Random.Range(1, 10);

            for (int i = 0; i < numFloors; ++i)
            {
                curPosition.y += 4;
                Transform f = (Transform)Instantiate(floors[Random.Range(0, floors.Length)], curPosition, Quaternion.identity);
                f.name = "Floor" + numBuildings + "_" + i;
                f.parent = c_parent;
                c_parent = f;
            }
        }

        curPosition.y += 4;

        if (roofs.Length > 0)
        {
            Transform r = (Transform)Instantiate(roofs[Random.Range(0, roofs.Length)], curPosition, Quaternion.AngleAxis(cardinals[Random.Range(0, cardinals.Length)], Vector3.up));
            r.name = "Roof" + numBuildings;
            r.parent = c_parent;
        }
    }

    void OnGUI()
    {
        if (building)
        {
            GUILayout.Label("Building...");
        }
        else
        {
            //public int blockXNum = 10;
            GUILayout.BeginHorizontal();
            GUILayout.Label("Block X Num: ");
            blockXNum = System.Int32.Parse(GUILayout.TextField(blockXNum.ToString(), GUILayout.Width(50)));
            GUILayout.EndHorizontal();

            //public int blockZNum = 10;
            GUILayout.BeginHorizontal();
            GUILayout.Label("Block Z Num: ");
            blockZNum = System.Int32.Parse(GUILayout.TextField(blockZNum.ToString(), GUILayout.Width(50)));
            GUILayout.EndHorizontal();

            //public float blockSpan = 10f;
            GUILayout.BeginHorizontal();
            GUILayout.Label("Block Span: ");
            blockSpan = (float)System.Double.Parse(GUILayout.TextField(blockSpan.ToString(), GUILayout.Width(50)));
            GUILayout.EndHorizontal();

            GUILayout.Space(20);

            //public int buildingXNum = 4;
            GUILayout.BeginHorizontal();
            GUILayout.Label("Building X Num: ");
            buildingXNum = System.Int32.Parse(GUILayout.TextField(buildingXNum.ToString(), GUILayout.Width(50)));
            GUILayout.EndHorizontal();

            //public int buildingZNum = 2;
            GUILayout.BeginHorizontal();
            GUILayout.Label("Building Z Num: ");
            buildingZNum = System.Int32.Parse(GUILayout.TextField(buildingZNum.ToString(), GUILayout.Width(50)));
            GUILayout.EndHorizontal();

            //public float buildingSpan = 10f;
            GUILayout.BeginHorizontal();
            GUILayout.Label("Building Span: ");
            buildingSpan = (float)System.Double.Parse(GUILayout.TextField(buildingSpan.ToString(), GUILayout.Width(50)));
            GUILayout.EndHorizontal();

            GUILayout.Space(20);

            if (GUILayout.Button("Generate"))
                StartCoroutine(Generate());
        }
    }
}

I will not translate the code for you, that isn’t how UA works, but I can give you a basic guide to converting C# to js. This is far more encompassing than what you need to translate your script.

  1. Change using to import

  2. You can either remove the class declaration, or you can do this:

      public class SimpleCity extends MonoBehaviour {
    
  3. Rules for Variable declarations:

*  You can leave the access modifier.  `public` isn't needed in js but it doesn't hurt.  
* Remove the type (that is the class or struct before the name of the variable).  It should be the first word after public.
*  Add `var` before the variable name.
*  After the variable name (but before the "=" sign) add "`: ClassName`"
* Leave anything after the "=" sign.
*  Example: `public Transform myTransform;` **becomes** `public var myTransform : Transform;`
*  Example 2: `private int internalValue = 128` **becomes** `private var internalValue : int = 128;`
*  I'm lying some because the compiler can guess the type on the second one, but if you follow these rules you won't have any problems.
* Special Cases:
* In C# true/false values are called `bool`.  In js, you must change the type to `Boolean`.
*  In C#, an "f" must be appended to a decimal to make it a float litteral i.e. `float someVal = 2.0f`.  In js, remove the "f".  

    *Note* the same rule applies for some other number types such as long.  Remove the appended character.
*  I don't know if you can do hexadecimal literals in js.  If you see one in C#, just turn it into its decimal equivalent.
* C# generics are defined like this: `System.Collections.Generic.List<T>()`.  In js, you need to add a period before the "<"
*  Delegates are difficult to do in js.  1. You cannot declare events in js.  You can add listeners to the event in js, but you cannot create the event.  You cannot create a specific delegate, instead you can create a generic function type. `public Action myDel;` **becomes** `public var myDel : Function;`
*  There are probably a few more I can't think of right now, but this should be most of them.
  1. Properties are very bizarre in js. There are not any in the above script, but the syntax is very strange:

        //C#
        public Class myProperty {
                 get {
                          return someValue;
                 }
                 set {
                          someValue = value;
                }
        }
    

    in js the become:

        //js.
        class SomeClass extends MonoBehaviour {  //Must be declared in a class.
                   public get MyProperty : SomeClass {
                             return someValue;
                   }
                   public set MyProperty : void { 
                             someValue = value;
                   }
         }
    
  2. Functions. Functions are fairly straight forward to change from C# to js.

* Leave the access modifier alone if there is one.
* Replace the return type with `function` example: remove `void` and replace it with `function`
* following the "()"s, add "`: returnType`" This is the value that you removed above. You actually won't need it most of the time, but it is helpful for writing more explicit code.
* if there are any parameters in the function (thats the variables between the parentheses, remove the type from the beginning and put it after as above example `(int damage , float range)` __becomes__ `(damage : int , range : float)`
* So the full change might look like: `public void ApplyDamage (int damage) { `.  ***Becomes*** `public function ApplyDamage (damage : int) : void {`
  1. Coroutines. There isn’t that much to do for coroutines. Remove the StartCoroutine() from any C# script so that just the function call remains. Remove the return after any yield statements.

  2. foreach loops. The foreach becomes for and the inside is changed like every other variable. Add var before it and use a colon + the type after it.

  3. Anonymous functions. C# anonymous functions are done through lambda expressions usually.

        //C#
        Action myDel = () => Debug.Log("Anonymous Method");
        //or
        //Action myDel = delegate() { Debug.Log("Anonymous Method"); };
    

In js, they are done as such

        //js
        var myFunction : Function = function() { Debug.Log("Anonymous Function"); };

I think that pretty much covers all of it that you will frequently come across. I don’t know how to do LINQ in js so avoid that if you can. If you come across anything else then I will help you translate it. Hopefully this can become a document for anyone who needs to translate from one language to the other.

Then it wouldn’t be a Spam Sausage Egg Biscuit, now would it?!?

(Edited spam - Almo)