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.

	<item name="TatenenBreadSlice" realName="Tatenen's slice of bread">He won't find out. Surely.</item>
	<item name="SandwichMeat" realName="Sandwich Meat">Its a little slimy, but nothing a little heat can't solve.</item>
	<item name="metalTray" realName="Metal Tray">A metal tray.</item>
	<item name="UncookedSandwich" realName= "Uncooked Sandwich">This sandwich needs to be cooked if I don't want to end up on the Med-Table again.</item>
	<item name="CookedSandwich" realName="Cooked Sandwich">Sandwich time!</item>
	<item name="HalfASandwich" realName="Half a sandwich">Just needs another slice to top it off.</item>

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&lt;inventory.Count; i++) { 
//check if a new page is needed....always starts off needing a new page. 
	if (pageCounter &gt; 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.

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

  1. Pat says:

    Hey, amazing stuff! The dev. blog is just a gold of mine to any Unity users around who has been struggling to make an p&c adventure. Have a lot of questions, indeed, hope you don’t mind.
    1) Concerning the text for the dialogs, are you rendering all the dialogs using Ex2d?…what about the GUI for the menu, is this also handled via Ex2d?
    2) What about the pathfinding? Are you using some A* routines? or just camera and point-following?
    3) The cursor-changing-action systems works fantastic, please take it into consideration for a future article
    4) AGS and Wintermute works in a room-by-room basic where each room generates the items and characters (some consistent, some others are destroyed after the main character leaves the room). How are you facing this? Like having just a giant level (scene) with all the elements on it, or as a group of different levels linked together as rooms?
    4) What about saving progress. It’s not included in the demo, are you working on it?

    wow, sorry for being so annoying! Amazing job Mike.
    To the Biktory!

  2. admin says:

    Hi Pat, Thank you so much!
    I noticed wordpress was stripping some of my code so it should be fixed now!
    Per your comments:
    1)All text (no matter dialogue or menu) is rendered using Ex2d. I use a custom word wrapping method to wrap the text and I dynamically size the background frame to match the height and width of the text. I think 2Dtoolkit comes with a word wrapping feature. I can talk more about displaying the text in a post!

    2)I use Aaron Grandbergs A* implementation for pathfinding. I made a custom AI script that handles moving along in 2D. You need sort the Z-index based off of the feet of a sprite. So I have a baseline script which calculates what the z axis should be depending on where the sprites “feet” are. This allows objects to be infront of or behind other objects. My AI script takes this into account. Its a great plugin!

    3)I will certainly describe my cursor system in a new post!

    4)I use the unity scene system for loading complete levels. So if there are multiple rooms or buildings for a scene, they all are part of the Unity scene. For example: when boarding the Umarian UFO ship there are about 6 rooms that you cannot just walk between. Each room exists in the scene and if the player needs to go to a new room, I fade out, adjust the transform of the character and camera, then fade back in at the new room. All the items in those rooms have states that last the duration of the current scene. If a state needs to last between scenes I have a global state that can survive between scenes. When the level loads it looks at the states of the objects and will place them accordingly. I’ll make a post about my state system!

    4)I do have a fully functional save system! I just disabled it for the demo because I extracted some pieces of the menu to make the demo stand alone and didn’t find the time to implement them again just for the demo. The system will save the state and position of each item, all dialogue states, and various global variables. I’ll make a post outlining how I made it. Actually that would probably be an easy post so maybe i’ll do that today!

    Thanks!

  3. Pat says:

    Hey, thank you so much for the info, i’m going to read it carefully this evening. I also changed my pledge to a bigger one just to help a little bit more in this adventure!

  4. admin says:

    Thanks Pat! Just a new post about saving!

  5. Ruben Burke says:

    Hey wonderful stuff man, I want to know how to create sprites of a resolution higher than most 2d games, how do I go about creating sprite and sprite animation of a higher quality?

  6. Mike Pinto says:

    Hi Ruben,
    You might want to check out 2D Toolkit for unity. It has very simple methods for creating sprites and animations within unity. http://www.unikronsoftware.com/2dtoolkit/
    Beware that the higher the resolution, the more memory the sprite will take up and on phones that can start to be a problem.

  7. Travis says:

    Thanks for posting this, and the post after it. I have made one game in Unity but I really want to make a classic point-and-click adventure, but sadly there seems to be very little info out there about this. I have been looking at some source code from game jam games, which is helping me get an idea about the best approaches to take but I wish there was more. Hopefully these posts will be of help, I just wish there were more of them.

  8. Mike Pinto says:

    Hi Travis,
    I agree there is very little info out there about building a framework for these types of games. The problem is that it takes SO long to build a framework for a point and click from scratch that it is very hard to justify the costs / time involved. For a while I was a big fan of making my own framework, but after having done it, I can safely say that unless you can do this full time, you should use a pre-built framework. There is one in the unity asset store, but I don’t have experience with it so i can’t really judge it. Otherwise you’ll be spending months and months just building the framework. If you have any specific questions please don’t hesitate to ask and I’ll try and point you in the right direction.

  9. Travis says:

    Thanks, well, I’ll see how it goes, anyway. Right now I am working on making a very simple adventure game for Point and Click Jam. I found a few source code examples from people using Unity to make some small adventures for this year’s global game jam. So armed with these, I will see how it goes over the next week or so. It may be that I decide it is indeed to much work, I suspect the game mechanics I get finished will be quite simple and need improvement for any serious work.

  10. Kandi74 says:

    Hi, i noticed that your page is very slow, it took around 7sec.

    to load this post. Do you know that page speed
    is major ranking factor for google now? If you speed
    up your site loading time you can rank higher and get more targeted traffic.

    There is simple method for faster loading, search for: Masitsu’s tricks

  11. Indira1992 says:

    This post is on 19 spot in google’s search results, if you want more traffic,
    you should build more backlinks to your website, there is one trick to get free, hidden backlinks from authority forums, search on youtube; how to get hidden backlinks from forums

Leave a Reply

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