Building a 2D point and click adventure game in Unity3D.

*EDIT (I am currently available to consult or help implement my adventure game framework for your project..more info here: http://forum.unity3d.com/threads/2-d-point-and-click-adventure-game-framework.293708/ **

Here is a video demonstration of the latest version of the editor for my framework:

Hi Everyone,
This is the first of many blog posts where I will describe the methods I used to create my Adventure game framework in Unity.

Why Unity?

When I first started working on Bik (in 2012) I was using Adventure Game Studio (AGS).  AGS is dead simple to use and has a really amazing community who actively keep it updated and can help you with just about anything!  After a few weeks into using AGS I realized it had some limitations.  For one, it had no built in  way to handle multiple aspect ratios. This was a big deal because I love widescreen gaming.

Another limitation was its ability to work on multiple platforms.  Yes, there are builds for various platforms including iOS, but these were not working well a year ago and they still are not very easy to get working.  It took Wadjet Eye 8 months to port Gemini Rue to iOS, and I haven’t heard any mention of android from them.

I wanted Bik to work on any device and any resolution.  Since I am one person, I couldn’t afford to spend the time optimizing for each platform. I also thought it would be great to be able to incorporate some form of 3D graphics into the game.  The answer was clear, Unity3D.

Part 1 – 2D graphics in Unity
**EDIT: Since I wrote this posting Unity has released their own 2D tools. You can find help on using them on the Unity website here: http://unity3d.com/learn/tutorials/modules/beginner/2d
**

I suggest reading this blog series on creating 2D games in unity.  It goes over how to set up cameras and work with sprites. Its a few years old now but the basic ideas are still the same: http://www.rocket5studios.com/tutorials/creating-2d-games-with-unity3d-part-1/

To summarize, you will need a way to display sprites from a sprite sheet.  There are a bunch of 3rd party plugins available at the Unity Asset store that will make your life much easier.  I use one called ex2d.  Another popular one is 2DToolkit.  They both include sprite atlas tools, animation tools, and font tools.

You should not use the built in OnGUI functions built into unity.  It is very slow on mobile.    All menus will need to be built with the 2D toolkit you make or purchase.  Basically anything you see in the game besides a 3D model will be using the 2D toolkit for display (text, sprites, menus).

I do have one warning about using 3rd party plugins.  Often times it may seem easier to get one, but in the end you spend just as long figuring out how to implement the plugin as you would have building your own implementation, and you will learn a lot more if you build your own.

If you want to know more specifics on how I am displaying 2D graphics please ask in the comments and I will try and answer, otherwise I’ll focus on the Adventure game aspects.

Part 2 – Inventory System

I’ll start by describing how I built the inventory system.
In unity you can store a gameobject in a prefab and then anytime you want that object to appear you can instantiate it into the game world.

For inventory items I have an inventory prefab that will be instantiated and then turned into a specific inventory item.  The base inventory prefab consists of a sprite script that displays a sprite, a collider to detect mouse or touch interactions,  and an inventory item script which handles what to do when an interaction is detected.

When an inventory item is collected it is added to an array of current inventory items.  The item is a class that contains the id of the inventory, the display name of the inventory item, a state of the inventory item, and a current description of the inventory item for when it is looked at.   All of this information is stored in an XML file.  This version only has a description for 1 state, my latest version has multiple states descriptions but I thought this would be easier to understand.

	He won't find out. Surely.
	Its a little slimy, but nothing a little heat can't solve.
	A metal tray.
	This sandwich needs to be cooked if I don't want to end up on the Med-Table again.
	Sandwich time!
	Just needs another slice to top it off.

I program in C# so any code examples will be in C#. I recommend not using javascript in Unity. If you are a beginner, it is much harder to learn what is “really” going on if you use javascript. Plus C# can use events and delegates which are extremely useful.

To feed the XML into the inventory items class I use the .NET System.XML namespace.   First I instantiate the inventory prefab, then connect to the new objects IconInventory script.  It is on that script I will change the variables to make this a unique inventory item. I then move the current object to be a child of the current page in the inventory we are on and move its local position.  Here is what part of the script looks like. Its a little sloppy since I never planned on others using it but it will hopefully help you out!

int page = 1; //current page
int pageCounter = 0; //once this reaches the "limit" it will reset and a new page will start..limit is 12 for now
int InvPageLimit = 12; // the limit of number of items per page
float counter = 0f; //counter for how many items we are currently at, when hit limit a new row is made
float tempz = 3.5f; //this is the amount to adjust the z axis by for new rows
bool needNewPage = true; //if pagecounter is greater than the limit, a new page is needed

for (int i=0; i<inventory.Count; i++) { 
//check if a new page is needed....always starts off needing a new page. 
	if (pageCounter > InvPageLimit) {
		pageCounter = 0;
		page++;
		needNewPage = true;
	}

	//if need new page create a new page
	if (needNewPage) {
		GameObject pg = new GameObject ("page" + page.ToString ());
		pg.transform.parent = transform.parent.Find ("Pages");
		pg.transform.localPosition = Vector3.zero;
		needNewPage = false;
	}

	//get the current page game objects transform
	Transform curPage = transform.parent.Find ("Pages/page" + page.ToString ());

	//name the inventory object with a INV out front
	string tempstring = ("INV" + inventory [i]);

	//instantiate the inventory item prefab and then connect to the IconInventory Script attached to it.
	GameObject instance = Instantiate (invPrefab, Vector3.zero, transform.rotation) as GameObject;
	IconInventory tempIconInv = instance.GetComponent () as IconInventory;

	//move new inventory item to be a child of the current page
	instance.transform.parent = curPage;
	instance.transform.localPosition = new Vector3 (-5f, 1f, 3.5f); //this is the starting point for all inventory items...they will be adjusted below

	//setup description and names
	tempIconInv.iconName = inventory [i];
	XmlNode node = root.SelectSingleNode ("//scene[@name='" + Application.loadedLevelName + "']/item[@name='" + inventory [i] + "']");

	tempIconInv.description = node.InnerText;
	tempIconInv.realName = node.Attributes ["realName"].Value;

	//add item to Real Names array....array is used by interactor for mouse overs to show the objects name
	inventoryRealNames.Add (node.Attributes ["realName"].Value); 

	//change new gameobjects name 
	instance.name = (tempstring);

	//change graphic to the sprite filename in the inventory sprite atlas.
	int index = instance.GetComponent ().atlas.GetIndexByName (inventory [i]);
	instance.GetComponent ().SetSprite (instance.GetComponent ().atlas, index, true);

	//check if we need to be on a new row
	if (counter == 4f) {
		tempz -= 2.5f; //adjust the zaxis for the new row
		counter = 0f; //reset row counter
	}

	//reposition inventory object at new calculated final position
	float tempnum = (counter + 2);
	instance.transform.localPosition = new Vector3 (-5 + tempnum + counter, instance.transform.localPosition.y, tempz);

	counter++;
	pageCounter++;

}

If the inventory is clicked on, an interaction script determines what to do next by reading an XML file depending on the mouse cursors current state. Its all about XML files. My main reason is because I also have a custom XML editor for the game that makes it really easy to deal with dialogue and sequences.

Next time i’ll talk about how I use XML to script sequences and dialogue!
Please leave any questions in the comments!

This entry was posted in DevBlog. Bookmark the permalink.

12 Responses to Building a 2D point and click adventure game in Unity3D.

Leave a Reply

Your email address will not be published. Required fields are marked *