Head First into Unity with UnityScript

From Unify Community Wiki
Revision as of 20:48, 10 January 2012 by NCarter (Talk | contribs)

Jump to: navigation, search

Written by Tonio Loewald (a.k.a. podperson)



Unity's "JavaScript" vs. the JavaScript you probably know

Use #pragma strict

#pragma strict</javascript>
=== Use enum ===
<syntaxhighlight lang="javascript">enum WeaponType { pistol, rifle, launcher}
var type : WeaponType = WeaponType.pistol;</javascript>
=== It's different ===
Although Unity's JavaScript tries to follow the ECMAScript standard closely, it varies in many ways from other implementations of JavaScript that are based on the same standard.  It is perhaps most similar to Microsoft's [http://msdn.microsoft.com/en-us/library/72bd815a.aspx JScript], especially in that both are .NET languages.  However, Unity's version was developed independently and there are a number of differences between the two.
=== It's fast ===
'''Unity JavaScript is compiled''' (and fast, which is excellent) but not so dynamic as JavaScript in browsers (which is interpreted).
Even so, as things stand, "real" JavaScript is still about '''two orders of magnitude''' slower than Unity's JavaScript, even on Squirrelfish Extreme.
=== The var keyword is required ===
In JavaScript, if you don't use the '''var''' keyword when defining a variable, that variable is scoped as a global one.
<syntaxhighlight lang="javascript">
function DoSomeStuff() {
   x = 3;
To avoid this ambiguity for long-time JS users, the '''var''' keyword is required when defining variables, and that automatically restricts the variable's scope to the current scope.
<syntaxhighlight lang="javascript">
function DoSomeStuff() {
   var x = 3;
=== UnityScript is classical, not prototypal ===
<syntaxhighlight lang="javascript">// Foo.js
var foo = "hello, world"
function doEet () {
  // does nothing, intended to be overridden
Here's a subclass:
<syntaxhighlight lang="javascript">// PrintingFoo.js
class PrintingFoo extends Foo {
   function doEet() {
    print( foo );
==== Virtual functions can be used to override functions ====
In Unity's javascript you can create virtual functions.
<syntaxhighlight lang="javascript">
class Foo
     virtual function DoSomething () 
         Debug.Log("from base class");
class SubFoo extends Foo
     virtual function DoSomething() 
          Debug.Log("from sub class");
var foo : Foo = new SubFoo();
<syntaxhighlight lang="javascript">
class SubFoo extends Foo
     virtual function DoSomething()
          Debug.Log("from sub class");
var foo : Foo = new SubFoo();
==== Consider Writing Mixins and Helpers Instead of Subclassing ====
<syntaxhighlight lang="javascript">/* Foo.js */
var bar : Bar;
function Start(){
  bar = gameObject.GetComponent(Bar);
function doEet(){
  // do my own thing
  if( bar ){
/* Bar.js */
  function doEet(){
    // do something special
=== It's String (Mono's String class) and not string ===
var x : String;
'''Most''' of the string functionality you know and love from JavaScript is still there, but it's differently capitalized.
'''A note on how to "Split" Strings'''
You have to use the following syntax for splitting with characters :
<syntaxhighlight lang="javascript">
var qualifiedName = "System.Integer myInt";
var name = qualifiedName.Split(" "[0]);
=== You Must Declare Variables Before Using Them ===
'''You must declare variables before using them.'''
<syntaxhighlight lang="javascript">a = "fred"; // works in JavaScript (a is treated as a global), error in Unity</javascript>
<syntaxhighlight lang="javascript">var a = "fred"; // a is now a string variable containing 'fred'
b = "wilma";
c = "barney";
c = 17;</javascript>
a) You can (and often should) explicitly scope variables as private, public, etc. If you leave out the scope, public is the default.
<syntaxhighlight lang="javascript">var a; // a is dynamically typed;
a = "fred"; // works
a = 5; // works</javascript>
=== Method (and Class) Names are Generally Capitalized ===
'''Method (and class) names are generally capitalized, except when they aren't'''. (It's confusing.) Basically, Unity's JavaScript is living in a .NET naming convention world (where methods are CamelCase and properties are camelCase), but is also trying to be like JavaScript (which, like C, is strongly biased towards lowercase and camelCase for everything).
=== Lots More Types, Two Kinds of Array, No Object Syntax Sugar ===
<syntaxhighlight lang="javascript">var a = new Object(); // works
native arrays (which are not associative or dynamic):
<syntaxhighlight lang="javascript">var a = [1, 2, 3];
If you want to make an array of a specific type:
<syntaxhighlight lang="javascript">public var friendsOfCarlotta : Transform[];</javascript>
<syntaxhighlight lang="javascript">var a = new Array();
You can convert Javascript Arrays to native arrays (which are faster but less flexible) using ToBuiltIn(ArrayType), e.g.:
var b = a.ToBuiltin(float);</javascript>
'''Integer types (including int, uint32, etc.)''':
'''Unity has many built-in classes (e.g. Vector3)''':
b) Unity's internal arrays are far less flexible than JavaScript's arrays or objects. However, various collection types such as List, Dictionary, Queue and so on are available. Internal arrays always have the advantage of the best speed.
=== Each .js File Implements A Class (By Default) ===
<syntaxhighlight lang="javascript">var x : int;
function y(){}</javascript>
<syntaxhighlight lang="javascript">class Foo extends MonoBehaviour {
  var x : int;
  function y(){}
But, you can also declare more than one class in the same file, which is particularly useful where you need utility classes which aren't descended from MonoBehaviour.
<syntaxhighlight lang="javascript">class ButtonState {
  var currentState : int;
  var offset : Vector2;
'''It's important to understand that when you write a behavior script in JavaScript you are actually writing a class implementation''', where:
<syntaxhighlight lang="javascript">public name : String; // when you drag the behavior onto a gameobject, these values will be visible and editable
function Update(){
function Bar(){
'''Calling Inherited Methods'''
'''super()''' is the inherited constructor, and '''super''' is "this" treated as a member of the superclass (so super.foo() calls the superclass's version of foo).
=== Semicolons Are Not Optional ===
<syntaxhighlight lang="javascript">var foo = 3 // OK in JavaScript but an error in Unity
foo += 17</javascript>
=== Math is Mathf; Math.abs is Mathf.Abs ===
== Using Mono (.NET) ==
The UnityScript runtime environment makes extensive use of Mono (the open source clone of .NET). In fact, UnityScript is implemented in Boo, which is a language that runs on the Mono virtual machine and compiles to its native code. Many of a typical JavaScript runtime environment (e.g. String and Math libraries) are provided by Mono. You can tell when you're using Mono classes because their capitalization convention is '''CamelCase''' for class names (e.g. String) and methods (e.g. Mathf.Sin()) but camelCase for properties vs. JavaScript's which is '''camelCase''' for everything.
In order to use the Mono libraries it's most convenient to '''import''' them, e.g.
<syntaxhighlight lang="javascript">import System;
import System.IO;</javascript>
Otherwise you need to specify the full namespace when calling functions, e.g. System.IO.File.Open instead of just File.Open. To find documentation on the libraries, the best place is probably http://msdn.microsoft.com/en-us/library/w0x726c2(v=VS.90).aspx  The Mono documentation (http://docs.go-mono.com/) is technically more accurate for what's included with Unity, but is fairly incomplete at this time. 
=== Mono Types ===
When a Mono function requires a '''char''' as an input, you can obtain one by simply indexing a string. E.g. if you wanted to pass the lowercase a as a char, you'd write:
<syntaxhighlight lang="javascript">"a"[0]</javascript>
<syntaxhighlight lang="javascript">var s : String = "Whatever_it_may_be";
When working with Javascript Arrays (which are more flexible than builtins) you can easily convert them to the faster builtin arrays using ToBuiltIn(Type):
<syntaxhighlight lang="javascript">fastArray : SomeType[] = monoArray.ToBuiltin(SomeType);</javascript>
UnityScript has access to generics (like in C#), so when using dynamically-sized arrays, you're better off using List instead of Javascript arrays. There's essentially no reason to use Javascript Arrays; Lists are faster and more functional in all cases. If you need an array of mixed types, you can use a List of Object, and then cast Object to the appropriate type when retrieving values. The syntax for generics in UnityScript is nearly identical to C#, except for an extra "." before the <> part. For example, "var myList = new List<int>();" in C# would become "var myList = new List.<int>();" in UnityScript.
=== Using 3rd Party .NET Libraries ===
== Debugging ==
Unity also generates useful '''warnings''' (with a "yellow ! icon") e.g. telling you a variable you've declared isn't used anywhere. Striving to write code that never generates warnings is a very useful habit.
The '''print()''' function will produce messages in the status bar and console, but only in MonoBehaviour classes. It's better to use Debug.Log("insert message here");. This does the same thing as print(), but everywhere. You can also use Debug.LogWarning and Debug.LogError to generate your own warning and error messages.
'''Debug.Break();''' pauses the game in the editor at that exact point. It's very useful if you want to examine the state of objects when a particular situation occurs (e.g. you're trying to figure out what's going wrong when a particular object collides with another).
[[Category: Tutorials]]
Personal tools