Make A 2D Game With Unity3D Using Only Free Tools Part 4

Make A 2D Game In Unity3d Part 4This is part 4 of our tutorial series on making a 2D game in Unity3D with freely available tools and plugins. Part 1 introduced you to the tools we’re using, in Part 2 we built our first level and in Part 3 we hooked up the control scripts and setup the ladders and ropes so that the player can navigate levels. In this article we’re going to create a pickup item, hook up the scoring system and add the interface text which reports score, lives and level.

Hopefully you already went through part 2 and part 3 of the series, if you haven’t already you might want to go back and do them now so everything in this part will make sense.

If you’d rather skip ahead, you can download the project up to this point. You can also click here to play the game as it will be at the end of Part 4.

Adding The Scoring and Pickup Scripts

The game is working great so far – the player can move, climb ladders and shimmy across ropes. Now we’re going to add a “gold chest” pickup item and an interface to track scoring, player lives and the current level.

  • Download scoring and pickup scripts and unzip the file somewhere on your hard drive.
  • Copy Scoring.cs and Pickup.cs from the extracted .zip file and paste them into your project’s Assets/Scripts folder.

Modifications To Existing Scripts:

You’re going to need to make a few changes to the scripts from part 3 so that these new scripts will work.

  • Open xa.cs script and then uncomment the first line in the Class:
public static Scoring sc;
  • In the Start function, uncomment this line:
sc = (Scoring)(this.gameObject.GetComponent("Scoring"));
  • Open Player.cs, find the OnTriggerEnter function (line 256) and then uncomment the following code block:
if (other.gameObject.CompareTag("Pickup"))
{
	if (other.GetComponent<Pickup>())
	{
		other.GetComponent<Pickup>().PickMeUp();
		xa.sc.Pickup();
	}
}

Making The Pickup Sprite

You might remember from part 2, that you already added the pickup.png to the level sprite atlas and then created a level container object that points to the sprite atlas so we don’t need to do any additional Container setup to create the pickup.

  • Drag & drop the Sprite object from Orthello –> Objects –> Sprites into the Hierarchy or Scene which will create a new object named something like “Sprite (id=-3700)“. Rename that object to “pickup“.
  • Drag the level object that we created in part 2 from OT –> Containers and drop it on to the Sprite Container slot in the Inspector.

Your sprite will appear but it looks like the brick sprite that we made before, that’s because the brick is the first texture on the Sprite Atlases index.

  • Click and hold your mouse over the word “Frame Index” in the inspector (with the pickup object selected) and then drag the mouse to the right to scroll through the textures on the sprite atlas. The pickup texture is at index 16 so set it to that. The sprite should now look like a a white rectangle with a red box in the center and a black background.

Adjusting The Collision:

The sprite is a square, but we only want the object to be picked up only when the player touches the white part of the pickup.

  • Check the Collidable checkbox to add collision to the object.
  • Open up the drop down list next to Physics and then select Custom.
  • Under Box Collider, set the Center Y to -0.15, Size X to 0.8 and Size Y to 0.5. Leave Size Z set to 0.4.

Setting The Tag:

We need to tag the pickup so that the player will trigger it when touched.

  • Create a new tag by going to Edit –> Project Settings –> Tags
  • Add a new Tag in the Tags list (probably in Element 3 if you’ve been following the series) named “Pickup” (without the quotes). It’s important that the name is correct since Player.cs looks for this exact name.
  • Select the pickup object in the Hierarchy, then click on the drop down list next to Tags at the top of the Inspector and then select Pickup.

Add The Script and Make It A Prefab

Now we just need to add the Pickup.cs script to the sprite so that it will get “picked up” when the player touches it and we also need to turn it into a prefab so that it’s easy to place in all your levels.

  • Drag the Pickup.cs script from the Project Scripts folder and drop it on to the pickup sprite in the Hierarchy.
  • Drag the pickup object from the Hierarchy into the Prefabs folder in the Project tab to create prefab from the object.

The pickup is designed so that you can snap the bottom edge (the black part) of the sprite to the top edge of a brick sprite the white part of the powerup will be the correct height from the top of the brick. Duplicate your new pickup prefab a few times and place it around you level.

If you followed all of the steps so far, your pickup should look like this:
2dGamePt4 pickup

Add The Interface Text

At this point if you place the pickup in your level so that the player can pick it up, the sprite will disappear correctly as if he picked it up, but you’ll get some errors in the console because the Scoring script isn’t in the scene yet and we don’t have any UI to report the score. So let’s fix that.

  • First add the Scoring.cs script to the scene: Drag Scoring.cs from your Project’s Scripts folder and drop it on to the Scripts object in the Hierarchy. If you select the Scripts object, you’ll see that the Scoring script has a bunch of slots for text objects that we need to add – but first we need to create the text objects.
  • Download the G7 Silkworm font and unzip the file somewhere on your computer. This font isn’t exactly the same as the one used in the original Lode Runner game, but it’s pretty close. If there’s another font you’d rather use, go for it. And if you find a font that’s closer to the Lode Runner font, please let me know in the comments.
  • Create a new folder in your Assets folder named Fonts, locate the silkworm.TTF font on your hard drive and then copy it into the Assets/Fonts folder.
  • In Unity, select the silkworm font in your Project’s Fonts folder and then in the Inspector set the Font Size to 26.

Adding The Score Text:

  • Drag the silkworm font from the Fonts folder in the Project panel and drop it into the Hierarchy. This will automatically create a new GUI Text object in the Hierarchy using the silkworm font.
  • Rename the object to “Score Label
  • In the Text field under GUIText in the Inspector, type “SCORE” in all caps without the quotes. The Silkworm font only has uppercase letters so don’t try to use lowercase letters.
  • When you add a font to the scene, the X and Y position are automatically set to X 0.5 and Y 0.5, but we’re going to set the position of our fonts using the Pixel Offset so reset the X and Y Position to 0.
  • Change Pixel Offset X to 16 and Pixel Offset Y to 592. This should position the SCORE text to the upper left hand corner of the Game view (note you won’t see the text in the Scene view so look at the Game view to help position the text).

We also want to keep the scene nicely organized and make it a little easier to hook up the interface objects to the Scoring script later on. You’re going to make the Score Label object a child of the Scripts object and then you’ll duplicate each of the other text objects from this one in order to save a few of the setup steps.

  • Select the Score Label object in the Hierarchy and then drag and drop it onto the Scripts object in the Hierarchy so that it becomes a child of the Scripts object.
  • Expand the little arrow next to the Scripts object, select Score Label object and then duplicate it.
  • Rename the new text object to “Score Value“.
  • Change the Text to 0000000 (7 zeroes).
  • Change the Pixel Offset X to 150 and leave the Y set to 592.

Adding The Lives Text:

  • Select either the Score Label or the Score Value text object and duplicate it.
  • Rename the new text object to “Lives Label
  • Change the Text to LIVES.
  • Change the Pixel Offset X to 348 and leave Y set to 592.
  • Duplicate Lives Label object and rename it to “Lives Value“.
  • Change the Text to 000 (3 zeroes).
  • Change the Pixel Offset X to 480 and leave Y set to 592.

Adding The Level Text:

  • Select one of the other text objects you already created and duplicate it.
  • Rename the new text object to “Level Label
  • Change the Text to LEVEL.
  • Change the Pixel Offset X to 576 and leave Y set to 592.
  • Duplicate Level Label and rename the new object to “Level Value
  • Change the Text to 000 (3 zeroes).
  • Change the Pixel Offset X to 710 and leave Y set to 592.

Hooking Up The Scripts:

Now we need to connect the interface text objects to the Scoring script.

  • Select the Scripts object in the Hierarchy. Under the Scoring script in the Inspector, you’ll see slots for each of the GUIText objects we just created.
  • Select each of the text objects from the Hierarchy and drag and drop them into the corresponding slot on the Scoring script. For example, drag Level Label and drop it on to the Level Label Text field.

Once all of the text objects are connected to the Scoring script, press Play in Unity. You should see the SCORE, LIVES and LEVEL text turn to a red color that matches the border color and the number of lives should change to 005 and the level number should change to 001.

Now if you run the character over a pickup object in the game, the Score should increase by 250.

Make The Top Border

To help keep the interface text separate from the gameplay area, we’re going to add a thin border just under the interface text.

  • Create a new cube by going to Game Object –> Create Other –> Cube
  • Rename the object to “border top“.
  • Set the Transform Position X to 0, Y to 8.7 and Z to 1.
  • Set the Scale X to 26, Y to 0.2 and Z to 1.
  • Find the border material in the Materials folder and then drag and drop it on to the border top object. We created the border material in a previous article.

If you followed all of the steps above, then your Hierarchy and Inspector (with the Scripts object selected) should look the following:

2dGamePt4 Scoring Text

Creating The GLOBAL Prefab

Next we want to do some things to keep the scene nicely organized and also to make it easy to add the key components to any new levels that you create. We’re going to create a GLOBAL prefab that contains the Main Camera, the Scripts (which includes the interface text objects) and the top and bottom borders.

  • Create an empty game object by boing to Object –> Create Empty, zero out the transforms so that it’s at 0,0,0 on the X,Y,Z and then rename the object to “GLOBAL“.
  • Select the Main Camera in the Hierarchy and then drag and drop it onto the GLOBAL object so that the Main Camera becomes a child of GLOBAL.
  • Select the Scripts object in the Hierarchy and drag and drop it onto the GLOBAL object.
  • Select the border bottom and border top objects (make sure they’re not already a child of some other game object first) and drag and drop them onto the GLOBAL object.

That’s everything we need for the GLOBAL object, so now let’s turn it into a prefab that can be easily added to other levels and updated later if we need to make changes.

  • Mark

    Thanks, Tim. Very much enjoying this series and looking forward to the tutorials ahead.

    I was just about to switch off the pc and go to bed when I thought – ‘Wait! Silkworm…. wasn’t that a game I had on the Amiga?!’ 

    And it was. :-)

  • Pingback: Tutorial: 2D Games in Unity3D mit kostenlosen Tools – Teil 4 - Unity News

  • http://www.rocket5studios.com/ Tim Miller

    Hey Mark, glad to hear you like the tutorials!

  • Kaven

    Hi,

    Your tutorial got me started in 2d game development using Unity 3D, it made me discover this wondeful software to develop multiplatform games!

    Looking forward to the next sections.
    Thank you!

  • Wallace

    I get hairline cracks between tiles when the game is running… this is easiest to see on the ropes… any ideas on how to resolve this?  

  • Wallace

    Aha, it looks like a thread on this problem exists in the comment section of part 3.  I will try out some of the suggestions there to see if they work.

  • http://www.rocket5studios.com/ Tim Miller

    Hi, sorry about not getting back to your question. Yes this has come up before both here and in the Unity forums – this issue occurs in all of the different sprite manager plugins available, not just Orthello. 

  • http://www.facebook.com/profile.php?id=100000601645806 Guilherme Gibertoni

     Hi Tim, I really like your tutorials and the game is getting really neat.

    I couldn’t find the part5 of the tutorial on this website though. Have you posted it yet?

    Thanks,
    Gui

  • http://www.rocket5studios.com/ Tim Miller

    Hi! Part 5 is here:  http://www.rocket5studios.com/tutorials/make-a-2d-game-with-unity3d-using-only-free-tools-beginning-enemy-ai-with-a-pathfinding/

  • RSE

    This is an awesome tutorial! Can’t recommend it enough.

  • http://www.rocket5studios.com/ Tim Miller

    @RSE thanks, glad you like it!

  • Darryl

    Great tutorials, thanks for taking the time to post these!

    I have only had one small problem: When my player moves around on open ground the sprite is being drawn at the same z displacement as the ground, but when the player moves onto ladders, ropes, or falls, the sprite pops towards the camera by one unit. The only way to see this is by watching the game in the scene view, angled about 45 degrees to the camera, with the player game object selected (you can see the z position change in the inspector). For the most part this isn’t causing problems, but it means that the  player misses treasure chests because the collision box for the player is being drawn too far back when the chest is not near ladders (or ropes). It was pretty easy to fix this by adjusting the z center and z scale of the chest collision, but it makes me wonder if I’m not setting something up correctly.

    Thanks,
    -Darryl

  • http://www.facebook.com/people/Jonatan-Lemos-Zuluaga/100000635246893 Jonatan Lemos Zuluaga

    Just change the value of z from 0f to -1f in line 146 from Player.cs. I guess it has to do with the newer Orthello versions.

  • http://www.rocket5studios.com/ Tim Miller

    Thanks for posting that, Jonathan.  Hopefully that fixed Darryl’s problem – I was going to suggest the same fix.

  • Laurenshoo

    He, im looking at the script right now, but at line 146 it doesnt say anything O.o pls some help here, since my player does weird:P

  • http://www.rocket5studios.com/ Tim Miller

    The same conversation is going on in one of the other parts of the tutorial right now.  I think it’s actually this part:

    // snap the player to the top of a ground tile if she’s not on a ladder if(!xa.onLadder) { thisTransform.position = new Vector3(thisTransform.position.x, hit.point.y + xa.playerHitboxY, 0f); }

    Try chaning the 0f to -1f

  • http://nickknowlson.com Nick Knowlson

    I am experiencing a display issue when I run my code or look at your live example. The blocks are a bit warped and there are lines in between the ladders.

    Any idea what’s going on here?

  • http://www.rocket5studios.com/ Tim Miller

    That’s really strange, I’ve never seen that kind of warping. Are you still having the issue?

  • http://nickknowlson.com Nick Knowlson

    I ended up deciding to go with flash for my ludum dare entry, and haven’t looked into this any more.

    It is still happening for me though, and seems to be independent of browser. I’m running Windows 7, for anyone else that comes across this in the future.

  • krikri

    ¿The value of Z-center of the Player’s Box collider are zero?

  • http://www.facebook.com/Corvaccio Pasquale נצח Sada

    I have a weird behavior. My player is stuck: if I hit left or right arrow he plays the animation but doesn’t move! I can see a small change in transform position but then x flips back to the origin. If I try to change the moveSpeed in the script the player starts falling trough the blocks. . .

  • B

    I’m having the same issue, my character won’t move from one spot. I thought maybe it was because of the shoot sprite or shoot parent blocking movement but its not (easily discovered by removing them from the player).

  • wyrmtale games

    There is something wrong with moving sprites using transform.Translate.
    (I am looking into that right now)

    however….

    the regular way to move a sprite in Orthello would be to use

    sprite.position += movement ;
    or
    sprite.position = position;

    so to quickly solve the issue now …
    change the transform.Translate() methods from player.cs to
    in UpdateMovement() to :

    GetComponent<OTSprite>().position+= (Vector2)movement;

    I will solve the Translate issue ASAP.

  • wyrmtale games

    right …

    It is not a bug but a ‘feature’

    I will explain :

    Because Orthello has a lot of functionality that has to be managed each update cycle, there are some things called ‘dirtyChecks’. These checks are executed each update cycle and are meant especially to handle things in editor mode.

    Like : Comparing the transform with the sprite.position and adjusting the sprite’s attributes accordingly is one of those things. Hence .. working with gameObject.transform, like in this lode runner example game.

    In the past versions (pre 2.4c) the bool OT.dirtyChecks was set to true, so that those dirty checks were performed at all time, but at a BIG cpu/fps cost.

    To improve (+150%) the overall performance of Orthello I have set this setting to be false by default.

    When no dirty checks are performed (default as of version 2.4c), moving sprites by setting the transform.position or transform.Translate, does not work anymore. The regular approach sprite.position is your way to go ….

    To solve this in this project there are 3 approaches.

    1. Use sprite.position, sprite.size and sprite.rotation to change your sprite.
    instead of the gameObject.transform class

    2. sprite.dirtyChecks= true;
    This particular sprite will execute its dirtyChecks (at a cpu/fps cost)

    3. OT.dirtyChecks = true;
    All sprites will execute dirtyChecks ( at a big cpu/fps cost)

    Hope this makes any sense.

    (and maybe a good thing to adjust the project download)

    regards,

    Martijn Segers
    WyrmTale Games.

  • Anna

    First of all: big thanks to author for this tutorial! I know that it cost a lot of work to prepare that, so hats off to you. :)

    @wyrmtale games: Thank you very, very much for your tip! :)

    @author: Please, add this information to the post – it will be easier to find solution for this common problem. :)

  • Grigory Kireyev

    Hi, Tim! Nice tutorial, i’ve just started with Unity, but stuck on the adding text.

    I see nothing. I did exactly as described, even tried to create via GameObject -> Create Other -> GUI Text… but still no luck. I can’t understand what happens.

    Objects was created but text doesn’t display.

  • David

    I’m stuck with the same problem.

  • Grigory Kireyev

    I restarted my computer and everything works! Probably it’s an occasional rare issue with Unity. Google-fu shows me an answer: “Restart”. =)

  • http://twitter.com/evandroabukamel Evandro Abu Kamel

    Nice tutorials! =)

    But I have a problem: my GUIText objects are not appearing. They are positioned at X = 0 and Y = 0; the Pixel Offsets are right as the tutorial says; I tried to put Material on them. Nothing changes.

  • http://twitter.com/evandroabukamel Evandro Abu Kamel

    SOLVED: On Scoring.cs I changed the .text attribute to .guiText.

  • Tyler Bell

    did you put the 592 for pixel offset Y? if so try maximizing your ‘Game’ window while playing to see if it shows up, because that number is associated with the size of the final placement and does not scale to the window size.

  • sweetjer

    for the record, I had EXACTLY the same issue with my level. I tried MANY different solutions for this. One of them was, as the Wyrmtale dev noted, to manually adjust the pos on each tile by -.01. Worked like a charm…but also a huge hassle to manually edit a level this way. I also tried adding borders — to the original tile, to the sprite sheet, etc, and all had either no effect or made it look even jankier. The final thing I tried was simply to reload the original atlas (the one we made in part 2) into the container after the level was completely built. For some reason that I don’t understand at all, this sorted it and lined everything up. Maybe this will help someone in the future: simply remove and reapply the atlas to the container. I think it may have something to do with those initial settings we apply to the atlas in Unity, but I’m truly not sure either way. It appears to me that it might have something to do with the TrueColor setting, as when I reapply the override to web option and set to TrueColor, it brings the problem back. I remove the atlas, reload it to the container (without any further changes to the compression beyond the initial which breaks the px alignment), and it’s magically fixed. Maybe someone with more knowledge on this kind of thing could find a reason why this is the case. Also using Win7 and Unity 4 free edition. Also worth noting: the version of the game you have located here (http://www.rocket5studios.com/2dgametutorial/Rocket52DGamePart5.html) has the same warping issue as in the screenshot. Maybe you can use your version of the program to test the issue? Seems isolated to Windows for some reason, though. Anyway, thanks for the tutorial, Tim. Despite having to pick thru a lot of stuff with a fine tooth comb to get it running with these newer versions of the tools, it’s been a great experience. In fact, some of the debugging has really helped me understand how the animation scripting works… I plan on fleshing the game out to completion to test my skills. So thanks!

  • UndeadPixel

    Be sure to have the Game Camera View at full size, for some reason the text doesn’t scale with the rest of the view (I guess it’s due to the font size and offset in pixels).

  • Andrew

    Thanks for the tutorial, Tim.
    Unfortunately, it would seem your sample files are out of date now that Unity has been updated to version 4. I downloaded the zip of the whole project up to this point and it simply does not work for my (latest) version of Unity.

    Are you aware of this? Or, am I just setting up your project files incorrectly?

  • Pingback: SkillSwap: Making A 2 Player 2D Game With Unity | Rocket 5 Studios