Unity3D - Syntax Differences in C# and Javascript |
|
The purpose of this answer is to provide a single point of reference for the syntactical differences between C# and JS. It is mainly for people who have already made their decision as to which language to use, and might need to know the differences (for instance, to translate a script from one language to another). |
|
Unity Script Directives Unity has a number of Script Directives, for example, AddComponentMenu. The syntax is: Type names A couple of the basic types are spelt differently in pure Unity C#:
Variable declaration Variable declaration is different, including access and type specification: // C#: the type is always stated when declaring a variable: // Javascript - type specification is not necessary: Variables with dynamic type resolution In Javascript only, variables can have an unspecified type. This only occurs if you do not assign a value while declaring the variable. For example: // Javascript: Performance is slower with dynamically typed variables, and you can run into casting problems. Multi-dimensional array declaration not supported Unity's Javascript doesn't support the syntax for declaring multi-dimensional built-in arrays. Eg: // C#: // Javascript: Character literals not supported Unity's Javascript seems to be missing the syntax to declare character literals. This means you need to get them implicitly by referencing a character index from a string. For example:// C# // Javascript: Class declarations You can define classes in Javascript, in a similar way to C#. Here's an example of a class which inherits from MonoBehaviour // Javascript example var myVar = 1; function Start() { // C# example: public int myVar = 1; void Start() { However in Javascript, if you're inheriting from MonoBehaviour, you don't need to write a class body at all (see the next section). You can also write classes which do not inherit from anything, however you can't place scripts like this on Game Objects - you have to instantiate them with the 'new' keyword: // Javascript example var myVar = 1; // constructor: // C# example: public int myVar = 1; // constructor: If you are inheriting from MonoBehaviour, you should not use constructors or destructors. Instead, use the Event handler functions "Start", "Awake" and "OnEnabled".
Implicit Class declarations Unity's Javascript has a feature whereby if you do not declare any class body, it is automatically implemented for you. For example, a script which contains only variables and functions (and no explicit class declaration) is automatically implemented as: // Your javascript is converted to (approximately) This means that any Javascript script that you write without an explicit class body, automatically inherits from MonoBehaviour, and is therefore a component which can be attached to a GameObject (which is usually what you want!). Limited interface support While Unity's Javascript does support inheritance and interfaces, it has the very limiting caveat that you can either inherit your class from an existing class, or declare one interface. Eg: // C# // Javascript - only one allowed: // or Generics The C# syntax supports "Generics" which allows you to use classes and methods which do not specifically declare a type. Instead, the type is passed as a parameter when calling the method or instantiating the class at runtime. These now work in both Unity and Unity iPhone (since v1.6). .Net comes with some useful Generic classes such as the List and Dictionary, and Unity's own API has some generic functions which remove the need for some of the verbose casting which would otherwise be necessary in C#. For example: // In Javascript, the "GetComponent" function returns an object, which is automatically cast by Javascript to the correct type // In C#, without the Generic version of "GetComponent" we'd have to cast it ourselves (yuck): // But instead, we can use the generic version provided by the Unity API, like this: For a more complete definition of Generics: MS Introduction to C# Generics The Foreach keyword C# Iterators use foreach instead of for. Also notice the variable declaration within the for/foreach statement. C# requires the type of the item contained in the list to be explicitly declared. // Javascript // C# The New keyword In Javascript, you can create a new instance of an object or struct without using the 'new' keyword. In C#, using "new" is mandatory. // Javascript: // C# Yield in Unity C# versus Unity Javascript Although Unity's documentation does (briefly) cover the syntax differences in using Yield at Writing C# Scripts(Step 4), there is also a Unity Answer that covers How do I Use Yield in C#, which has a more detailed explanation. In addition, the answer by equalsequals has a link to a Coroutine Tutorial that is worth checking out.Unity's Yield has additional capabilities over .NET C# Yield The above paragraph covered the differences in Unity's C# versus Javascript syntax. However, I think that it's worth explaining that the behavior of Unity's Yield statement (in both C# and Javascript), has some additional features not in Microsoft's .Net C# behavior. Basically, Unity has added the YieldInstruction (and child classes such as WaitForSeconds) to Yield. These classes give Yield the ability to temporarily pause the function, until a condition is met. If it has zero parameters, it pauses for a single frame. If it has a parameter of WaitForSeconds: then it pauses for some number of seconds. If the parameter is another Coroutine, then it pauses until that Coroutine finishes. Yield only works this way inside a Coroutine. To start a Coroutine in C#, you use StartCoroutine, whereas it is automatically called in Javascript. For a good explanation of how Coroutines and the main routine interact, see Duck's Answer Casting Javascript automatically casts from one type to another, where possible. For example, the "Instantiate" command returns a type of "Object": // in Javascript, there's no need to cast the result of "Instantiate" provided the variable's type is declared: // in C#, both the variable and the result of instantiate must be declared: Also, see Murcho's answer for more information about casting, including why you would want to use the second casting method listed. Properties with Getters/Setters In C#, it is possible to define special functions that can be accessed as if they were variables. For instance, I could say foo.someVar = "testing";, and under the hood, there are get and set functions which process the argument "testing" and store it internally. But - they could also do any other processing on it, for instance, capitalizing the first letter before storing it. So you're not just doing a variable assignment, you're calling a function that sets the variable, and it can do - whatever functions do. I'm not going into the syntax here, this answer is long enough :) But here are two links:
Changing struct properties / by value vs by reference This is actually a bit more than a syntactical difference but nevertheless fits here quite well: The following code does work in JavaScript/UnityScript but not in C#: transform.position.x = 3; The reason is because transform.position really is not just a public variable but a property, so it's actually returned by a method call - and that happens "by value" for structs (Vector3 is a struct and not a class - for performance reasons). So, to achieve the same in C#, you have to write: Vector3 pos = transform.position; Function/Method definitions First of all, terminology - Javascript uses the term "Function", while C# calls these "Methods". They mean the same thing, and most C# coders understand the term "Function". Javascript functions are declared with the keyword function before the function name. C# Method declarations just use the return type, and the method name. The return type is often "void" for common Unity events. Javascript functions are public by default, and you can specify them as private if required. C# methods are private by default, and you can specify that they should be public if required. In Javascript, you can omit the parameter types and the return type from the declaration, but it's also possible to explicitly specify these (which is sometimes necessary if you run into type ambiguity problems). Javascript function examples: // a common Unity monobehaviour event handler: // a private function: // a public function with a return type. And the equivalent C# methods examples: // a common Unity monobehaviour event handler: // a private function: // a public function with a return type. |