Frank Moricz

Co-Founder and Executive Editor for Gaming Irresponsibly. Computer nerd and video game enthusiast. I love to write, but sometimes find gaming more immersive than even even the most epic novel.

Apr 132012
 

In part 1 of “Saving and Loading” (Megabite #24), I showed how PlayerPrefs and PlayerPrefsX could be utilized to save things quite easily into a Unity-based game.  In this edition, I will show how to create a save file on a hard drive – this is more complex, and also more versatile.

Again, there is no need to reinvent the wheel if good code exists elsewhere, so I’ll share this gem I found here:

The Serializer works like this:

You create a holder class for everything you want to save and then you mark it with the Serializable attribute:

[Serializable ()] public class SaveData : ISerializable { public bool foundGem1 = false; public float score = 42; public int levelReached = 3; public SaveData () { } } 

Then you have to define functions for how the class should be loaded and how it should be saved, these should be put inside the class.

 public SaveData (SerializationInfo info, StreamingContext ctxt) { //Get the values from info and assign them to the appropriate properties foundGem1 = (bool)info.GetValue("foundGem1", typeof(bool)); score = (float)info.GetValue("score", typeof(float)); levelReached = (int)info.GetValue("levelReached", typeof(int)); } //Serialization function. public void GetObjectData (SerializationInfo info, StreamingContext ctxt) { info.AddValue("foundGem1", (foundGem1)); info.AddValue("score", score); info.AddValue("levelReached", levelReached); } 

The only thing left now is the save and load functions in your script.

public void Save () { SaveData data = new SaveData (); Stream stream = File.Open("MySavedGame.game", FileMode.Create); BinaryFormatter bformatter = new BinaryFormatter(); bformatter.Binder = new VersionDeserializationBinder(); Debug.Log ("Writing Information"); bformatter.Serialize(stream, data); stream.Close(); } public void Load () { SaveData data = new SaveData (); Stream stream = File.Open("MySavedGame.gamed", FileMode.Open); BinaryFormatter bformatter = new BinaryFormatter(); bformatter.Binder = new VersionDeserializationBinder(); Debug.Log ("Reading Data"); data = (SaveData)bformatter.Deserialize(stream); stream.Close(); } 

Oh, just one thing more, you need to define a VersionDeserializationBinder class, otherwise you can’t load the game when you open it later, something about Unity generates a new key of some sort for the binary formatter, search for “Serialization” on the forum and you can find a post about that.

public sealed class VersionDeserializationBinder : SerializationBinder { public override Type BindToType( string assemblyName, string typeName ) { if ( !string.IsNullOrEmpty( assemblyName ) && !string.IsNullOrEmpty( typeName ) ) { Type typeToDeserialize = null; assemblyName = Assembly.GetExecutingAssembly().FullName; // The following line of code returns the type. typeToDeserialize = Type.GetType( String.Format( "{0}, {1}", typeName, assemblyName ) ); return typeToDeserialize; } return null; } } 

You will need to use these namespaces to get it working:

using System.Text; using http://System.IO; using System.Runtime.Serialization.Formatters.Binary; using System; using System.Runtime.Serialization; using System.Reflection; 

Done, at last :D

To utilize this code, we’re going to use C# instead of Javascript.  You will want to first create a C# file and name it “SaveData”.  The order of the code above is a bit difficult to read if one has no C# experience, so here it is in complete form:

using UnityEngine;
using System.Collections;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System;
using System.Runtime.Serialization;
using System.Reflection;
[Serializable ()]
public class SaveData : ISerializable {
 public bool foundGem1 = false;
 public float score = 42;
 public int levelReached = 3;
public SaveData () {
 }
 
 public SaveData (SerializationInfo info, StreamingContext ctxt)
 {
 //Get the values from info and assign them to the appropriate properties
 foundGem1 = (bool)info.GetValue("foundGem1", typeof(bool));
 score = (float)info.GetValue("score", typeof(float));
levelReached = (int)info.GetValue("levelReached", typeof(int));
 }
//Serialization function.
public void GetObjectData (SerializationInfo info, StreamingContext ctxt)
 {
info.AddValue("foundGem1", (foundGem1));
 info.AddValue("score", score);
 info.AddValue("levelReached", levelReached);
 }
 
 public void Save () {
SaveData data = new SaveData ();
Stream stream = File.Open("MySavedGame.game", FileMode.Create);
 BinaryFormatter bformatter = new BinaryFormatter();
 bformatter.Binder = new VersionDeserializationBinder(); 
 Debug.Log ("Writing Information");
 bformatter.Serialize(stream, data);
 stream.Close();
}
public void Load () {
SaveData data = new SaveData ();
 Stream stream = File.Open("MySavedGame.gamed", FileMode.Open);
 BinaryFormatter bformatter = new BinaryFormatter();
 bformatter.Binder = new VersionDeserializationBinder(); 
 Debug.Log ("Reading Data");
 data = (SaveData)bformatter.Deserialize(stream);
 stream.Close();
}
 
}
public sealed class VersionDeserializationBinder : SerializationBinder 
{ 
 public override Type BindToType( string assemblyName, string typeName )
 { 
 if ( !string.IsNullOrEmpty( assemblyName ) && !string.IsNullOrEmpty( typeName ) ) 
 { 
 Type typeToDeserialize = null;
assemblyName = Assembly.GetExecutingAssembly().FullName;
// The following line of code returns the type. 
 typeToDeserialize = Type.GetType( String.Format( "{0}, {1}", typeName, assemblyName ) );
return typeToDeserialize; 
 }
return null; 
 } 
}

The way it is set up, this code will create a file named MySavedGame.game, and inside it will save the variables “foundGem1″, “score”, and “levelReached”.  Once you have this script saved, you simply need to implement the functions.  The easiest way to do this is with another C# file.

If you are testing this script on a new project, you can simply create a gameObject of any sort – I’m partial to cubes – and attach a new C# file to it.  I named mine “Test”, and here it is:

using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
void Start () {
 SaveData save = new SaveData();
 save.foundGem1 = true;
 save.levelReached = 7;
 save.score = 4000;
 save.Save();
 }
}

As you can see, all it does is set the variables to be saved, and then it calls the Save() function within the SaveLoad file.  In a working title, you’re always going to need to decide the things you want saved, and build a function around that premise.   In the example above, save.Load() should actually read the file and the variables can just as easily be pulled out of the “save” object.

As you can see, it’s quite a bit more complex, but very much worth it to anyone who has plans to expand into multiple save files, more complicated games, or simply a more traditional setup.

Apr 062012
 

In this brief tutorial, I wanted to show some quick code examples which will allow your scripts to easily communicate with each other by means of executing each other’s functions.  Without going into descriptions of more intermediate topics such as classes, methods, or other terminology that might be difficult to understand, what I will do here is basically create two javascript files and two functions within those files.  One of those functions will send a message to the other and our desired effect will be achieved.

In the following case, all we are doing is sending a “print” line, which will appear in your unity console.

Script1:

function PrintText(text : String) {
print(text);
}

Script2:

function DoText() {
var target : GameObject = GameObject.FindGameObjectWithTag("myObject");
target.SendMessage("PrintText", "This text was sent and executed!");
}

As you can see from script 2, we’re targeting a game object with the tag of “myObject”.  Creating and adding a tag to any type of gameObject will suffice, so create a cube and be sure to apply the tag you create.  Once finished, just attach script1 to the object.

As for script2, we can trigger this any way we like.  You can choose to add it to an input button or an event to test it, or simply add it to a second gameObject in play and relocate the code into the “Start” section of the script, so it would look something like this:

function Start() {
var target : GameObject = GameObject.FindGameObjectWithTag("myObject");
target.SendMessage("PrintText", "This text was sent and executed!");
}

Be sure this script is attached to an object, or else it will not run as intended when you test the game.  If everything worked correctly, you should get something like this:

There are obviously much more useful ways to use the SendMessage() function, and knowing the basics, you should experiment with things like damage application or sound triggers – really whatever you can think of.  The important thing to note is that because you are targeting the object itself, the command WILL execute all instances of the script you name when calling SendMessage.  This can cause you errors if you didn’t plan for it, so be sure to stay vigilant in its usage.

 

Mar 302012
 

Manipulating time in Unity3d is quite a bit of fun.  When I first created the project you can see below, I wanted to see how difficult it would be it institute something similar to what we see in Braid – basically a button that can turn back time.  For my purposes, I wanted to start out fairly small and be able to attach a script to any game object in the scene that would be affected by this time-shift.  I’ll paste the code here, but be sure to check it out in action at the link below:

Time-manipulation Demo

This was also my first real experience with the new Shiruken particle system, and I have to say I’m rather impressed.  It’s clearly very different, but you can’t argue with the results.  Anyway, I decided to use a simple array to hold the data for time reversal.  The main control key, “R”, simply triggers a boolean variable when held down.  This is located in the regular character movement controls, like this:

//Reversal key
 if (Input.GetKey("r")) {
 isRevving = true;
 } else {
 isRevving = false;
 }

By doing that, I don’t have every instance of the script listening for the R key.  The actual time script looks like this:

var thisHistory = new Array();
function Update () {
 var revControl : boolean = GameObject.FindGameObjectWithTag("Player").GetComponent(charMover).isRevving;

 if (revControl == false) {
 thisHistory.Push(transform.position);
 if (thisHistory.length > 1000) {
 thisHistory.RemoveAt(0);
 }
 }

 if (revControl == true && thisHistory.length > 0) {
 RevOne();
 }
}
function RevOne() {
 var onNum = thisHistory.length;
 transform.position = thisHistory[(onNum - 1)];
 thisHistory.Pop();
}

As you can see, it simply hold the last 1000 frames of position data in memory and begins to delete the old data as time goes on.  If the reverse key is pressed, it stops recording and starts moving backward, deleting each frame as it goes along.  I was quite happy with the results for character movement, and this same thing could be applied to many variables aside from position if the script was extended.  Some ideas that are fairly obvious would be character health, rotation, or any other piece of numerical data that would be important to your game environment.

I didn’t apply the script to the in-game “bullets”, because the script doesn’t support the deletion of the bullet once it rewinds to the point of its origin.  however, something tag-based could be quite easily added into the script if that was a desired feature.

The other fun thing I wanted to do with time in this demo is something similar to bullet-time.  When a target is hit, I thought it would be fun to slow the overall game time down and gradually increase it back to regular speed.  Through the Time.timescale function, unity made this little diddy a snap.  It works something like this:

//time fixer (currently located in the character movement script)
 if (Time.timeScale > 0 && Time.timeScale < 1) {
 Time.timeScale += 0.005;
 }

Make note of the specification that the timescale needs to be above 0. This was added so that a game could still be paused without gradually unpausing itself.  With this if condition added into the Update section of a running script, all we have to do is trigger a drop in timescale based on a condition.  In this case, I used the collision of a bulled with one of the white target blocks:

//This snippet is attached to the white target blocks
var exp : Transform;
function OnCollisionEnter(other : Collision) {
 if (other.transform.tag == "bullet") {
 var splode : Transform = Instantiate(exp, transform.position, Quaternion.identity);
 splode.particleSystem.Play();
 GameObject.FindGameObjectWithTag("Player").SendMessage("Timing");
 Destroy(gameObject);
 }
}
------
//This function was added to the character movement script
function Timing() {
 Time.timeScale = 0.1;
}

With these few pieces of code added to my dull demo platformer, I was able to quickly pull off some quality features with very little programming.  Hopefully readers will find this demo useful as well, and if you have any questions, please feel free to drop them in the comments below :)

Mar 232012
 

Some users, especially those new to Unity3d, may have issues understanding variables and declarations within a script.  I wanted to take a moment to explain in-depth the different types of variables, how they work, and what your own best practice should be for the usage of each.

Public

First, we’ll speak about public variables.  When using javascript, this is the default variable type.  Declaring one is quite simple:

var myVariable : String;

When using javascript, we don’t actually need to declare using the word “public”.  In C#, this isn’t the case.  The same thing in C# would be:

public string myVariable;

A public variable is two things:

  • A variable which can be accessed by other scripts if needed
  • Available in the Unity editor for quick access and alteration

Regarding the latter, a quick note should be made.  If a public variable is declared and compiled, it will remain the same in the editor even if a dev later changes it in the original script where it is first declared.  For example, if you write something like:

var myVariable : int = 25;

…and then save/compile it (see it in the unity editor), if you change the script to something like:

var myVariable : int = 50;

…then nothing would actually change.  This one thing is confusing to every new unity user (even experienced developers used to other dev tools).

On the other hand, one of the main advantages about public variables is the ability to utilize them anywhere.  Let’s set up an example here.

//This script is ScriptOne.js, and simply makes a public variable.
var scriptOneVar : int = 25;
//This is ScriptTwo.js, and it accesses the variable information from the other script.
var script : ScriptOne;
script = GameObject.GetComponent("ScriptOne");
var accessedVariable : int = script.scriptOneVar;

This same thing will work with public functions as well, but that should be another tutorial altogether.  For now, just know that due to this nifty functionality, you need not declare a variable multiple times for multiple scripts.  Using GetComponent, you can access a script (along with its variables) from any gameObject the script is attached to.

Static

A static variable is one that will be active from the very beginning of the program’s execution.  For this reason, you may want to use them more sparingly, because they will need to be changed manually through script each time, and cannot simply be destroyed along with gameObjects.

//Script name myScript.js
static var myVariable : String = "Steve";

If the code above is used, for example, the variable is equal to “Steve” from the moment the game begins to run.  Static variables can only be declared or altered through script, but I myself have found them handy for overall usage in things that are altered as a player moves from one level to the next.  If you have a script that only contains static variables, you should never need to attach that script to any particular gameObject.

Accessing these variables is as easy as pointing to the script name.  In a project where the above script exists, a separate script that says:

//Other script
print ("The character's name is" + myScript.myVariable);

…should output the static value.  In the same vein, changing the value is as easy as:

myScript.myVariable = "Justin";

Private

A private variable is hidden from the inspector and only usable/accessible from the script it is executed from.  Using these will keep your inspector looking cleaner and make things easier on bigger projects overall.  Declaring them is quite simple:

private var myVariable : int = 55;

By default, I will use a private variable each and every time.  Only if I know that I will need to alter something via the inspector or access the value from another script will I start to decide on other types.  When programming, I find things easier overall if you plan for any project to get much larger than intended, and using private variables will make your code more manageable for the future.

 

Mar 092012
 

The problem with saving and loading as it pertains to newer programmers is often a lack of understanding.  Like pathfinding or AI, it’s one of those things that needs to be customized to each game.

In the older days, games did not take up a great deal of RAM while running.  As such, it wasn’t a big deal to save everything the game was doing into a file and just load it up.  This practice is commonly referred to as saving and loading “states”.  Games today, however, can fill machines that use anywhere from 2-16+ gigabytes of ram – we wouldn’t want our save files that large, so the process of holding onto data had to adapt.

Today I will cover a few things for more beginner-type saving.  While saving to an actual file on the hard drive is quite possible, what we will cover today will be a basic walkthrough of two things – PlayerPrefs and PlayerPrefsX.

PlayerPrefs is an easy feature that comes with Unity3d by default.  With it, we can quickly and easily save integers, strings, and floats.  Just as easily, we can recall that data and use it however we like.  Here is an example with two functions – one will save a basic score, and the other will load that score into a variable:

function Save(theScore : int) {
PlayerPrefs.SetInt("Score", theScore);
}

var loadedScore : int;
function Load() {
loadedScore = PlayerPrefs.GetInt("Score");
}

As you can see, its pretty streamlined.  However, the ease of use that PlayerPrefs allows comes with its greatest downfall – saving complex numbers, vectors, arrays, etc aren’t easily feasible.  This is where PlayerPrefsX comes it – and it’s something you don’t automatically get with unity by default.  However, it’s free and easy to get set up.

PlayerPrefsX Javascript + Basics

Copy the code from the large code block at the bottom of the page above and save it as PlayerPrefsX.js.  Drop it into your Standard Assets folder and the functions are accessible from any script you choose.

As you can see, this gives you access to the following functions:

  • PlayerPrefsX.SetBool
  • PlayerPrefsX.GetBool
  • PlayerPrefsX.SetVector2
  • PlayerPrefsX.GetVector2
  • PlayerPrefsX.SetVector3
  • PlayerPrefsX.GetVector3
  • PlayerPrefsX.SetQuaternion
  • PlayerPrefsX.GetQuaternion
  • PlayerPrefsX.SetColor
  • PlayerPrefsX.GetColor
  • PlayerPrefsX.SetIntArray
  • PlayerPrefsX.GetIntArray
  • PlayerPrefsX.SetFloatArray
  • PlayerPrefsX.GetFloatArray
  • PlayerPrefsX.SetBoolArray
  • PlayerPrefsX.GetBoolArray
  • PlayerPrefsX.SetStringArray
  • PlayerPrefsX.GetStringArray
  • PlayerPrefsX.SetVector2Array
  • PlayerPrefsX.GetVector2Array
  • PlayerPrefsX.SetVector3Array
  • PlayerPrefsX.GetVector3Array
  • PlayerPrefsX.SetQuaternionArray
  • PlayerPrefsX.GetQuaternionArray
  • PlayerPrefsX.SetColorArray
  • PlayerPrefsX.GetColorArray

All of these will function as you would expect, and in the same way as PlayerPrefs does.  However, you have the versatility of saving Vector3s, Quaternions, String Arrays, and many more.

While PlayerPrefs is a wonderful tool (and actually what PlayerPrefsX uses to function), with this new script in your arsenal you just need to get all of the data you would like to keep into array format.  Saving the positions and rotation of players and game objects becomes this much easier, and saving/loading worlds and levels becomes that much more seamless.

To test this script myself, I created a terrain and used the unity tree generator tool to create a tree gameObject.  When the scene begins, 10,000 trees are created and placed in random positions along the 2000×2000 terrain.  With PlayerPrefsX, I was able to gather the vector3 positions of each tree into a Vector3 array and seamlessly save it into a variable, like so:

//trees
 var allTrees : GameObject[] = GameObject.FindGameObjectsWithTag("tree");
 var numTrees : int = allTrees.length;
 print ("There are " + numTrees + " Trees in this world");
 PlayerPrefs.SetInt("NumTrees", numTrees);
 var treeLocs = new Vector3[numTrees];
 for (x =0 ; x < numTrees-1; x++) {
 treeLocs[x] = allTrees[x].transform.position;
 }
 PlayerPrefsX.SetVector3Array ("TreeLocs", treeLocs);

As you can see, I also used the normal PlayerPrefs function to save the raw number of trees that exist at the time.  To load the trees onto a blank slate terrain, I simply use this code in a Load() function:

//Load new trees at saved locations
 var numTrees : int = PlayerPrefs.GetInt("NumTrees");
 var treeLocs = new Vector3[numTrees];
 treeLocs = PlayerPrefsX.GetVector3Array("TreeLocs");
 print("Tree locations recieved for " + numTrees + " trees");

 for (x =0 ; x < numTrees-1; x++) {
 var tree = Instantiate(treePrefab, treeLocs[x], Quaternion.identity);
 }
 print("added trees in previous locations");

I hope this article can be of some help to you.  While it may be difficult to realize each little thing you want to save, if you build your game with saving and loading in mind, the process becomes much easier to manage.

As always, drop questions or comments into the comment fields below :)

Mar 022012
 

A basic understanding of how coordinates work can go a very long way in Unity as well as other gaming engines.  On a basic level, the world coordinates are the ones that an object defaults to if it’s not attached as a child of another object.  If it is, it then is subject to coordinates that work in relation to it’s parent.

This same thing applies to both the position of an object as well as the rotation of an object.

Why is it set up like this?  Well, in truth its for ease of use and more versatility in how your game works.  While it might be complicated to wrap your head around at first, its a very worthwhile thing to master.

Lets take a look at an example as see what I’m going on about.

3 total gameobjects - none of them are a parent or a child.

In this first picture, we have 2 cubes and a camera. Each is completely independent, and one of them will not affect the other in terms of position or rotation.  However, if we make one cube a parent of the other (by dragging the child atop the parent in the Hierarchy), the situation changes.

Attached Child

Rotating the Parent

Once the two cubes are paired, the child cube is more reliant on the parent. If the parent moves, the child moves with it. If the parent rotates, so will the child.

What you will see in the inspector will always be the local position and rotation if you have a child object selected.  For the purpose of working with the Unity editor, this is typically ideal – it makes a great deal of sense when you can physically see the results of your actions and alterations.

One very common usage for this child-parent relationship would be something along the lines of attaching a camera to a player’s character.  As the character would move through the world, the camera would move and rotate completely relative to the player’s gameObject.

Where things might get somewhat complicated is in the scripting side of things – many unity functions will default to world space and not local space.  Some functions and variables will also be specifically used with child objects for the same reason.  transform.position for the parent, transform.localPosition for the child, for example.

Calculations made when manipulating child objects will be drastically affected by scale as well, so while transform.position.y+=10; might make an object move exactly where you want it to go, transform.localPosition.y+=10; will not if the scale of your parent is anything other than 1.  This becomes further complicated if the child’s parent ALSO has a parent – calculations will need to be made to compensate all the way up the chain.

However, just because things might become complex, using this child-parent relationship in gameObjects is crucial.  My best suggestion for newer users is to experiment with both the editor as well as code until you are confident you have a basic level of understanding on the subject.  Of course, and questions you might have can be fielded here as well.

Happy dev-ing!

Feb 242012
 

In the last Megabite, I covered simple arrays – again, arrays are a huge deal and make coding and variable storing a much easier and more dynamic process.  One thing that an array lacks though is a searchability.  From an array, you can get the amount of entries or the values of individual entries, but you’d have to write a function to go through each thing one-by-one if you were looking for a specific entry or object.

This is where hashtables come in, and they are also wonderful.  Like an array, a hashtable holds both data and a key, but it does it in a little bit of a different format.  On the C# side, a hashtable is called a dictionary, and that’s a good way of looking at it – its an indexed, searchable variable holder.

Creating your first hashtable is easy:

var myHash : Hashtable;
myHash = new Hashtable();

This function is code-only as far as I know – it’s not something you can simply add via the inspector.  To start it off, we’re going to add a few strings into it with the Add function.  Something like this:

function Start() {
var myHash : Hashtable;
myHash = new Hashtable();
myHash.Add(1, "red");
myHash.Add(2, "blue");
myHash.Add(3, "green");
myHash.Add(4, "yellow");
}

What we have here will basically create these 4 entries into our dictionary when the script begins.  Like an array, we can access things by key like so:

print (myHash[1]);

This will output “red”, as expected.  You’ll notice that we don’t start at zero like an array would.  The “pages” of a hashtable work differently.  We actually don’t have to go in any kind of order (though you will most likely choose to anyway).

if you do go in order, you can use most functions just as you would with an array without much hassle.  If you’re overwriting an existing key that you’ve already add, you simply want to use the Remove() function on that key before adding a new entry.  Add() will not actually overwrite without an error.

The big advantage however is that a hashtable allows the use of ContainsValue() and ContansKey().  These functions will output a boolean true/false that works great with IF statements.  There are a multitude of reasons to use this type of functionality, but as you Add and Remove entries throughout your code, you can use these as triggers or safety nets.

if (myHash.ContainsValue("purple")) {
print ("Purple was found in the dictionary.");
DoSomeOtherThing();
}
if (!myHash.ContainsKey(6)) {
print("Page 6 is missing from the dictionary.");
}

Other functions for hashtables include Clear() and Count – doing something like: myHash.Clear(); will simply delete all entries within the hash, so it’s not something to use lightly.  Count will return the total number of “pages” in your hashtable in the same manner that myArray.Length would do.  Count is not a function though, so it would be used something like this:

print("myHash contains a total of " + myHash.Count + " entries.");

While this isn’t something that I expect everyone will have immediate need of, it’s one of those great things that come in handy when you want to want to use an array and have finer control or general search indexing available.  For myself, I know that this little addition has been a lifesaver in certain scenarios, and I hope you get the chance to use it for yourself.

As always, let me know if you have any questions in the comments below!

Feb 232012
 

Arrays are an incredibly valuable method of storing variable data in the world of programming, and a great way of accessing that data in very useful ways.  In this article, I want to touch on the basic array options that Unity3d gives you access to, and also explain why you would want to use such things to make your life easier.

Let’s say, for example, that you want to store 5 separate pictures as textures.  You can easily make 5 different variables the old fashioned way:

var pic1 : Texture;
var pic2 : Texture;
var pic3 : Texture;
var pic4 : Texture;
var pic5 : Texture;

If you do something like this, however, accessing that data becomes difficult in certain scenarios.  You need to actually declare specific variables within your code, and to use the 5 pictures you end up with a big chunk of non-dynamic code.  For example, if I wanted to make a row out of these variables and they were each roughly 50px X 50px, I would have to do something like this:

function OnGUI() {
     GUI.DrawTexture(Rect(0,0,50,50), pic1);
     GUI.DrawTexture(Rect(0,50,50,50), pic2);
     GUI.DrawTexture(Rect(0,100,50,50), pic3);
     GUI.DrawTexture(Rect(0,150,50,50), pic4);
     GUI.DrawTexture(Rect(0,200,50,50), pic5);
}

For some scenarios, that might be perfect.  In everything, we want to consider the options available to us.  Consider for a minute though all the work that would go into doing something similar for a scope of maybe 20 pictures… or maybe even 100.  Very quickly something like this would get out of hand, and the code would be more susceptible to programming error.

With arrays, we can make one single variable that holds all of your data.  On top of that, we can actually access it dynamically through loops or fancy code.  Unity gives us 2 options when it comes to building arrays in javascript – one is the standard javascript method, and the other is to use the unity inspector to assign the data.  Heck, we can even change the type we choose on the fly to suit our needs, but we can get to that later.

First, we’ll use a built-in array.  This array will allow us to use the inspector for easy drag/drop assignment.  To make the variable, we simply use this:

var pic : Texture[];

That’s it?  Yep, pretty much.  After you save and compile the script, you end up with something like this in your inspector window.  The variable name “Pic” is there, and it has a size of 0 because we haven’t set that number yet.  Let’s set it to 5 and see what happens.

Once we set the size, we end up with neat little drag/drop spaces (or you can simply click on the spaces and select your pictures).  This makes it pretty easy to change the order of pictures or replace them on the fly while simply collapsing the variable with the arrow if you no longer need to mess with it.

But how do we use the data?  Well, an array variable is accessible through the key number that you see in the picture.  The first entry is 0, and it progresses upwards form there.  So Pic1-Pic5 from the first example effectively becomes Pic[0] – Pic[4].  Using those brackets is important – it tells unity that we’re dealing with an array.

To complete this picture example, I want to point out that the key number of an array is actually an integer when it comes to code.  That’s not the case if you just call a variable “Pic1″ – that number becomes a string in that regard.  In an array, we can use math to access the different portions of an array, and that’s uber-important when it comes to loops like this:

function OnGUI() {
   for (x=0; x < Pic.Length; x++) {
      GUI.DrawTexture(Rect(0,(x * 50), 50, 50), Pic[x]);
   }
}

While this might seem complicated (and it might be if you don’t fully understand the FOR loop), the important thing to notice is that the loop will actually run for the length of however many objects are in the “Pic” array.  This means your code will work fine with 5 pictures, but it would also work just as well for 5000 or 5,000,000 pictures.  We’ve made our code completely dynamic now, and the math allows it to expand as needed.

In some cases, we may not want to work with the inspector at all.  In that event, we may need to make an array on the fly and add to it with code alone.  Commonly this is the case with things such as Vector3s, integers, floats, or other variable types.

Making a blank array variable is easy:

var myArray = new Array();

Heck, we can even start it off with some values pretty easily:

var myArray = new Array(42, 38, 11, 14);

In the above case, myArray[0] would equal 42, myArray[1] = 38, and so on.

One important thing to note is the terminology.  This is commonly referred to as a javascript array.  The javascript array is the only type that can be altered in size through code.  If your array is visible in the inspector, you won’t easily be able to change the size and scope of the array without conversion.

The Unity Docs contain a lot of good stuff and examples in the world of js array manipulation, but the common commands to memorize should be:

  • Push
  • Pop
  • Shift
  • RemoveAt

Push is great, especially when you are first creating an array.  If you’ve just used the “new Array()” command, you can quickly fill it with 50 random numbers by doing something like this:

for (x=0; x<50; x++) {
myArray.Push(Random.Range(0,5000));
}

You’ll end up with an array where myArray[0] though myArray[49] exist, each with a random number between 0-5000.  You can use the Pop command to remove the last array entry completely

myArray.Pop();

if you did this, you have myArray[0] though myArray[48] now – the Pop command destroys the last entry in the series.  If you wish to destroy the very first number, tho one currently in the myArray[0] slot, you would use the Shift command:

myArray.Shift();

In doing this, you are deleting that first entry, but everything moves down to fill the space.  You still have one less entry, but the new first number in the array is the one that used to be at myArray[1].  Removing from arrays will always cause the index key to reorganize to fill the blank space.  This is important to realize when working with RemoveAt(), because if you choose to do something like this:

myArray.RemoveAt(39);

Then whatever was at myArray[39] would disappear and everything at 40 or higher would move down to fill the spot.

While for your own purposes you may use arrays to hold integers, you may find it useful to experiment how amazing they are with Transforms, GameObjects, Vector3s, and so forth.  Experimentation will lead you into places you never expected, but through mastery of the basic array, you should be able to perform some extremely dynamic and spectacular functions.

Feb 212012
 

A surprising post was made today by Andrew “Redigit” Spinks, the creator of Terraria:

The future of Terraria has been highly debated as of late, not just with the community, but for us as well. The last year has been a crazy ride! When I started on this game, I just had a few ideas of what I thought would make a fun game. I had no idea that it would receive so much attention. I want to thank all of you for supporting us and making this game’s success possible.

After a lot of internal debate, we have decided that it is time to move on. My wife and I are due to have another boy soon, and I want to spend some time getting to know him. I also want to spend the time recharging and bettering myself as both a programmer and game designer. I have learned a lot from working on Terraria and plan on using what I’ve learned, building upon it, and moving forward with another, even better project. However, we are still planning at least one more bug fix for Terraria.

For those that haven’t already heard, Finn “Tiy” Brice has moved on to form Chucklefish and is heavily at work on an exciting new game called “Starbound”. It’s looking to be a lot of fun, so make sure to check it out if you haven’t already!

Thanks again for all your support, and I am very much looking forward to providing you with something much better than Terraria in the future!

As a site that covered Terraria from a time before it was even released, I found it fitting to make this post myself.  Andrew and the Re-Logic team have been a major inspiration not only for myself but I’m sure a number of others.  Gaming Irresponsibly wishes him well until he returns with what I’m sure will be another amazing title.

I would assume with a “final” version of the game out soon, we may see a rise in terraria mods and general user additions to the game from the wonderful community that has been established.  As such, we will leave our Terraria forums active until the point where they are no longer used.

Farewell for now, Redigit, and thanks for the awesome ride!

Feb 172012
 

This post is simply to serve as an update for my Megabite readers.  For those who might have missed it, our site here was attacked this past week by hackers, and I spent a majority of my free time fixing it, updating it, adding security measures, etc.

Long story short- I don’t have my full article this week as scheduled.  I will, however, not be skipping the week.  I anticipate a new, official Megabite within the next few days, and another this upcoming Friday as the schedule resumes.

I apologize to anyone who is disappointed by the news, but I didn’t want to hack out a half-assed article just to meet a deadline.

Thanks for your understanding :)

–Frank Moricz

Feb 102012
 

This Megabite, the 20th in the series, will focus on a question asked by a reader.  D Hunter asks:

… I’d love to know how to script a player-controlled ship you can walk around while it’s moving (like on autopilot). I’ve been struggling with this and it’s hard to find resources on that particular issue. If you can find a way to generalize it to the principal, that would be sweet too; if its not in your interest, no worries either :) I’m still pretty new to Unity

Well, D Hunter, I’m happy to say that this will be an easy one for you – assuming your autopilot is already functional.  What we’re going to do here is set up a rigidbody for the “ship”, switch it to isKinematic = true, and add some constraints for the demo.

For my ship, I just made a cube.  I added a rigidbody component like so:

Take note of the constraints – We don’t want it flipping around for any reason, and we don’t want it being affected by gravity to fall into the planet.  For motion, I simply added a RotateAround .js file, but if yours uses AddForce or ConstantForce, that should work just as well.

function Update () {
transform.RotateAround(Vector3.zero, Vector3.up, 10 * Time.deltaTime);
}

It’s rotating around the vector of 0,0,0.  When I added my standard character controller, I made sure to add it as a CHILD of the ship itself, so it rotates along with the parent.  Input and movement are now relative to the parent.  Which means you don’t want to simply jump off of the ship and hit the ground – the character, if attached as a child, would continue to move with the ship.  If you wanted something like that, you would need to have something added to set the parent to null given a certain scenario.

Because of this, I added some invisible walls to make sure the character stays on the ship at all times.  The collision detection isn’t as strong as it should be, so if you were to jump against them a few times your character will fall from the ship and you can see how bad that could get :)

Of course, you want to make sure those walls are children of that parent ship as well.  They will all move together that way and everything runs smooth.  Below, I’ll add the demonstration scene and a download link for the package itself so it might help anyone else struggling with this issue

Use WSAD controls to move around :)


Download Package

Feb 032012
 

Theres an obvious popularity in the world of independent development when it comes to grid-based games, or worlds constructed of blocks or squares.  Because Unity has no easy one-click functionality for such a thing, I wanted to start a project and show the world how I went about achieving something similar without using a voxel engine.

The results of what I have so far come out something like this:

As you can see, the ground has a grid pattern, and the blocks fit atop the terrain quite nicely.  I had a small assortment of default textures assigned as well as a few free downloads from the Unity Asset store, and I’ll be releasing all the important code for this project here so that it can be clearly seen and utilized.

As a note, this is not 100% finished – this is a work in progress but was far enough along that I could demonstrate the usage and ability of the code to create blocks, assign a shader, and batch the draw calls despite changing the renderer on-the-fly.

There are only 3 total components in this scene:

  • A camera
  • a directional light
  • a piece of terrain measuring 600px x 600px

You can see in the picture here that this is all very basic – it was designed to be.  The cubes in this project are not prefabs – they are generated on-the-fly via scripting.  The width I chose for my cube world was 3 units, and you can see via the picture above that the “good dirt” texture is set to simply tile every 3 units.  It was offset by 1.5 in both directions simply so that we can start block placement at Vector3(0,0,0) without confusion.

To make the texture appear as a grid, I simply opened the texture in photoshop and placed a small black border around the picture.

Only 2 scripts run this project – one to move the camera however we like, and the other runs the block generation.  Instead of placing blocks simply one at a time, the script is fully capable of drawing lines in both horizontal and vertical directions.  Eventually the script will allow clicking and dragging out a grid which will place a square or rectangle of individual blocks as well.

Below I have pasted the entire code that generates the blocks:

private var readyClick : boolean = true;
var currentInfo : Transform;
private var lastBlock : Transform;
var cube : Transform;
var boxTex : Texture[];
private var curPos : Vector3;
private var blockNum : int;
private var blockArr = new Array();
var shader : Shader;
function Start() {
 for (var x=0;x<boxTex.Length;x++) {
 var cube : GameObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
 cube.transform.localScale = Vector3(3,3,3);
 var theMat = new Material(Shader.Find(" Diffuse"));
 cube.renderer.material = theMat;
 cube.renderer.sharedMaterial.mainTexture = boxTex[x];
 blockArr.Push(cube);
 }
}
function Update() {
 var point : Vector3;
 var theRay: Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
 var theHit: RaycastHit;
 if (Physics.Raycast(theRay, theHit)) {
 mousePoint = theHit.point;
 point = GetTerPoint(theHit.point, 1.5);
 if (theHit.transform.name == "Terrain" && dragOn == false) {
 ClearLast();
 theCube = Instantiate (cube, point, Quaternion.identity);
 lastBlock = theCube;
 curPos = point;
 }
 }
//This is the code that would place a single block instead of allowing dragging
// if (Input.GetKey("mouse 0") && curTex != null && point.y != 0) {
// Instantiate (blockArr[blockNum], point, Quaternion.identity);
// print(blockNum);
// }
 
 if (Input.GetKey("mouse 0") && dragOn == false) {
 dragOn = true;
 startPoint = point;
 DoDrag(startPoint);
 }
 var xPt : int = 3 * (Mathf.Floor(mousePoint.x / 3));
 var zPt : int = 3 * (Mathf.Floor(mousePoint.z / 3));
}
private var startPoint : Vector3;
private var mousePoint : Vector3;
private var dragOn : boolean = false;
private var dragNum : int;
function DoDrag(start : Vector3) {
 tempCube = Instantiate (cube, start, Quaternion.identity);
 yield StartDrag(start);
 Destroy(tempCube.gameObject);
 dragOn = false;
}
function StartDrag(start : Vector3) {
 while (true) {
 while (Input.GetKey("mouse 0")) yield;
 var rawNum : int;
 var numBlocks : int;
 if (mousePoint.x > start.x + 3) {
 //do right side blocks
 rawNum = (3 * (Mathf.Floor(mousePoint.x / 3))) - start.x;
 print("raw: " + rawNum);
 numBlocks = rawNum /3;
 for (x = 0; x < numBlocks; x++) {
 Instantiate (blockArr[blockNum], Vector3(start.x + (x*3), start.y, start.z), Quaternion.identity);
 }
 }
 if (mousePoint.x < start.x + 3) {
 //do left side blocks
 rawNum = (3 * (Mathf.Floor(mousePoint.x / 3))) - start.x;
 print("raw: " + rawNum);
 numBlocks = -(rawNum /3);
 for (x = 0; x < numBlocks; x++) {
 Instantiate (blockArr[blockNum], Vector3(start.x - (x*3), start.y, start.z), Quaternion.identity);
 }
 }
 if (mousePoint.z > start.z + 3) {
 //do up side blocks
 rawNum = (3 * (Mathf.Floor(mousePoint.z / 3))) - start.z;
 print("raw: " + rawNum);
 numBlocks = rawNum /3;
 for (x = 0; x < numBlocks; x++) {
 Instantiate (blockArr[blockNum], Vector3(start.x, start.y, start.z+ (x*3)), Quaternion.identity);
 }
 }
 if (mousePoint.z < start.z + 3) {
 //do down side blocks
 rawNum = (3 * (Mathf.Floor(mousePoint.z / 3))) - start.z;
 print("raw: " + rawNum);
 numBlocks = -(rawNum /3);
 for (x = 0; x < numBlocks; x++) {
 Instantiate (blockArr[blockNum], Vector3(start.x , start.y, start.z - (x*3)), Quaternion.identity);
 }
 }
 return;
 }
}

 

function ClearLast() {
 if (lastBlock) {
 Destroy(lastBlock.gameObject);
 }
}
function GetTerPoint(thePoint : Vector3, height : float) {
var numX : float = 3 * (Mathf.Floor(thePoint.x / 3));
var numZ : float = 3 * (Mathf.Floor(thePoint.z / 3));
var theVec : Vector3;
theVec = Vector3(numX,height,numZ);
return theVec;
}
private var curTex : Texture;
function OnGUI () {
GUI.Box(Rect(0,0, Screen.width,50), "");
 for (var x = 0; x < boxTex.Length; x++) {
 if (GUI.Button(Rect(2 + (x * 50),2,48,48), boxTex[x])) {
 SwitchTex(x);
 }
 }
GUI.Box(Rect(0,53,50,50), "");
if (curTex) {
 GUI.DrawTexture(Rect(2,55,48,48), curTex);
}
}
function SwitchTex(num : int) {
 curTex = boxTex[num];
 blockNum = num;
}

A few explanations.  The only Prefab you see here is for a temporary cube.  This object shows up while the mouse is touching the terrain, and it shows where blocks will be placed.  Because the ability to draw out a rectangle while dragging is not complete, right now the code results in drawing out an L shape.  There are also no safeguards to keeps blocks from drawing on top of each other for now.

I’ll continue to build on this project and post all of the code here within the Megabite articles.  When it is finished, what I want to have ready is a web-based (or downloadable) project that just allows a user to build whatever they like very quickly – whether it be a castle, a terrain, etc.

If anyone tries the code out or would like to help me expand upon the idea, simply let me know in the comments below :)

Jan 272012
 

I busted tail to attempt some code for my loyal Megabite readers this week, and in the end I decided to scrap it.  Why?  Well, my idea was to show that Unity was capable of procedural terrain generation on a massive scale (which it is), but what I came up with pales in comparison to what I came across within the Unity Community forum.  (link here)

A user by the name of Megaton has not only created an amazing Terrain Generator, but he’s also been kind enough to release it for free (here).

Also, be sure to check it out in your browser here, because it’s hard to explain how amazing it looks live.

 

So, in this article, I’m going to show a few sections of this very complex piece of code and do what I can to explain how something like this can be accomplished.  By comparison, my own little experiment looked far less realistic, and I think I would be doing an injustice for my readers by showing them something like that while knowing this was available to them for free.

The first thing we should look at is the setup of the variables – the ones that control the finer points of generation as a whole and make the world bumpy.  The developer who created this project placed these variables inside of a .js sale called “cgame”, and it reads like this:

#pragma strict
class cgame extends UnityEngine.Object {

 // Project
 var PRODUCT_NAME = "Procedural Terrain Generator";
 var PRODUCT_VERSION = "1.0";

 // Engine
 var GAMESPEED = 1.0;

 // Game World
 var WORLDSEED = 123;
 var WATER_COLOR = Color( 0.5, 0.6, 0.7 );

 var TERRAIN_SIZE = 256;
 var TERRAIN_GRIDSIZE : float = 200;
 var TERRAIN_GRIDVIEW : float = 10;
 var TERRAIN_GRIDCOUNT = 100;
 var TERRAIN_HEIGHT = 250.0; // default: 200
 var TERRAIN_MAX_SUBOBJECTS = 75;
 var TERRAIN_PLANE_QUADSIZE = 12.0;
 var TERRAIN_GRID_SIZE = 2000;
}
static var gCgame : cgame;
static function InitCgame() {
 gCgame = new cgame();
}

You can change the numbers in this section to get some varying results – things are labelled fairly well so theres really no need to go much into detail here.  What I will mention about how this script works is that it does continuously generate new terrain meshes that match up to the existing pieces – each has a unique name and they match up fairly well.

The magic of this effect comes from a mixture of scripts, but all seem to be centralized around terrain.js, which contains heading such as:

  • GET PLAYERS POSITION ON THE TERRAIN GRID
  • IF PLAYER STEPS ONTO A NEW TERRAIN GRID THEN ADD AND REMOVE PLANES
  • ADDS PLANES DURING PLAY
  • etc.

Each section in this portion of the script is very clearly labeled, and it is a great learning experience for intermediate unity js programmers.  I found that for me, working backward from this portion made things more understandable:

//----------------------------------------
 // ADDS PLANES DURING PLAY
 //----------------------------------------
 function TerrDrawRow( position : Vector3, tgF : Vector2, tgT : Vector2 ) {
 Math.Floor( tgF );
 Math.Floor( tgT );

 var gridsize = gCgame.TERRAIN_GRIDSIZE;
 while( tgF != tgT ) {
 var pos = position;
 pos[0] += tgF[0] * gridsize;
 pos[2] += tgF[1] * gridsize;
 var name = "X" + Mathf.Floor( pos[0] ) + "Z" + Mathf.Floor( pos[2] );
 if( !TerrPlaneExists( name ) ) {
 TPlaneNames.Add( name );
 var plane : Transform = Instantiate( t_plane, pos, Quaternion.identity ) as Transform;
 plane.parent = parentObject;
 plane.name = name;
 var soc : Terrain_Plane = new Terrain_Plane( plane );
 terrain_planes.Add( soc );
 heightmodqueue.Add( soc );
 }
 tgF[0] += tgF[0] != tgT[0] ? Mathf.Sign( tgT[0] - tgF[0] ) : 0;
 tgF[1] += tgF[1] != tgT[1] ? Mathf.Sign( tgT[1] - tgF[1] ) : 0;
 }
 }

Of course you do need to bounce around between the various functions, and some are spread across multiple files, but things start clicking into place.  This section will add the new terrain objects and name them while attaching them to a parent object.  At the same time, it only does so if the name doesn’t already exist.

Admittedly, the author admits that the generation isn’t 100% seamless – in some areas where one grid connects to another, you can literally see the seam where one ends and the next begins.  However, it isn’t something that detracts from the overall usefulness of the tool.

If you download and use this yourself on a project, load up the test scene and alter the movement controls of the “player” to allow yourself a high ground/air speed and an increased jumping ability.  In doing, you’ll be able to take yourself across the landscape for a very long and scenic ride.

Jan 202012
 

I had a big plan for this week’s Megabite, but my demonstration wasn’t quite ready in time.  Fortunately though, it was on this very same topic, and it gives us all something else to look forward to next friday.

In this article, I’m going to answer the question that I’ve gotten a few times regarding Stellar: “How did you create the blocks”? The blocks in question are the ones within the “Skirmish Mode”, seen here:


Well, the blocks themselves were easy to create, but it’s the tunneling system and colorization script that really started bringing things together a bit more.  It wasn’t long ago that the colors were random and chaotic.

The script works at first in a similar manner to a roguelike – first you fill all the spaces, then you actually cut away the areas you want open.  In doing, you’ll save yourself a massive headache.  So with a script like the one below, what we’re doing is basically making a giant grid of thousands of tiny blocks:

for (var i =0; i < cuber; i++) {
 if (i > 0) {
 Status = "Generating " + (i).ToString() + " of " + cuber.ToString();
 }
 if (i == (cuber - 1)) {
 Status = "Manipulating Terrain Elements";
 }
 yield;
 transform.position.x = transform.position.x + cubeSize;
 for (var i2=0; i2 < cuber; i2++) {
 var eachCube = Instantiate (genCube, transform.position, Quaternion.identity);
 eachCube.renderer.material.color = Color(0.51,0.36,0.13,1);
 transform.position.z = transform.position.z + cubeSize;
 }
 transform.position.z = minZ;
 }

A few important things to note here:

  • I used “yield;” in the script so that the GUI could update and allow a user to not think that the game has frozen.  Generating a massive world can take a lot of time.
  • If you’re going to try this, make sure your camera is not looking at the generation in progress.  Cull away the rendering until after all is finished and you’ll save yourself much needed processing power.
  • I’ve rendered each cube as my standard “dirt” color.  The idea is to add in “veins” of slightly different colors to give the cubes a more natural look.
  • The cubes themselves are simply unscripted primitive cubes with a standard grey appearance by default.  They are very simple, and only contain a collider component.

Now, we want to set up a starting location for our tunneling system.  What we’re doing here is moving a gameObject around the cubes and shooting out a physics ray to select cubes that lay in front of it.  A ray is a single line, so we’re also going to add two additional lines to cut out a larger path.  In addition, we’re going to do this in short bursts of 100 meters and have the tunnel weave a bit randomly.  When the script detects cubes, it destroys them and we have a straight line of demolition.  The code for the tunnel detector looks something like this:

function KillFwd() {
 var hits = (Physics.RaycastAll (transform.position, transform.forward, 100));
   for (hit in hits) {
    if (hit.transform.tag == "genBlock"){
    Destroy(hit.transform.gameObject);
    }
   }
}

The code that executes the above script is:

function KillVein(startHere : Vector3) {
 Status = "Creating Routes & Generating Frustration";
 yield;
 for (x=0; x < 4; x++) {
 transform.position = startHere;
 transform.rotation = Quaternion.identity;
 transform.Rotate(Vector3.up * (90 * (x+1)));
 for (i=0; i < 100; i++) {
 KillFwd();
 transform.Translate(Vector3.right * 10);
 KillFwd();
 transform.Translate(Vector3.left * 20);
 KillFwd();
 transform.Translate(Vector3.right * 10);
 var move = Random.Range(0,90);
 var rot = Random.Range(-60,60);
 transform.Translate(Vector3.forward * move);
 transform.Rotate(Vector3.up * rot);
 }
 }
}

We do this in a few places, and what we end up with is the leftover “islands” that create the world.  When I lay down the enemy spawn points and bases, I have some additional code that clears the area first, but that’s pretty much the basics.

Colorization is done in a very similar way – we randomize more lines and instead of destroying them, this time we change the way they are displayed:

function StabColor(theColor : Color) {
 var hits = (Physics.RaycastAll (transform.position, transform.forward, 100));
 for (hit in hits) {
   if (hit.transform.tag == "genBlock"){
   hit.transform.renderer.material.color = theColor;
   }
 }
}

As you can see, it’s a very similar script.  The script that runs this function is actually a bit more complex than the tunneling though:

function AddColor() {
 var colorHere : Vector3;
 for (var i = 0; i < 3; i++) {
 colorHere.x = Random.Range(minX, maxX);
 colorHere.y = 0;
 colorHere.z = Random.Range(minZ, maxZ);
 Colorize(colorHere, Color(0.66,0.34,0,1));
 }
 for (i = 0; i < 3; i++) {
 colorHere.x = Random.Range(minX, maxX);
 colorHere.y = 0;
 colorHere.z = Random.Range(minZ, maxZ);
 Colorize(colorHere, Color(0.60,0.40,0,1));
 }
 for (i= 0; i < 15; i++) {
 colorHere.x = Random.Range(minX, maxX);
 colorHere.y = 0;
 colorHere.z = Random.Range(minZ, maxZ);
 ColorBomb(colorHere, Color(0.71,0.29,0,1));
 }
}
function ColorBomb(startHere : Vector3, theColor : Color) {
 var range : int = Random.Range(15, 45);
 var blocks : Collider[] = Physics.OverlapSphere(startHere, 100);
 for (each in blocks) {
 if (each.transform.tag == "genBlock") {
 each.transform.renderer.material.color = theColor;
 }
 }
}
function Colorize(startHere : Vector3, theColor : Color) {
 //print(startHere + " " + theColor);
 Status = "Creating Routes & Generating Frustration";
 yield;
 for (x=0; x < 4; x++) {
 transform.position = startHere;
 transform.rotation = Quaternion.identity;
 transform.Rotate(Vector3.up * (90 * (x+1)));
 for (i=0; i < 100; i++) {
 StabColor(theColor);
 transform.Translate(Vector3.right * 10);
 StabColor(theColor);
 transform.Translate(Vector3.left * 20);
 //StabColor(theColor);
 transform.Translate(Vector3.right * 10);
 var move = Random.Range(0,90);
 var rot = Random.Range(-60,60);
 transform.Translate(Vector3.forward * move);
 transform.Rotate(Vector3.up * rot);
 }
 }
}

The “ColorBomb” function has another really nifty tool – Physics.OverlapSphere.  With this handy unity function, we’re able to grab a “circle” of blocks and colorize them.  With this, I was able to add a bit more of a blotchy and natural look in addition to the veins of color.

I’m working on a separate project to show some of the integrated features of the Unity Terrain generator – hopefully it will be ready for next week’s Megabite.  Until then, if you have any questions about what you see here, feel free to drop a comment below!

Jan 132012
 

When I first began with Unity, I noticed a great deal of things in tutorials were coded within the Update() section of a script.  As you may already know, this portion of a script will execute once per frame.  Depending on the framerate of a user, this could be a good thing or a bad thing.  If anything, it’s unpredictable at best and taxing on a machine if you have a piece of complex code within.

The option also exists for FixedUpdate(), which is more predictable but can have a tendency to be just as taxing for complex code.  What do we do when we want to run something every second or so instead of every rendering frame or according to the physics timescale?  For that, we use the Invoke methods.

//This script will call our TestFunction() every 2 seconds
function Start() {
   InvokeRepeating("TestFunction", 2, 2);
} 

function TestFunction() {
print("Test function run at: " + Time.time);
}

In combination with CancelInvoke(), this method is far less taxing overall, especially if you’re using complex code.  As opposed to Update, if we run the code once per second and the game is running at 60fps, we’ve just saved our machine from running the code 59 extra times.  If you have some type of loop in the function itself or anything that would have drained resources, this can be a godsend.

Invoke() itself has a great functionality as well, and can be used in conjunction with things like CancelInvoke() or isInvoking().  Invoke() allows you to also set a delay on a function without the hassle of using yield in the first line of code, and it gives you more versatility overall with the possibility of stopping the code from executing if needed.  For example:

//This script does something like a megaman-type cannon effect.  The user has to hold down the space key for 3 seconds, uninterrupted by enemy fire.  If interrupted, the fire functions will cancel out.
private var chargedUp : boolean = false;
var chargeAnimation : Transform;
var gunTip : Transform;
function Update() {
  If (Input.GetKey("space") && !isInvoking("FireCannon") && !chargedUp) {
     ChargeGun();
     Invoke("FireCannon", 3);
  }
} 
function ChargeGun() {
     Instantiate(chargeAnimation, gunTip.transform.position, Quaternion.identity);
     Invoke("ReadyCharge", 3);
}
function ReadyCharge () {
chargedUp = true;
}
function FireCannon() {
     if (Input.GetKey("space") && chargedUp == true) {
       Fire();
     }
}
function OnCollisionEnter (other : Collider) {
     if (other.transform.tag == "enemyBullet") {
       if (isInvoking("FireCannon")) {
         CancelInvoke("FireCannon");
       }
       if (GameObject.FindGameObjectWithTag("chargeAnimation")) {
         var theAni : Transform = GameObject.FindGameObjectWithTag("chargeAnimation");
         Destroy(theAni.gameObject);
         CancelInvoke("ReadyCharge");
       }
     }
}

Because of the isInvoking() directive, the above script is responsive immediately but will only execute once if the conditions are met.  Obviously the Fire() function would reset chargedUp to false as well as actually launch the projectile, but the innovative nature of isInvoking() allowed us to also set the rate of refire unless we decided on extra delay between shots.

For things such as general movement, the Update section of script is safe enough to use.  The same can be said regarding camera movement or a few other common features.  In truth, if your project is small you may not even see the difference in performance for a PC/Mac or Web build because of the powerful processors found in most gaming machines.  Where you may see the most benefit in something like this is in mobile development or in large projects with a lot going on at once.  Even so, it’s best practice to try and write your code to not do anything unnecessary.  That way, additions to your game will have more available resources and you can do more at once.

With things available such as InvokeRepeating(), you might immediately be able to move code from Update() into its own function and set a delay of your choosing.  Even if you execute once every 0.1 seconds, you should immediately have a performance increase of that script section of at least 200% (at 30fps, which is low).  InvokeRepeating can be launched from the Start() of a script, or from another function if needed.

As a side note, simply running the command CancelInvoke() without adding the name of a function will actually cancel all invocations on the current script.  After learning these commands and really starting to work with them, I can safely say there is a lot of my old code that could be better revised.  Learning these as soon as possible will likely safe you a great deal of time and energy.  :)

Jan 122012
 

When working with a headset (or in this case two), the process of reviewing it can be difficult unless you center on just a single use.  The other aspect of this is comfort – making sure things can be adjusted and “broken in” in the case of noise canceling devices.  In the case of both the 1300 and 1500 Corsair Vengeance models, they are made to clamp tightly onto your skull and keep out stray noises – I wanted to be sure I could accurately judge the level of “comfort” with something like this, and for that, it takes a little breaking in.

To that end, I worked with each of these headsets for about a month apiece.  Not only did I play games while using them, but I also watched movies, worked with audio editing for game development, tested the microphones with voice and ambience, etc.  In this review, I will score each of the headsets separately and speak about the pros and cons of both.

The 1300 Model:

The Corsair Vengeance 1300 is the analog model – the long, high-quality connection wire ends with both a headphone and microphone analog jack as opposed to a USB connector.  As such, it lacks the features that can be supplied by using the energy a USB jack can provide.  The volume control is an analog wheel set in a control device along the wire (which rests at about lap-level), and the microphone toggle is a hardware switch.

That said, the quality of sound and general performance of the headset should exceed all expectations.  While I was wary at first about the differences that might be caused by an analog headset, I can truly say that there was little to no difference in comparison to the Logitech brand USB headset I used previously.

The ear pads on this headset are leather-like material filled with memory foam.  Even in times of long use, they stay very comfortable.  In comparison to smaller ear pads, these large, noise-cancelling versions set around your entire ear instead of pressing your own ears into your head.  They seem to completely silence the ambient noise in the room around you and allow you to focus completely on the task at hand.

The microphone stick can be bent and manipulated to whatever position you choose, and the sound quality of the mic itself leaves little else to be desired.  I used it for everyday things such as Skype conversations and Ventrillo, but I also loved it for recording my voice for use in YouTube videos and game voiceovers.

Audiophiles may have issue with the fact that an analog connection will only supply stereo sound as opposed to 5.1 or 7.1.  To that end, I would argue that you only have 2 ears, and for both everyday purposes as well as gaming, most users may not even notice a difference.  A headset is pressed against your head, so the benefit of multiple speakers might escape the average user.  For those that want a truly immersive experience, I would recommend…

The 1500 Model:

For this model, Corsair decided to exchange the synthetic leather for a cloth mesh, which increases the breathable nature of the headset and is better suited for longer usage times.  At the same time, it should be made clear that there is little to no effect in how much this affects the noise-cancelling properties of the headset itself.  With both models, you can expect to be able to focus your attention on the task at hand without distraction from the sounds around you.

You’ll also notice that the sides of the headset are constructed of polished chrome, which I thought was an impressive stylistic choice.  In addition, the headset volume controls are powered by the USB jack of your computer which allows them to light up and be color-coded.  If your mic is muted, the entire unit is lit up in red.  Otherwise, it stays a cool blue (as seen in the picture here).

The 1500 makes full use of Dolby 7.1 surround sound, creating a truly immersive gaming experience.  It’s a great tool for getting the edge on opponents in your favorite FPS game, for example, and being able to hear every little sound in the distance.  The mic is similar in design to the 1300, and the perfect tool for communication or sound recording.

Despite the multitude of additional features, the 1500 model is only slightly more costly.  While both models are of terrific quality overall, if one is deciding between the two, the 1500 is highly recommended if you have a free USB port available.

The only con I can see in this model is that the available drivers are limited to Windows-based machines.  With the increase in the popularity of both Mac and linux-based games, official driver support for those platforms would really put this model over the top.  (While untested in a linux environment, this model did function correctly in OSX without hassle and without drivers.)

Conclusion:

The main complaint in regards to noise-cancelling headsets will be in regards to overall comfort – especially for those of us who use headsets almost 100% of the time.  To that, I will be sure to point out that these models both increase in comfort as time wears on and the materials stretch and “break in” to the size/shape of your head.  Like all devices of this nature, they may seem a bit constricting at first and perhaps a bit more oversized than you are used to, but it won’t be long until they feel like a natural extension of your PC experience.

I knew when Corsair decided to allow us the opportunity to use these review copies that the process would be a long one, but I can safely say that it has also been a completely enjoyable one.  Both of these headsets have become permanent additions to my working and gaming computers, respectively.  For those readers that are in the market for a new headset device, be sure to take a look at these models – I don’t think anyone will be disappointed.

To attribute scores to the headsets themselves, I would rate the 1300 model as a 4/5 and the 1500 model as a 4.5/5.  Again, you can’t go wrong with Corsair brand headsets, regardless of purpose.

Jan 062012
 

In episode #10, I covered my first attempt at creating an AI system on a 2d plane.  Now, just 5 episodes later, I’m happy to report that I’ve been extremely happy with the advancement through the weeks and have adapted the original code to something more universal and configurable.  Infact, the same code is used for any of my AI enemies in the development of Stellar.  It’s set up so that customization takes place within the inspector, and ship models are basically plug and play – I import, size them, make em into a prefab, and just attach my script.  Easy peasy.

That said, such a script comes with many variables to maintain:

var reactionDist : float = 10;
var strafeSpeed : float = 25;
var ftReacDist : float = 10;
var rotSpeed : float = 100;
var baseSpeed : int = 25;
var fireAtEnergy : int = 75;
var explosion : Transform;
var bullet : Transform;
var firefrom : Transform;
var damping = 30.0;
var smooth = true;
var canBounce : boolean = true;
var maxHealth : int = 100;
var fireRate : float = 2;
var fireCost : int = 30;
var recharge : float = 0.1;
var targetTag : String = "Player";
var targetRange : int = 100;
var canMine : boolean = false;
var kamikaze : boolean = false;
var thisIsABoss : boolean = false;
var tripleShot : boolean = false;
var tripleSpread : float = 7;
var willMine : boolean = false;
var retribution : boolean = true;
private var target : Transform;
private var front : boolean = false;
private var left : boolean = false;
private var right : boolean = false;
private var farRight : boolean = false;
private var farLeft : boolean = false;
private var lastRand : float = 0;
private var ranDir : int = 0;
private var health : float = 100;
private var playerDist : float;
private var lastfire : float = 0;
private var player : GameObject;
private var playerArr : GameObject[];
private var lastCheck : float = 0;
private var lastPorted : float;

While it may seem complex, I basically replaced any of the numbers or specifics within the script with a variable.  In doing, every little thing can be changed until the movement, reaction time, attack ability, etc. all meet my expectations.

For this article, I’ll cover some of the major functions and explain how they work without errors.  Nothing is ever “perfect”, s this may not be the final product, but it works perfectly for what I need right now.

First, let’s look at how an enemy selects a target:

function findPlayer() {
 if (Time.time > lastCheck) {
  lastCheck = Time.time + 3;
  if (targetTag == "Player") {
  player = GameObject.FindGameObjectWithTag(targetTag);
  } else {
  playerArr = GameObject.FindGameObjectsWithTag(targetTag);
  var rnd = Random.Range(0, (playerArr.Length));
  player = playerArr[rnd];
  }
 var enemies : Collider[] = Physics.OverlapSphere(transform.position, 100);
 for (each in enemies) {
  if (each.transform.tag == "decoy") {
  player = each.transform.gameObject;
  }
 }
 }
}

What I’ve done here is allowed myself to change what the primary target of an enemy is.  In my game, enemies may simply ignore the player and go after another tag-based object, such as a player’s structures.  What we see above will target a player if the inspector has it labelled as such, but we can use any tag we choose otherwise.  At the bottom, you can see that each time the script is executed, an enemy will search within 100 units for a unit with the tag of “decoy” as well.  If this is true, the target first becomes the decoy game object.

This next chunk of code is found within the “Update” section, and is executed every frame:

var inft : RaycastHit;
 var didhit = Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), inft, 100, 1 << 8 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 0);
 var goodShot : boolean = false;
 if (didhit) {
 if (inft.transform.gameObject.tag == "Player" || inft.transform.gameObject.tag == "playerStruct" || inft.transform.gameObject.tag == "decoy") {
 goodShot = true;
 }
 if (canMine == true && inft.transform.gameObject.tag == "genBlock") {
 goodShot = true;
 }
 }
 if ((playerDist < targetRange) && goodShot == true && (health > fireAtEnergy) && (Time.time > lastfire)) {
 lastfire = (Time.time + fireRate);
 health = health - fireCost;
 var fired = Instantiate (bullet, firefrom.transform.position, Quaternion.identity);
 Physics.IgnoreCollision(fired.collider, collider);
 fired.transform.parent = transform;

Im a big fan of the way this one worked out.  In the previous code, an enemy would fire whenever a “Player” was within range – whether or not they were actually aimed at the player.  Of course, we could have done a transform.LookAt, but that would have been unnatural and would have interfered with the way the ship navigated the terrain.  In this instance, we are telling the ship only to fire if the line of sight actually comes from the front of the ship and lands on an object with the labels of “Player”, “playerStruct”, or “decoy”.  In doing, we’ve also solved the problem about firing through walls to get at a target.

Within OnColisionEnter(), we have:

if (transform.tag == "decoy") {
  if (collision.transform.gameObject.tag == "enemybullet") {
  health = health - 75;
  }
 }

Decoy?  That’s right – even though decoy is a target, the same AI code controls the movement of a decoy ship!  This saves us from having to create a whole separate script, and everything is controlled by whether or not the ship has a “decoy” tag on it.

Now, for all intents and purposes, the AI is functional and has no real issue with navigation.  When we play through, we just take a look at various what-if scenarios and go from there.  This is where the idea of “retribution” came from, and this simple little piece of code causes a ship that would normally only attack buildings to turn and attack a player if fired upon:

if (retribution) {
 if (GameObject.FindGameObjectWithTag("Player")) {
 player = GameObject.FindGameObjectWithTag("Player");
 target = player.transform;
 }
 }

Retribution is a toggled ability in the inspector as well, so I can choose (like everything else), if this is something that the enemy naturally does.  By building the script in this way, the AI has become much more robust than before, and each enemy type seems to have a personality of its own.

Building an AI with Unity has been a lot of fun, and I really can’t wait until things for this title are more finalized.  When that happens, I’ll see if it will be possible to release the AI code in its entirety for all to see.  For now, if anyone has questions, feel free to drop me a comment and I’ll get back to you as soon as possible!

Dec 302011
 

Unity makes everything in the world of sound fairly easy to understand and manipulate to your liking.  Even so, there are a lot of settings that should be understood before diving in to the audio components to help with performance and overall game size.

Import

First, you’ll want to import sounds into your project.  While you can do that with any type of sound file, you’ll want to examine the settings before attaching it to a prefab or GameObject.  An Audio Importer component will be automatically attached, and from there you’ll be able to set your settings to maximize performance.

First, take a look under Audio Format.   Whether or not you want your sound compressed will be dependent on what you want to use the sound for.  While uncompressed sounds will have a higher level of quality, this setting is best used for very short sound effects as opposed to something like in-game music.  In conjunction with this selection, you’ll also want to pay close attention to the “Load Type” section, where you can control how the audio data is pulled from disk and into memory.

Using “Decompress on Load” will be best for those very short sounds – this will keep your game from locking for a frame or two when a new sound happens within a scene.  Basically, you are opting to have the sound readied when the scene is loaded.  For larger sounds, you can choose to keep the file “Compressed in memory”, which will decompress the file as it is played.  If your file is highly compressed, this will cause a bit of load on your target machine, but it will keep initial load times down and keep your available memory more free.  Lastly, you can opt to simply stream the file from the hard drive by selecting “Stream from Disk” – this will save you on memory and loading, but because you are accessing the disk you wouldn’t want to use this setting for more than a few tracks at the same time.  Ideally, just use this setting for music since you will likely only have a1 song playing at once.

The level of compression (if you are choosing to compress your file) will be selectable via this window as well.  You want to aim to compress as much as possible while keeping your file usable for your own purpose.  This may be a setting you’ll want to experiment with – audio files can quickly drive up the file size of your game.

Listen

In each scene, you’ll want to always have just one audio listener.  This will be attached to a main camera by default, which effectively places your player’s head wherever the camera is.  However, you may want to opt into having your listener attached to your game character or some other game object.  If you add the audio listener component to any other object, you’ll want to make sure there is always one in existence in the event your character dies, as an example.  Without a listener, all sound will disappear.

In the cases where I’ve done this myself, often times the best result was achieved by disabling the listener from the player and immediately enabling one attached to the main camera (in the same function that would kill the player).  When the new player spawns, you simply reverse the process in the spawning function.

Effects

Sound effects are versatile, and you can basically opt to use them however best fits your game.  For instance, you can attach a sound to a GameObject and check the box labeled “Play on Awake” – if this is done, the sound will play as soon as the object exists.  While this may seem to be a good object for something like a bullet, you should understand that if the object is destroyed, the sound will disappear with it.

For our purposes, when you examine from a common FPS type perspective, picture we are firing a rifle.  The bullet itself may have a whizzing sound as it flies through the air, but it’s highly likely we’re going to want to attach the gunfire sound to the rifle itself.  This will do two things: keep the firing sound at a constant volume (keeping it from fading as it gets further away), and also keep the sound playing in the event the bullet is destroyed immediately.

Sounds can be added into the inspector like other variables by declaring them as AudioClip.  Once that is done, you can really use basic scripting to customize to your liking.  For example:

var myFireSound : AudioClip;
var myReloadSound : AudioClip;
var reFire : Float;

function Update () {
if (Input.GetKey(“space”) && Time.time > reFire) {
reFire = Time.time + 1;
FireGun();
}

if (Input.GetKey(“r”) && Time.time > refire) {
reFire = Time.time + 1;
ReLoad();
}
}

function FireGun () {
audio.clip = myFireSound;
audio.Play();
}

function Reload () {
audio.clip = myFireSound;
audio.Play();
}

Music

I don’t doubt that one of the most common audio questions relates to adding in-game music.  Unity doesn’t have a specific component for it, but it’s fairly easy to design your own.  In the same vein as the example above, the easiest way will be to attach your music files as inspector variables (perhaps even as an array), and play them accordingly.

An example of this might be something like this:

var musicArray : AudioClip[];  //attach as many tracks as you want in the inspector

function Start() {
ChangeTrack();
}

function ChangeTrack() {
var trackNum = Random.Range(0,musicArray.Length);
audio.clip = musicArray[trackNum];
audio.Play();
WaitTrack();
}

function WaitTrack() {
yield WaitForSeconds(audio.clip.length);
ChangeTrack();
}

Something like this would work for a quick music solution, and extra customization could be added for different areas or situations, etc.  Of course, the GameObject this script is attached to will need to have an audio component – simply don’t attach a specific clip and instead load up the array we’ve just created.

Rolloff

The way sound reacts to its distance from an audio listener component is known as rolloff.  This can be customized like everything else of course, but the easiest to understand will be a simple linear rolloff.  You can find this option available as a visual graph on any audio source component, and depending on what you are doing within your game, you will simply want to be sure that your listener falls within the ranges that the sound will make available.

The easiest way to acclimate yourself with how rolloff affects your game is to play the title within the editor.  As with all of these scripts and components, learning by doing will be invaluable.

Thanks for reading – if anyone gets hung up or has audio issues, feel free to drop me a line in the comments here.  :)

Dec 232011
 

In Megabite #11, I discussed how to do the basic layout features for both GUI and GUILayout.  In this release, what I’ll be discussing is a bit more in-depth (You will want to already have a basic understanding of the previous article.)

The first thing I want to talk about is GUILayout.Window, which is a very cool feature, especially if you are planning on having a draggable elements such as an inventory system or perhaps a status window.  The command is simple enough, but the setup for a GUI window is a bit more complex than to just add your information into OnGUI.  First, you will want to declare a Rect variable and give it a name:

var myWindow : Rect;

function Awake() {
   myWindow = Rect(0,0,300,100);   //This will default our window to the upper-left corner, and set the minimum size as 300 wide and 200 tall.
}

Now we can set up our window command within OnGUI:

function OnGUI {
myWindow = GUILayout.Window(0, myWindow, MyGUIFunction, “My first draggable window!”);
}

At this point, we have our OnGUI function gather information from 2 places – our variable and also a function we will now create.  The “0″ in the commad above symbolized an ID number for the window, which is also found in this new function.  Because all of our regular GUI stuff will be actually located within this fuction, you may find this method to be a much cleaner way of laying out your regular GUI elements to begin with.

function MyGUIFunction (id: int) {
   GUILayout.BeginHorizontal(“box”);
      GUILayout.Label(“This box is draggable”);
   GUILayout.EndHorizontal();
   GUI.DragWindow();
}

Running your game with all of these pieces of code within a .js file should give you a draggable window.  The initial placement of the window can be manipulated in the section where you declare your Rect variable, and the window should resize based on the content as long as you are using GUILayout as opposed to simply GUI.  Of course, both of these are options an much of how you use this type of setup will be largely based on your own choices.

Next, I wanted to discuss the addition of textures into your GUI.  This could be useful for a lot of reasons, and you can use a standard picture or sprite-type image, or if you use Unity Pro you can actually add a render texture which is quite nice – basically the results of a camera can be sent into a texture format.  If you want a “video” element within your GUI (like a spinning 3d item, etc.), that’s the way to go.

Because access to Unity Basic is more universal, I’ll cover that end of things.  First, you’ll want to declare a texture variable:

var myPicture : Texture;

When you do that, you’ll end up with a drag/droppable section in the editor inspector.  You can import any picture you like into Unity and simply assign the image to the inspector.  Now you can use the GUI.Box or GUILayout.Box elements to display your texture as opposed to showing text.  if using the same code from above, just do it like this:

function MyGUIFunction (id: int) {
   GUILayout.BeginHorizontal(“box”);
      GUILayout.Box(myPicture);
   GUILayout.EndHorizontal();
   GUI.DragWindow();
}

Now you’ve got a fancy picture within your draggable window.  If you managed a render texture, you’ve actually got a video feed, which is also awesome. :)

Now, we’re going to talk about dynamic generation.  With the clean, functional layout we have here, it’s easy to use a FOR loop to actually make your window display information from an Array in a very dynamic way.  In this example, we’re going to replace our function after declaring an array.  For now, we’ll fill that array with a few strings for testing purposes.

var myArray = new Array(“One”, “Two”, “Three”, “F0ur”, “Five”);

function MyGUIFunction (id: int) {
   GUILayout.BeginHorizontal(“box”);
     for (var i=0; i < myArray.Length; i++) {
       GUILayout.Box(myArray[i]);
     }
   GUILayout.EndHorizontal();
   GUI.DragWindow();
}

What will happen here is that our draggable window should have 5 boxes – one for each element in our array.  You may want to eventually add spacing and such depending on what you’re going for, but this should give you an idea of what is possible.

Overall, there are a lot of options within the GUI command subset.  GUI elements are difficult to master, but they are not only a handy thing to learn but also an important part of any game for navigation, inventory, statistics, status readouts, and thousands of other uses.

The above concludes the actual “lesson” portion, but as an added bonus, I’ll paste a few pieces of GUI code functions below for some extra examples:  (as of today, this is code included in “Stellar“, and can be seen in-action here.)

function MakeWindow (id : int) {
 for (i = 0; i < mats.Length; i++) {
 GUILayout.BeginHorizontal ("box");
 GUILayout.Box(camArray[i], GUILayout.ExpandWidth(false));
 GUILayout.Box("" + mats[i], GUILayout.ExpandHeight(true));
 GUILayout.Box("x " + gotItems[i], GUILayout.ExpandWidth(false));
 GUILayout.EndHorizontal ();
 }
 GUI.DragWindow ();
}
function MakeCraft (id : int) {
 GUILayout.BeginHorizontal ();
 GUILayout.BeginVertical("box");
 GUILayout.Box("Available Upgrades:", GUILayout.ExpandHeight(false));
 scrollPosition = GUILayout.BeginScrollView (scrollPosition, GUILayout.Width (250), GUILayout.Height (450));
 if (gotItems[0] >= 10 && gotItems[1] >= 1 && enginePower <=1150) {
 GUILayout.BeginHorizontal ("box");
 GUILayout.Box("Engine Power");
 if (GUILayout.Button("Upgrade")) {
 gotItems[0] = gotItems[0] - 10;
 gotItems[1] = gotItems[1] - 1;
 enginePower += 50;
 }
 GUILayout.EndHorizontal ();
 }

 if (gotItems[0] >= 10 && gotItems[2] >= 1 && rotSpeed <= 450) {
 GUILayout.BeginHorizontal ("box");
 GUILayout.Box("Rotational Speed");
 if (GUILayout.Button("Upgrade")) {
 gotItems[0] = gotItems[0] - 10;
 gotItems[2] = gotItems[2] - 1;
 rotSpeed += 50;
 }
 GUILayout.EndHorizontal ();
 }

 if (gotItems[0] >= 10 && gotItems[1] >= 1 && gotItems[2] >= 1 && fireRate >= 0.3) {
 GUILayout.BeginHorizontal ("box");
 GUILayout.Box("Firing Rate");
 if (GUILayout.Button("Upgrade")) {
 gotItems[0] = gotItems[0] - 10;
 gotItems[1] = gotItems[1] - 1;
 gotItems[2] = gotItems[2] - 1;
 fireRate -= 0.1;
 }
 GUILayout.EndHorizontal ();
 }

 if (gotItems[1] >= 5 && gotItems[2] >= 5 && gotItems[3] >= 2 && bulletCost >= 8) {
 GUILayout.BeginHorizontal ("box");
 GUILayout.Box("Firing Cost");
 if (GUILayout.Button("Upgrade")) {
 gotItems[1] = gotItems[1] - 5;
 gotItems[2] = gotItems[2] - 5;
 gotItems[3] = gotItems[3] - 2;
 bulletCost -= 2;
 }
 GUILayout.EndHorizontal ();
 }

 if (gotItems[3] >= 5 && gotItems[4] >= 2 && boostPower <= 14) {
 GUILayout.BeginHorizontal ("box");
 GUILayout.Box("AfterBurners");
 if (GUILayout.Button("Upgrade")) {
 gotItems[3] = gotItems[3] - 5;
 gotItems[4] = gotItems[4] - 2;
 boostPower += 1;
 }
 GUILayout.EndHorizontal ();
 }

 if (gotItems[0] >= 30 && gotItems[1] >= 5 && gotItems[2] >= 5 && gotItems[3] >= 5 && gotItems[4] >= 5 && radar == false) {
 GUILayout.BeginHorizontal ("box");
 GUILayout.Box("Install Radar");
 if (GUILayout.Button("Install")) {
 gotItems[0] = gotItems[0] - 30;
 gotItems[1] = gotItems[1] - 5;
 gotItems[2] = gotItems[2] - 5;
 gotItems[3] = gotItems[3] - 5;
 gotItems[4] = gotItems[4] - 5;
 radar = true;
 }
 GUILayout.EndHorizontal ();
 }

 if (gotItems[0] >= 20 && gotItems[1] >= 5 && gotItems[2] >= 5 && gotItems[3] >= 5 && bounce == false) {
 GUILayout.BeginHorizontal ("box");
 GUILayout.Box("Bouncing Bullets");
 if (GUILayout.Button("Install")) {
 gotItems[0] = gotItems[0] - 20;
 gotItems[1] = gotItems[1] - 5;
 gotItems[2] = gotItems[2] - 5;
 gotItems[3] = gotItems[3] - 5;
 bounce = true;
 }
 GUILayout.EndHorizontal ();
 }

 GUILayout.EndScrollView ();
 GUILayout.EndVertical();
 GUILayout.BeginVertical ("box"); 
 GUILayout.Box("Current Stats:", GUILayout.ExpandHeight(false));
 //GUILayout.Box("Stats:", GUILayout.ExpandHeight(true));
 GUILayout.Label("Engine Power: " + enginePower);
 GUILayout.Label("Rotational Speed: " + rotSpeed);
 GUILayout.Label("Firing Rate: " + fireRate + " Sec. Delay");
 GUILayout.Label("Firing cost: " + bulletCost + " Energy");
 GUILayout.Label("Afterburners: " + boostPower + "x Speed");
 if (GUILayout.Button("Open Loot Inventory")) {
 showInv = true;
 }
 if (GUILayout.Button("Show Recipie Book")) {
 showRecipies = true;
 cwindowRect = Rect(cwindowRect.x,cwindowRect.y,700,200);
 }
 GUILayout.EndVertical ();
 if (showRecipies == true) {
 GUILayout.BeginVertical ("box");
 //Recipie List
 scrollPosition2 = GUILayout.BeginScrollView (scrollPosition2, GUILayout.Width (250), GUILayout.Height (450));
 GUILayout.Box("Engine Power:\n10 Scrap Metal\n1 Plasmoid");
 GUILayout.Box("Rotational Speed:\n10 Scrap Metal\n1 Nebulite");
 GUILayout.Box("Firing Rate:\n10 Scrap Metal\n1 Plasmoid\n1 Nebulite");
 GUILayout.Box("Firing Cost:\n5 Plasmoids\n5 Nebulite\n2 Meteor Rocks");
 GUILayout.Box("Afterburners:\n5 Meteor Rocks\n2 Stellar Shards");

 GUILayout.Box("Install Radar:\n30 Scrap Metal\n5 Plasmoids\n5 Nebulite\n5 Meteor Rocks\n5 Stellar Shards");
 GUILayout.Box("Bouncing Bullets:\n20 Scrap Metal\n5 Plasmoids\n5 Nebulite\n5 Meteor Rocks");

 GUILayout.EndScrollView ();
 if (GUILayout.Button("Close Recipie Book")) {
 showRecipies = false;
 cwindowRect = Rect(cwindowRect.x,cwindowRect.y,500,200);
 } 

 GUILayout.EndVertical (); 
 }
 GUILayout.EndHorizontal ();
 GUI.DragWindow ();
}
Dec 162011
 

Working with Remote Procedure Calls – “RPC”s – is a bit confusing at first.  First, let me go into a bit of applicable context and make things more understandable.

An RPC is needed when we are going to execute a function on a remote machine while connected on a network.  They use what is called a “Network View” to accomplish this, and of course your game must be network-connected.  (There are plenty of different downloads via Unity and the Asset store directly that will get you that far to begin with).

The scripting behind an RPC works similar to a regular function, except it has a tag like this:

@RPC
function MyRPCFunction() {
iDidSomething = true;
}

To execute the function, you need to start it from the Network View component, which can be easily attached to any GameObject.  Via javascript, we do something like this:

networkView.RPC(“MyRPCFunction”, RPCMode.Server);

The RPCMode requirement is tell Unity who we are communicating with.  In this case, what would happen here is that the server for the game would get the “iDidSomething” variable changed, but nobody else would – including the original sender.  This feature is invaluable for manipulating data across a network.  When choosing a mode, we can choose:

  • All
  • AllBuffered
  • Others
  • OthersBuffered
  • Server

Now the trickiness lies in the contingency that we need to be careful to make sure everything flows.  Whatever object our script is attached to must have a Network View component, if we’re trying to change variables or execute things on another connection, we need to be certain that those things already exist on their system as well (If a server has a script that clients do not, for example.)

It can be frustrating at first, but eventually writing these functions becomes second nature.  Fortunately Unity’s development console will give you a list of RPC errors just like any other scripting issue.  For the most part, it will be fairly easy to pin down problems by running your editor as a server and a build as a client, and then vice-versa with your eye on the error readout.  In this way, you can see if the problem is client-side or server-side.

There are many different ways to set up the server/client relationship within Unity.  Because of a more recent project, most of my experience is with an Authoritative server setup, meaning that the server makes all the final calls – each client sends input to the server, and the server moves the player around on their own screen.  This choice was made to ultimately make the game “fair” for multiple players in the event that someone has a sub-par connection.   While I will show how this works within this article, I wanted to first touch on another subject that boggled me as I developed:

Network.Instantiate

There was a distinct lack of information out there on this subject, so I wanted to try and explain how this worked as it applied to me.  Being that my last project was my first networked project, there were a few things I needed to wrap my head around:

  • When we just use Instantiate on a server or client, nothing is networked automatically.  Thus, it can’t be seen on another machine unless we go the extra mile to be sure.
  • If we do an RPC call and make everybody Instantiate an object, that object is seen by all, but also controlled via each machine.  It STILL isn’t truly networked unless we go that extra mile.
  • Network.Instantiate will basically make a single object across ALL machines.  It does all the extra mile work for us, and it is controlled by the machine that spawns it.  If you are using this command, make sure it only is run by one machine (like the server).  If everybody runs the code at the same time, you will have a mess.

“The extra mile”

There are situations where we want to do something similar to Network.Instantiate, but perhaps not exactly.  So, let me be clear about what it actually does when we use it.  Network.Instantiate is powerful because it automatically serializes the object.  In essence, we do have a single object as far as the network is concerned, and when it is affected, it is affected network-wide.  In truth, the command is not as powerful as what it does behind the scenes – automatic serialization.

As we move forward, we will find a great many situations in which we want serialized data.  A health bar is a good example.  Let’s say for instance that an enemy spawns with 100 health.  That enemy is hit by an existing player, and now it has 50 health.  Now, a brand-new player enters the game.  Without serialized data, that new player would perceive that the enemy has full health if the data was not serialized correctly.

So, how do we serialize?  Well, we need a Network View to send/receive the data.  Whatever script contains the health variable can be dragged onto it so it is being “watched”.  Now, we need to tell unity what needs to be transferred over the net:

function OnSerializeNetworkView(stream : BitStream, info :NetworkMessageInfo) {
if (stream.isWriting) {
var healthC : int = currentHealth;
stream.Serialize(healthC);
} else {
var healthZ : int = 0;
stream.Serialize(healthZ);
currentHealth = healthZ;
} }

This section of code came directly from the unity reference for OnSerializeNetworkView.  This is another fancy built-in Unity function that comes in very handy for this exact purpose.  It determines automatically what to send/receive based on ownership, and it will be sure your health variable is the same throughout the network.

Back to the RPCs

After all that, we now understand a bit more about the inner-workings of a network.  Now, let’s put it into a basic, understandable script.  What we’ll do here is have an object that is instantiated into an auth-networked game (Not network.instantiated, just regularly.)  As such, both the player and the server see it on their own screens, and we want to take the player input and give it to the server to make our object shoot.

function Update() {

if (Network.isClient) {
if (Input.GetKey(“space”)) {
shootButton = true;
} else {
shootButton = false;
}
if (shootButton = true && Time.time > nextFire) {
nextFire = Time.time + 1.5;
networkView.RPC(“Fire”, RPCMode.Server);
}
}
}

@RPC
function Fire() {
var fired = Network.Instantiate(bullet, transform.position, Quaternion.identity,0);
fired.GetComponent(bulletControl).enabled = true;
}

So, in this case our player’s spacebar is being monitored for input and rate of fire.  On the server side, we have the server create the bullet and enable the script to control how it moves.  (That way seemed to simplify things much more for me when dealing with eliminating the bullet later in a very clean manner.)  We’ve minimized the amount of RPC data that will be sent for this scenario, which will save a bit of bandwidth as well (instead of sending an RPC at every keypress, we do it only when something can be fired.)  In addition, because the server created the bullet, the server can easily destroy it with Network.Destroy.

Bufferiffic

Lastly, I wanted to speak about the buffer.  Network.Instnatiate automatically does it, so it’s likely that it’s something you’ll want to consider in your design.  An RPC function to “All” or “Others” can also be “AllBuffered” or “OthersBuffered”.  When you buffer, you are keeping a queue of commands that will execute for players if they connect to the server after the commands are run.

This is very useful to consider, because the last thing you want is non-synchronized objects in-game because of bad timing.  RPCs can add things to the buffer, and things can also be manually removed from the buffer in the same manner.

So, before you have a client fire out an RPC call to All or Others, be sure to ask yourself if a player joining thereafter will need to know that this thing just happened.  If so, you will need to be sure your RPCMode is buffered.

 

Dec 092011
 

One of the most important things to make note of with the Unity GUI system is that everything within the OnGUI () function will run twice per frame (Correction thanks to AngryAnt via the comments: OnGUI is not run twice per frame. It’s run once per event. By default that is two – one layout event and one repaint event. If, however, you have mouse or key events you’ll get more invocations) .  While you can easily use variables to manipulate the size and position of windows, boxes, buttons, etc., you’ll want to do the calculations for those variables in other places and avoid using loops or complicated formulae within the function.

When it comes to displaying a basic GUI you have a few easy options - GUILayout or manual placement.  Depending on the look you want, you may be able to use either one but with different complexities.

As an example, let’s start off with GUILayout, which attempts to automatically lay out the components of your GUI.

function OnGUI() {
GUILayout.Button(“Here is a test button”);
}

In this simple piece of code, the result is a labeled button on your game screen.  Because we didn’t declare anything about where we wanted to place it or declare a size, it appears in the upper left of the screen and is as long as the text it contains.  Making it do something is as easy as making it into an “if” statement:

function OnGUI() {
if (GUILayout.Button(“Here is a test button”)) {
DoSomething();
}
}

In this case, pressing the button will run the function “DoSomething()”.  To use the manual option for this same thing, let’s set up a test button:

function OnGUI() {
GUI.Button(Rect(0,0,200,50), “This is a test button”);
}

What we’ve done here is manually place the button at screen position x=0 and y=0, which is the upper left just like the other button.  However, we’ve manually set up the width as 200px and set a height of 50px.  Whether you use boxes, buttons, labels, or any other GUI elements, you can manually set them up using:

GUI.[element] (Rect( X-Position, Y-Position, Width, Height ), “(Text here if applicable)”)

Typically I prefer to have this level of control over each element, and it allows for more variables to be easily inserted.  However it does make your code a bit more complicated.  As a result, the majority of the examples here will be focused on using GUILayout.

When placing GUI elements, I often times want to make things resolution independent.  Because you don’t want someone with a 30 inch monitor forced to play your game at 800×600 unless they choose, you can use the default Screen variables to get numbers based on the resolution of the game.  For example:

function OnGUI() {
GUI.Box(Rect ( (Screen.width / 2) – 100, ( Screen.height / 2) – 100, 200, 200), “This is a centered box.” );
}

Manually Created

Now, getting back to doing the same with GUILayout – as you can imagine we do need to tell Unity where to actually draw our box.  The process is very similar to what we’ve just done:

function OnGUI () {
GUILayout.BeginArea (Rect ( (Screen.width /2) – 100, (Screen.height /2) – 100, 200, 200));
GUILayout.Box(“This is a centered box.”, GUILayout.ExpandHeight(true));
GUILayout.EndArea ();
}

By comparison, this may look more complicated than than manual placement, but it allows for easy placement of more elements.  It will always be at your discretion which method you prefer for what scenario.  My best suggestion is to familiarize yourself with both options and all of the available elements in Unity GUI.

Next, we’re going to work with using the GUI for functionality.  This includes text input, sliders, and selecction grids (which work similar to “radio buttons” in HTML).

Dec 022011
 

Over this holiday break, I was able to do something exciting – create a working AI for a top-down game I’ve been working on.  While it isn’t perfect, I’ll share with you the steps and the code that I used in order to get the functionality that I wanted.

First, allow me to explain how this game works because AI is going to be very specific to the type of game you want to create for yourself, and there won’t really ever be any plug-and-play solution to paste into your title.  My newest game, being top-down, ignores the Y plane.  the Z plane makes my little spaceships go up/down, and the X plane is left/right.  Because of this simplicity, I was better able to grasp what needed to be done.  The ships are all individual rigidbodies that will be able to bounce from walls, rotate, strafe, fire bullets at players, and determine their own path.  (an example of the AI in action can be found here).

Before we can do something such as having the enemy turn attention to a player, I wanted first to focus on making sure the ships can do basic pathfinding on their own.  Each of them has a Constant Force attribute that propels them forward indefinitely, but how do we determine if we’re coming up to a wall?  In this example, we’re going to use a couple of awesome Unity features: Physics.Raycast and Debug.DrawRay.

First, Debug.DrawRay is a feature for you, not the player.  What it allows you to do is see a line drawn in the “scene” window while the game is running.  In the example here, you can see the green line that the ship shoots forward.  This is a cool feature that will show you how your other scripts are working together if you set it up correctly.  In the Update() section of a javascript file attached to this ship, you will see:

Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * reactionDist, Color.green);

It’s a fairly simple piece of script.  We want to send a line from the position of the ship forward for a distance that we’ve set as a variable called reactionDist (25), and make the color green.  We want to do this because the actual physics detector, Physics.Raycast, will be invisible to us.  On that note, let’s add the raycast now and I’ll explain what happens there.

if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), reactionDist)) {
front = true;
} else {
front = false;
}

So now we’re sending an invisible line forward.  When it hits a collider, we have a boolean variable that comes back true, but otherwise it stays false.  Also, because we’ve used a variable for reactionDist, we can customize this quite easily in the inspector.  We can actually set up as many of these types of lines as we want (at the expense of processing power, so don’t go absolutely nuts :P ), and have a multitude of reaction input to go off of.  For my purpose, I know the ships will always be moving forward, so all I wanted was the “front” direction, two 45 degree angles forward, and the two sides.  It came out something like this:

I also made the front/side lines a bit longer than the 45 degree ones which “rounded out” my feelers.  The code for all of this is here:

//Determine colliders within reactionDist
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), reactionDist + ftReacDist)) {
front = true;
} else {
front = false;
}

if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3(1,0,1)), reactionDist)) {
right = true;
} else {
right = false;
}

if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3(-1,0,1)), reactionDist)) {
left = true;
} else {
left = false;
}

if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3(-1,0,0)), reactionDist + ftReacDist)) {
farLeft = true;
} else {
farLeft = false;
}

if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3(1,0,0)), reactionDist + ftReacDist)) {
farRight = true;
} else {
farRight = false;
}

//Draw rays
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * (reactionDist + ftReacDist), Color.green);
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3(1,0,1)) * reactionDist, Color.green);
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3(-1,0,1)) * reactionDist, Color.green);
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3(-1,0,0)) * (reactionDist + ftReacDist), Color.yellow);
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3(1,0,0)) * (reactionDist + ftReacDist), Color.yellow);

Again, I put all of this into the Update() section of the script so that I knew it would execute every frame.  I made the side lines yellow because I knew the strafe code would be a bit different than the code needed to just turn the ship, but other than cosmetically it didn’t change anything at this point.  On the next page, I’ll show you how to use the information gathered here and actually perform the movement calculations.

Nov 252011
 

In development, we are limited by the hardware of the end user.  Optimization of each model is key to making sure a project will run on more hardware types, but the sacrifice is sometimes difficult.  Recently, I decided to model a dungeon scene, and an integral part of that scene was to create chains that hung from the ceiling of the cell with shackles attached.  Of course, each link of a chain is rounded, as apparently many things are in a dungeon.  Once modeled, the chains consisted of thousands of polygons which would seriously tax the video hardware if the scene was to launch on a mobile device, web-player or even a computer with sub-par gaming peripherals.  To demonstrate, I will actually embed the dungeon scene into this post so you can see the lagginess.

Luckily, Unity’s editor will break down the statistics that can give you an idea of how something will run on some devices, and the manual has a section for video optimization, which we will discuss in this article.  One of the best parts of designing within the Unity environment is the knowledge that you can build your game onto whichever platform you like, but just because your game works perfectly within the editor does not mean your target device will handle it correctly.

While every Unity developer will be able to access the statistics window (the button is at the top of the “game” window within the program), if you have access to Unity Pro, you will also be able to use the Profiler, which can really break things down for you.  If you have access to such a useful tool, you’d be a fool not to utilize it.  In this article I won’t be going into the Profiler (not all readers have access to it) so much as the statistics.


Before the breakdown, let’s take a look at the complete dungeon scene attempting to run in a web environment.  Once loaded, click on the Unity window and you should have standard FPS controls and mouse look.  When you’re finished, follow me onto page 2 and we’ll get into optimization ideas.


Nov 222011
 

This entry isn’t so much an article as just a demonstration showing some of the models I’ve created for Unity.  Use the zoom/rotate controls after selecting an asset to see it in whatever view you would like.


Nov 182011
 

I have yet to have any real problems with the Unity asset importing features, but the reason I wanted to write this article was to explain some of the quirks that might make things easier for new Unity developers.  In this article, the two major things I want to cover are:

  • Importing textured 3d models into your game
  • Importing sound files and using them correctly
To begin, we’re going to start with 3d models.  Personally, I’ve been using Cheetah3d which is a very inexpensive and basic modeling program.  You can also use Blender as a no-cost alternative, and you really shouldn’t have major issues regardless of the file type you prefer.  While Cheetah3d defaults to a .jas type of file, I have now taken to saving as .fbx because it seems to be more common and universal for other modeling programs.  However, it’s important to note that Unity itself has no issue reading or importing any of the file types I’ve come across.
Obviously, the first thing we want to do here is design and texture a 3d model.  For this article, I chose to use a terra-cotta pouring vase, seen below within Cheetah3d.
When rendered within the 3d modeling program, we get something like this:
To understand the path ahead, what we want to end up with here are basically 2 files – the object itself which is a series of polygons, and the texture that wraps around those polygons.  If we were just to save it and import it now, we would end up with just a shape without any texture.  To get the textures into a usable file, we simply bake them into a .png picture file.
We don’t need to know how everything works exactly except that our program has a UV editor and an option to bake the texture for us.  I select the object, select “bake texture” from the menu, and open the UV editor to see this:
On the left, you can see the flat mapping of every polygon that can be affected by applied textures.  You’ll notice that on the right, I’ve chosen UV1 and set a decent texture resolution of 1024×1024.  When this picture is rendered, we get a result that looks like this:
Save your main file wherever you like, and be sure to save this image file along with it.  Within Unity, we can right-click on our project window to get the option to “Import new Asset” or “Open in Explorer (or Finder)”.  Whichever you choose, add your files into your game assets and you’ll see Unity work for a moment to calculate everything it needs.
 Once it’s within your project window, you can manipulate settings on the prefab that Unity creates.  Before anything else, be sure to drop your texture image file onto the little window within the material object.  With this file added, you can see in the preview window of the 3d model prefab exactly how everything is rendered.
In some cases, the object may look a bit funky at this point.  This is something that was slightly frustrating to me early on, but I found that Unity compensates through the inspector window and can correct the display.  Take a look at the pictures below and you’ll see the rendering difference when “Normals” are imported versus calculated for this model:

 

Once you have your object set up correctly, drag it from your project window into the scene and take a look – hopefully everything looks as you expect.  There are many more advanced ways to work with materials and texturizing, so if things are not exact, you can change your resolution or settings within your modeling program to your liking.

Another important thing to note is that if you work with the saved model file directly from your assets folder, you can change your model on the fly.  Simply edit and save to instantly update everything within unity.  (keep in mind you may need to bake your texture again if you make big changes).

While I’ve yet to work with the major professional modeling applications such as Maya or 3d Studio Max, I can’t imagine they would be much tougher than what we’ve done here with Cheetah.  I look forward to working with those programs when I have the chance and perhaps writing a more specific tutorial if the process is different.

On the next page, we’ll work with importing and utilizing sound files within our project.

Nov 112011
 

Continuing on from the last lesson, in this article we will make our game much more finalized and playable.  What we should currently have is a sphere as a game piece, a board for the sphere to roll on, and a hole for the ball to fall into.  All in all, what we have is quite basic, but it’s the framework that will allow us to really customize things how we like.

Before anything else, let’s apply a more realistic set of physics to the ball and be sure it isn’t going to fly through the walls of our level.  A basic speed should be declared, and we’re going to make it a variable in case we want to change it.  (as a side note, I would suggest doing this as often as you can in case you want to change these things in-game based on things such as options or even power-ups).

In our movement script, lets add this line outside of the functions:

private var ballSpeed : int = 30;

A base speed of 30 should be about average because we’re going to be multiplying it by accelerometer numbers, which are going to be less than 1.  We’ve covered a few basics of AddForce in previous tutorials, but this will give you an idea of how versatile the function really can be.  Our old movement script went something like this:

transform.position.x = (transform.position.x - (dir.y - calibrateY));
transform.position.y = (transform.position.y + (dir.x - calibrateX));

This was good enough when we didn’t have physics, but we now want our GameObject to really interact and react to colliders.  What we can replace these lines with will be something more like this:

rigidbody.AddForce (Vector3.left * ballSpeed * (dir.y - calibrateY));
rigidbody.AddForce (Vector3.up * ballSpeed * (dir.x - calibrateX));

Instead of moving the ball around the universe, we’re now effectively “pushing” it into the right direction.  This way, if it hits something it will react accordingly.

While we’re in this script, let’s also make sure we know where the ball is going to be on the Z-axis while playing.  This can be done by just adding the following to the Update function:

print(transform.position.z);

Now, go ahead and test the game in the player.  When the ball is settled, make sure to take note of the debug line in the console (at the bottom of your screen).  The number there (for me it was 14.48) will be the exact Z position of the ball after settling on the level base, and we can now establish victory if that ball falls into a hole.  Based on my design, I know that if the Z-position of the ball is anything OVER 14.48, I’ve “won” the game by getting the ball into the goal.  so in my movement script, Ive added these lines:

Outside of functions: private var victory = false;
Within Update() if (transform.position.z > 14.50) {
victory = true;
} else {
victory = false;
Within OnGUI() (NOT inside of the overlay we created - we don't want to have to hit the back button to see if we win) if (victory == true) {
GUI.Box (Rect(Screen.width /2 - 100, Screen.height /2 -50, 200, 100), "You Win!");
}

Play your game to be sure your own measurements line up and “win” the game if your ball falls into the hole.  In the next section, we’ll work on adding obstacles and such to the level itself.

Nov 042011
 

Having read every book in the series-in-progress “A Song of Ice and Fire” from George R.R. Martin and being an avid watcher of the newer television series “Game of Thrones” which accompanies the series, I was excited to see something new pertaining to Martin’s world.  At the same time, I was apprehensive to play the game for fear that the developers might have skewed the storyline or ruined something that I had grown to love.

Upon firing the game up for the first time, I was somewhat relieved to see that the game is set long before the happenings within the books, and covers a section of history that isn’t laid out exactly within the timeline.  What this has allowed Cyanide Studios to do is to take a few liberties and freedoms that would have otherwise angered fans.

After allowing myself to put my fears aside and dive into the campaign, what we have is a basic strategy game with a few innovations and twists that lovers of similar games may or may not enjoy.  Rather than having the focus on combat and conquering enemy territories, the game is largely focused on using diplomacy, subterfuge and secret alliances to gain ground.  Of course, there is still the element of combat, but the presence and need for raising large armies is dulled by the upkeep of keeping your own territories afloat and under your own control.

While I played, I was sending out envoys to enemy territories, spying on illicit deeds that caused my own people to turn against me, inciting revolts, and assassinating enemy troops.  There is a large focus on the element of stealth and surprise which didn’t exactly mesh with my typical play style.  Had I been given the choice, I would have much rather raised my armies and simply taken the world by force, but therein lies the problem – I wasn’t given the choice.  While my armies stood ready and willing to obliterate other attack units, I found a good deal of the diplomatic units simply immune to my wrath.  I won’t lie – it bothered me that I could effectively surround a territory with tons of troops but was unable to take the land without bringing in an otherwise useless unit to barter through diplomacy or incite a revolt.

I agree that the game has a focus that differs from  the norm, but this isn’t always a good thing, especially when it takes away from the immersion.  That said, the game would have a different pace and difficulty if it simply became a battle of armies.  The most important thing about a game is that it causes a player to have fun while playing and enjoy the time they’ve spent, and I can’t truly say that this game did that for me.  While players who are more focused on strategy and diplomatic gains might have a great time with the intricacies of this system, it lacked the battle element that I enjoy most.

Once you are able to raise armies versus simply hiring small bands of mercenaries, the game seems to disappoint even further.  Armies are comprised of just a few simple units, and not the large, powerful group you might expect.  I can safely say that I got more enjoyment out of the assassin game unit than I did a large, mixed army of troops.

I experienced a frustrating time with strange issues as well which forced me to become defeated immediately.  Twice during my play I was simply given a defeat screen that stated my “main character” had died, but this wasn’t the case – she was still alive and well.  Moreover, this character isn’t even controllable, which is another gripe I should mention.  If I am to protect this unit, I simply am forced to keep troops stationed around her because establishing a perimeter in a game with such a large stealth focus is next to impossible.

While some might compare this game to other RTS greats, it is actually more comparable to capture-the-node play style.  It lacks the action that I’ve grown to love within the series it’s named after, and whether you are a fan of the series or not, I still wouldn’t recommend this purchase.

PC Game

Graphics

60
 

Audio

50
 

Gameplay

40

Creativity

40
 

Execution

30
 

Offset

40
    

4.3

  

How do these ratings work? Click here for descriptions!

Nov 042011
 

In the last article, we set up a basic framework that used the accelerometers of our device to manipulate our little cube.  Obviously if our game was more finalized we would want to hide all the debugging numbers and such completely, but for now, lets simply toggle them on and off by using the “back” button on the device.

Android registers this button as “escape”, which is effectively like pushing the escape button on your keyboard.  This is handy because it will allow us to test our functionality quickly.

To begin, let’s use our existing script for movement (mine was called “cubemover”), and set up a private variable called overlayOn.  Because this is an off/on variable (this is called a “boolean”), we will set it to false by default, like this:

private var overlayOn = false;

Next, we just need a way to toggle it.  This script will go into the Update() section of the script to listen for our key press.

//Making use of the Android "Back" Button
if (Input.GetKeyDown(KeyCode.Escape)) {
	if (overlayOn == false ) {
	overlayOn = true;
	} else {
	overlayOn = false;
	}
}

The last thing to do is simply encase our GUI script elements in an IF statement.  With everything together, the whole script should end up like this:

var dir : Vector3 = Vector3.zero;
private var calibrateX : float = 0;
private var calibrateY : float = 0;
private var overlayOn = false;

function Update () {
		//In landscape mode, +X is up, -X is down, +Y is left and -Y is right
	dir.x = Input.acceleration.x;
	dir.y = Input.acceleration.y;
	dir.z = Input.acceleration.z;

	if (dir.sqrMagnitude > 1) {
		dir.Normalize();
	}
	//left/right
	transform.position.x = (transform.position.x - (dir.y - calibrateY));
	//up/down
	transform.position.y = (transform.position.y + (dir.x - calibrateX));
//Making use of the Android "Back" Button
if (Input.GetKeyDown(KeyCode.Escape)) {
	if (overlayOn == false ) {
	overlayOn = true;
	} else {
	overlayOn = false;
	}
}
}
function OnGUI() {
if (overlayOn == true) {  // only display if Overlay is toggled on.
	GUI.Label(Rect(4,4,300,30), "dir.x: " + dir.x);
	GUI.Label(Rect(4,44,300,30), "dir.y: " + dir.y);
	GUI.Label(Rect(4,84,300,30), "dir.z: " + dir.z);
	//Button to Reset to center position
	if (GUI.Button (Rect(Screen.width /2 - 60, Screen.height /2 - 120, 120, 50), "Reset")) {
	transform.position = Vector3(0,0,0);
	}
	//Button to recalibrate Zeroed control center
	if (GUI.Button (Rect(Screen.width /2  - 60, Screen.height /2 - 65, 120, 50), "Calibrate")) {
	calibrateX = dir.x;
	calibrateY = dir.y;
	}
	//Button to exit program
	if (GUI.Button (Rect(Screen.width /2  - 60, Screen.height /2 - 10, 120, 50), "Exit Game")) {
	Application.Quit();
	}
}
}

As an added bonus, I added in a third button that will actually exit the program as well.  When saved and run, everything will disappear until we hit our escape key.  after we do, we see this:

On the next page, we’re going to import some assets to use for the first time and get rid of that blue background. :)

Oct 282011
 

Like the rest of the Megabite series, I will be instructing by using Unity3d, which has proved itself to me time and again over the past few projects.  Most recently, I was able to use the trial of Unity Android to get myself published onto the Android Market, and though in my case the game was nearly finished for its format as a web-based game, I merely had to switch platforms within the settings and alter a few lines of code to add things such as accelerometer controls.

In this article, I will be talking about the basics of going from “New Project” to “Hey check out the app I just published”.

To begin, you will need a trial copy of Unity3d Android at the minimum, which can be found here.  The licensed copies of the software or the Pro version are $400 or $1500 dollars respectively (which may seem steep until you get an idea of the features and differences), but a trial is enough to get yourself started and even get a working game ready for publication.  If you are on a trial copy, you will see “trial copy” watermarked in small text at the bottom-right portion of the finished product, but the software isn’t limited in any other respect that I’ve come across so far.

You should download and install the Android SDK as well, and update it with the packages you are aiming to target.  While this tutorial will not cover the SDK inner-workings, Google has a great deal of pre-existing documentation on the basics if you choose to use it.  For our purposes, we don’t need to spend much more time than to install it.

Getting your game together

If you have existing code, you may see some errors pop up if you were lazy in the way you declared variables (like I was).  if you have a script that contains something like:

var myVariable;

You will likely see a warning that forces you to declare what type of variable you are creating.  Since you should already know what it is you’re trying to DO with this variable, this isn’t a big issue.  You simply define it as a string, integer, float, game object, or whatever you need.

var myVariable : String;

For me, this was simply a wake-up call that let me know I should be more specific.  Not to mention, it’s a good habit to develop anyway and it makes your code more readable when you go back to decipher work from earlier.  Suffice it to say that Android development was just a slight bit pickier in how things are read, but you can see it wasn’t a deal-breaker.

If this is your first time using Unity to develop, I suggest reading through earlier posts in this series to get a basic understanding of Unity development as a whole before you dive into the deep end.  In fact, we’re going to import the project that is still standing from #2 in the series and use that project to develop our first APK file.

We’ll start by switching the platform over to Android, as you can see on the left (File -> Build Settings). Once you’ve selected it, you simply click the button beneath to begin the automatic process.  Unity converts whatever it needs to behind-the-scenes while you wait.

Once the process is complete, you will see if there are any errors that might need to be handled.  In the case of the Megabite project, there were not – so we can move on.

Because we are now developing for a different resolution and such, you will notice that your “game” tab has some new view switching options.  Obviously Android has many different hardware setups, so you should keep these in mind as you test your game in the player.  Sometimes seeing what the game looks like in a different aspect will remind you about hiccups that may have occurred in your calculations or display setup.

What we’re going to do here is a landscape setup, so you will want to open your player settings to choose these options.  Go to Edit -> Project Settings -> Player, and you will see the different options available in the new Android tab.

While you’re in here, you can alter things such as your icon (will display on the Android device home screen or within the applications menu), the Product (game) name, and your company name.  Under Resolution and Presentation, I will choose “Landscape Left”, which seems the most compatible and common landscape option.

Fair warning: I did attempt to change some of the settings within “Other Settings” when I first published GIRType, and simply ended up crashing my phone.  I would suggest you stick to the default options unless you know specifically what you are choosing, but you should be sure to change these boxes when applicable:

For your first go-round, the Identifier is the important option.  The version number and version code will need to be raised for each publication to the market (or else google will give you an error), but to test things locally you can leave them unchanged for now.

Lastly, the publishing settings.  While the terminology here might be new or seemingly complicated, you really just need to create 2 passwords here.  Check the box for “Create new Keystore” and then browse – Unity will create a file and save it to the system.  Once done, you need to create a password for this keystone and confirm it.

The pull-down box for the “Alias” will have an option to create a new key, which will allow you to put in more information.  Here you will create a second password and re-enter it on the publication tab when finished.

Once all these basic things are accomplished, you will immediately be able to build the project into an APK file.  Open the build settings once more (be sure your scene is in the scene list.  If it isn’t, open your scene and hit “add current” and you’ll see it listed) and hit the Build button.  You’ll be prompted during the process to select your base folder for the Android SDK if Unity doesn’t automatically find it, but you can move on once selected.

Follow me onto the next page and we’ll get that file up and running.

Oct 212011
 

UPDATE:  Thanks to some amazing Reddit users, the code here has been updated for extra security.  

Connecting your Unity web application to html or PHP files is actually quite easily done.  This could be useful for a great many reasons including: score lists, login/password, progress saving, etc.  In this Megabite article, I will be showing how to get everything situated for a “top 10” type of score list.  An example is now displayed whenever your ship is destroyed in GIRType.  Try a single playthrough of the game to see a working example.

For the purpose of this article, we will have to assume you have a web server to host your game, and the ability to create MySQL databases and tables.  While you may not need a great deal of experience with PHP/MySQL, any experience at all might be helpful.

Before any scripting, you will need to know a couple of things:

  • Your MySQL server address (in some cases this may be different than “localhost”)
  • Your database name and login/password information (the creation process will vary between hosts)

The basic process consists of 2 PHP files for our purpose.  We need one file to simply add information to the database, and another that easily lists the information in a way that Unity can easily read and display.  To easily create the table itself, however, I will also throw in this additional PHP file that can be pasted, saved/edited, and executed in order to set up your table within the database.  This only needs to be run once if you don’t see en error displayed.

<?php
ignore_user_abort(true);
error_reporting(E_ALL  & ~E_NOTICE);
$connection = @mysql_connect("localhost", "username", "password") or die(mysql_error());
$db_name = "scoredatabasename";
mysql_select_db($db_name, $connection);

$sql = 'CREATE TABLE `scoredatabasename`.`tablename` (
`id` INT( 5 ) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(35) NOT NULL,
`score` INT(25) NOT NULL
)
ENGINE = MyISAM';
$result = @mysql_query($sql, $connection) or die(mysql_error());
echo "Table Created!";

?>

Save this file as whatever you like and add a .php extension.  It will need to be edited to include the information you would like to use.  Once the correct sections are filled out, upload it to your server and navigate to it through a web browser.  If you see that your table was created, you can feel free to delete the file completely.

In the next section, we will use GET variables to add scores into the system.  Follow along to page #2.