Unity

Writing Games With Unity 3D in JavaScript and C# – Part 1

by on April 29, 2013 3:40 pm

Unity is a development environment for creating professional-level games. It is built on top of MonoDevelop, and utilizes it to achieve the deployment of the same code to many platforms. Unity comes in two versions, but this post will focus on the free version with no add-ons.

The free version (which is the one I use) supports out-of-the-box deployment to Mac, Windows, Linux, Web, and Google Native (a Chrome technology for deploying without plugins). Additionally (as of this writing), for $400 each free (free price announced 5/21/13) deployment to Android and iOS (both iPhone and iPad) is available. If you are part of a team, a team license that adds collaboration capabilities to share assets is available for $500. The free version supports multiplayer games, physics, 3D audio, animation, Direct3D 11, shaders, light mapping, and terrains among other useful features. If you happen to be an XBox360, PS3, or Wii developer, you can deploy to those platforms as well, although I don’t know the licensing details.

Unity Pro is a $1,500 license and extends Unity with many high-end capabilities like level of detail (LOD), automatic path finding, high end audio filters, video playback and streaming, IK animation, 3D textures, realtime shadows, and many other professional features. The Android and iOS licenses for the pro version are $1,500 apiece and support features that the $400 versions do not.

Introduction to KeyShot

My creation, KeyShot, came about when I showed the guys I work with a game I created following the excellent free tutorials available from the Walker Boys Studio. There are 70+ hours of video training available covering the basics, writing code in JavaScript, and step-by-step instructions on how to create four different genres of games. KeyShot is based on the second game in this tutorial series, although it extends it a lot. Additionally, I converted all of the JavaScript classes to C#. The project includes the same functionality for both languages, which are easily swappable inside Unity.

So, I was asked if I could make a game for the Kansas City Developer ConferenceThe reasons for this are currently shrouded in secrecy, and will only be revealed on this blog after the conference is over. :) Incidentally, after the conference, you can come back to this blog to download the zipped project and try it out for yourself. You can now check it out on GitHub.

KeyShot is a (very) basic Galaga clone. The objective is to get the highest score possible in 30 seconds without running out of lives. The top 10 scores are saved, which gives players motivation to beat the high score.

KeyShot_Gameplay

Implementation

I’m going to cheat a bit here and send you straight to the tutorials to find out how to implement the base of the game. The Walker Boys Studio does a fantastic job of covering these details in their video tutorials, so if you are interested, head on over here for some great instruction!

Features that I will cover that aren’t in the Walker Boys Tutorial:

  • Using multiple cameras to implement a background logo
  • JavaScript and C# implementations, including how to use nested generics in JavaScript and how to call C# scripts from JavaScript
  • How to use 3D models with axes that don’t line up with normal “Y-up” Unity standards
  • Implementing a high score table using PlayerPrefs (check it out in Part 2!)
  • How to implement a dialog with text fields to collect user data (check it out in Part 2!)
  • How to implement cheat codes in Unity (check it out in Part 2!)

Using multiple cameras to implement a background logo

Alright, let’s find out how to display that Keyhole logo behind the playfield.

1. From the Assets –> Import New Asset… menu, I selected the PNG to import. This pulls the asset into Unity and makes it available for use.

KeyShot_Asset_Import

KeyShot_Import_Logo

2. Next, load Scene1 by double-clicking on it:

KeyShot_Scene1

To get the image behind the other assets, we will use a layer and a camera.

3. In the upper right of the Unity window, there is a Layers drop down. Select “Edit Layers” from that drop down. You’ll see a list of Tags, then Builtin Layers, then User Layers.

4. If you click to the right of User Layer 8, you can set a name for that layer. I chose Background Image for my layer name (possibly a confusing choice…but we’ll work with it).

KeyShot_Background_Image_Layer

5. In the Hierarchy drop-down, use the Create menu and select “GUI Texture.” Name it Background Image.

6. Drag the logo asset to the Texture property of the GUI Texture (in order to tell it that we want to use the logo as the texture).

7. Now select the Background Image GUI Texture in the Hierarchy to see its property sheet. To get the size correct, use the Pixel Insert fields. I looked at the properties of the image to find it is 512×128. To center the image, set X to -256 and Y to -64, then set width to 512 and height to 128.

8. Set the Layer of the Background Image to…Background Image.

KeyShot_GUI_Texture

To display the image properly, we need to create a second camera.

9. Click on “Main Camera” in the Hierarchy view. Then select the “Create” drop down on the Hierarchy and choose “Camera.” I named mine Background Camera. By default, the new camera will have the same viewport as the camera that was selected when we created our new one, so we don’t have to adjust that.

10. Now click on the Background Camera and set the Culling Mask of the Background Camera to use only the Background Image layer.

To do this, click on the Culling Mask, select Nothing. Then select Background Image. At this point I also set the background color of the Background Camera to match the background of the Keyhole logo.

11. Finally, we need to tell the main camera to ignore the Background Image layer.

To do this, click on the Main Camera, then the Culling Mask.
Un-select the Background Image layer.

KeyShot_Create_Background_Camera

KeyShot_Background_Camera

It is quite a few steps, but the results are pretty cool, with a watermark showing behind all the other elements in the game.

JavaScript and C# Implementations

Including how to use nested generics in JavaScript and how to call C# scripts from JavaScript

In the Walker Boys tutorials, they chose JavaScript to code all of their games, which works just fine. However, if you’re like me, you might like to code in C# rather than JavaScript. So, I converted all of the Javascript to C# and I’ll include both in the source code for the project, which again will be available after Part 2.

There are a few things to point out when choosing the language for your games in Unity:

  1. If you code in JavaScript, it will be converted to C# before compilation. This is why you must use #pragma strict when coding in JavaScript. Each JS file is implemented as a C# class with the same name as the JS file. So, why not go with C# since that is the target language anyway?
  2. You can call C# from JS or vice versa, but not both in the same project. This is because one set of files is compiled before the other.  The files in the special folder “Standard Assets” are compiled before the files that are located anywhere else. In my project, I have all of my C# files in the Standard Assets folder, and all of my JS files in the base folder. This means I can call C# from JS in my project. For tutorial purposes I don’t, but I’ll give an example so you know what to do if this is necessary for your project. Note for this example all of my JS files end with 2, whereas their equivalent C# files have the same names but without the 2. To call the C# version instead of the JS version, just remove the 2s from scriptSceneManager2 and scriptAstroid2. Once the files are located in the proper places, it really is that easy.
    function OnTriggerEnter(other:Collider) {
        if (other.gameObject.tag == scriptSceneManager2.TAG_ASTROID) {
            var astroidScript = other.GetComponent(scriptAstroid2);
            astroidScript.ResetPosition();
        }
        ...
    }
          
  3. Generics in JavaScript use a funky syntax. This can be especially frustrating with nested generics such as the following:
    C#: List<KeyValuePair<int, string>> highScores = new List<KeyValuePair<int, string>>();
    JS: var highScores:List.<KeyValuePair.<int, String> > = new List.<KeyValuePair.<int, String> >();

    Take special note of the space between the closing brackets in JS, because if this is not present it will not compile.

  4. The type name of string is “string” in C# and “String” in JavaScript.
  5. You can make C# calls directly inside your JavaScript code, and often you have to. This is just another reminder that JS is converted to C# at compile time.
  6. Even though the conversion is made, the JS syntax is checked before the conversion. Therefore, scope is different in JS than C#. For example:C#:
        for (int i = 0; i < 10; i++) {
            print("i = " + i);
        }
    
        // i was only in scope during the for loop, so i must be redefined for the next for loop
        for (int i = 0; i < 10; i++) {
            print("another i loop. i = " + i);
        }
    

    JS:

        for (var i:int = 0; i < 10; i++) {
            print("i = " + i );
        }
    
        // in JS, once a variable is defined it stays defined. Scope is at the function level
        for (i = int 0; i < 10; i++) {
            print("another i loop. i = " + i);
        }
          
  7. JavaScript coerces a lot of values that C# will not, even in JS strict mode. Coercion (automatically converting from one type to another) causes a lot of side effects that can cause bugs that are not easy to find. For this reason, when coding in JS, I pay very close attention to the specified parameter types and ensure that I specifically use the types that are expected.
  8. JavaScript functions are always accessible, but C# obeys scope rules. If one script is going to call another, in C# make sure those methods that will be called by other scripts are public.

How to use 3D models with axes that don’t line up with normal “Y-up” Unity standards

When importing 3D models from other programs (Blender, 3Ds, Lightwave, etc), many of these models do not have their axes set with Y being “up”, which is what Unity expects. Using these models can be seemingly impossible until you learn how to wrap them so that their axes are not getting in the way.

You can read this and look at the pics, but it was a bit confusing for me: http://docs.unity3d.com/Documentation/Manual/HOWTO-FixZAxisIsUp.html

So, I’ll show you with some screen shots and discussion. Follow along now, then after Part 2 is release (with the source code), you can try it out.

1. Create an empty GameObject

KeyShot_Create_GameObject

2. Rename the GameObject “Key2” and drag it to be a child of prefabPlayer. Since I’m duplicating my Key to illustrate how to do it, I’ll leave the current Key alone and show you how to match what is there.

KeyShot_Key2_Created

Note how Unity places the object in the scene at a fairly random location. Change the location (i.e. the Transform) to 0, 0, 0 so it will be fairly close to the existing key. Now drag the Key_B mesh and matPlayer to the Key2 object.

You’ll end up with something like this:

KeyShot_Key2_2

Note that the new key is in its default orientation, which has the rotation wrong. Since we have a GameObject holding the mesh instead of adding it directly to the prefabPlayer object, we can reset the rotation of the Key2 GameObject without affecting the rotation of the prefabPlayer (which would create havoc-like bullets shooting the wrong way, “left” and “right” moving anything but left and right, and so on).

Setting the Y and Z rotation of the Key2 GameObject to 90 and 90 respectively (for this particular mesh) corrects the orientation of the key so we have an upright, side-viewed key that we can use for the player.

KeyShot_Key2_3

I hope you have enjoyed Part 1 of this post. Definitely feel free to ask any questions you may have and I’ll try to answer as best I can.

Also, check out Part 2 of this series to download the project and check out high scores, dialogs, and cheat codes, and Part 3 for Mobile development!

— John Boardman, asktheteam@keyholesoftware.com

  • Share:

5 Responses to “Writing Games With Unity 3D in JavaScript and C# – Part 1”

  1. […] Part 1: http://keyholesoftware.com/2013/04/29/writing-games-with-unity-part-one/ […]

  2. […] will be building on Part 1 and Part 2 in this Unity 3D tutorial – so if you haven’t read them yet, head on over […]

  3. […] back for Part 2! We covered the following topics in Part 1 of this Unity 3D […]

  4. Phil says:

    great article. I’m a Unity 3d newbie and I’m trying to follow your script using the new GUI tools 4.6. I’m finding that your steps no longer follow the selections available in Unity. my eyes are crossing trying to translate the steps in your article to creating a watermark layer in the new GUI.

    any chance of an update please? and save my sanity. :^)

    • John Boardman says:

      Thanks for looking at my blog! I’ll see what I can do for you. In the mean time have a look at this thread and see if it helps you out. He’s looking to put elements in front of everything, but it may be applicable to you as well.

      http://forum.unity3d.com/threads/having-gui-elements-in-front-of-everything.263735/

      In particular, this comment:
      “You can use multiple canvas with the new UI.
      Each canvas has a sorting layer and a layer order.”

      may help you avoid having multiple cameras, by creating a canvas and using sorting/layer order to put it behind everything else.

      I haven’t had a chance to look at the latest features, so it may be a bit before I can try this stuff out myself. I hope it gives you a hint of where to look in order to proceed.

      Best of luck!
      John

Leave a Reply

Things Twitter is Talking About
  • Let's talk testing. Here are common challenges #Agile teams face when writing automated tests & how to overcome them: http://t.co/DrKbNZJcE0
    July 3, 2015 at 11:06 AM
  • #GrokOla users get free educational tutorials. But lucky you, we've released some to the public. #JavaScript primer - http://t.co/nIR9XiWY6O
    July 3, 2015 at 10:55 AM
  • Being able to isolate debugging techniques can help make you a better debugger. Here's Time-Oriented #Debugging http://t.co/UplJgP4VzC
    July 2, 2015 at 10:50 AM
  • RT @zachagardner: @zachagardner has declared it is @ChipotleTweets day at @KeyholeSoftware . You have been warned 🐓🐖🐄
    July 2, 2015 at 10:09 AM
  • Current state of random number generation & the differences in how #Java & #JavaScript approach it - http://t.co/5tBKNXnu8T #security
    July 1, 2015 at 2:45 PM
  • Woohoo - 600 followers! Thanks, everyone. We'd love to ask you - what type of tweets / dev content would you like to see more of from us?
    July 1, 2015 at 10:38 AM
  • We would like to welcome Dallas Monson to the team today! Dallas is a Senior Architect focused on UI/UX and #JavaScript. Welcome, Dallas!
    July 1, 2015 at 8:35 AM
  • Good introduction to TypeScript - http://t.co/0N22fVpAHt Plus, how to approach modularization in #TypeScript - http://t.co/wxRWGBj3Uh
    June 30, 2015 at 3:25 PM
  • .@mrbristopher just delivered a new S911 Night Drone to James Hayes, winner of our #kcdc15 giveaway! Congrats, James! http://t.co/RriJIxubH2
    June 30, 2015 at 11:35 AM
  • It feels like primitives could have been left out of the initial implementation of #Java. See why - http://t.co/A8ChCBHXJO
    June 29, 2015 at 4:05 PM
  • Developers in a bounce house! I repeat, developers in a bounce house! We had a blast at our 1st company picnic. Pics: http://t.co/XIqs7ECUst
    June 29, 2015 at 1:40 PM
  • New #SpringBatch tutorial from @jhackett01: Spring Batch – Replacing XML Job Configuration With JavaConfig http://t.co/PmdXnriKQu #java
    June 29, 2015 at 11:46 AM
  • We had such a fun time at the Keyhole company picnic! Pictures to come, including some of our developers in the bounce house. #loveourteam
    June 29, 2015 at 8:41 AM
  • In #JavaScript, how do we harness the power of callbacks without the confusing mess of nested functions? Promises - http://t.co/j1gAJ9hi3D
    June 29, 2015 at 8:40 AM
  • .@zachagardner We are so happy that your family attended! This will definitely need to be repeated every year!
    June 28, 2015 at 8:14 PM
  • Thank you to all on the Keyhole team who came to our first inaugural company picnic! Wonderful food, family and bounce house fun!
    June 28, 2015 at 7:50 PM
  • Debugging is a challenging part of being a programmer. We have a tutorial series to help, with a #JavaScript focus - http://t.co/rfhjJo64P7
    June 27, 2015 at 1:45 PM
  • We love #KCDC15! @PinsightMedia's James Hayes just was drawn as the winner of the @KeyholeSoftware drone giveaway. Stop on by the KHS booth.
    June 26, 2015 at 2:24 PM
  • Congratulations to James Hayes! You have won the Keyhole drone giveaway, come up and get your prize! #KCDC15
    June 26, 2015 at 2:09 PM
  • There are just 15 minutes left to register to win the drone from us at the Keyhole Software booth - come say hi and grab some frogs! #kcdc15
    June 26, 2015 at 1:45 PM