Creating 2D Games with Unity3D Part 5 Complex Collision

collision iconWay back in the first part of this series, I mentioned that you can make complex collision objects in 3D packages like Maya or Blender to match the shape of your 2D sprites. Unity3D provides basic primitives like cubes and spheres, but sometimes you need more complex shapes to match the contours of the objects in your scene.

Even though this post is part of the “Creating 2D Games” series, these techniques will work for 3D games too. In fact, I created all of the 3D models for my iOS game Giant Moto using many of these techniques. I’ll be using Maya 2008 in this tutorial, but these concepts can be applied to your favorite 3D modeling package.

More Tutorials In This Series

Rocket’s Game, Example 1

This example shows how to make collision objects to match the shape of your 2D game characters. When a bullet collides with the Cat’s space ship, a small sphere will appear briefly to show where the bullet hit the ship’s collision mesh.

Click the image to load the example game in a new window:
Rocket's Game Collision Example

Making Collision For Rocket’s Ship

You can download “RocketsGame” project folder here. Remember that in order for the sprites in my project to display properly, you’ll need to use the Sprite Manager 2 plugin which is not included in my project. Once you have the project open in Unity, double click your “SM2 1.84.unitypackage” to import the package into the project. After that, you might also need to reassign the Sprite Material to the sprites in the scene – refer to Creating 2D Games with Unity3D Part 2 for details on how to do that. Note that I’m using Sprite Manager 2 v1.84.

After your project is set up and your sprites all look correct, we need to take a screenshot of the scene so that we can create a 3D model in Maya that will match the sprites exact shape. Use the following script to take a screenshot of your game (this is also included in controls.js in the project files).

function Update () {
	if(Input.GetKeyDown("s")) {
		print("screenshot");
		Application.CaptureScreenshot("Screenshot.png");
	}
}
  1. To take a screenshot, press the play button in Unity and then press the “s” key on your keyboard (assuming you’re using the script above). The word “screenshot” should print to the console to confirm it worked and you should find Screenshot.png in your project directory. Here’s what mine looked like.
  2. Open up Maya and confirm the following settings. Go to Window –> Settings and Preferences –> Preferences and then click on Settings. Make sure the “Up axis” is set to “Y” and Linear Working Units is set to “Centimeters”.
  3. To confirm that everything is working between Maya and Unity, create a 1x1x1 cube at 0,0,0 in Maya and then save the file in your project eg. RocketsGame/Assets/Models/cube.ma. Then switch back to Unity and drag the “cube” object into your scene. While still in Unity, go to Game Object –> Create Other –> Cube to create a cube. The cube you created in Maya and the one you created in Unity should be exactly the same size.
  4. Next we need to find the Unity/Maya unit size of the Screenshot.png file you made in step 1. Scale up the Unity cube you made in step 2 so that it fills the Game view exactly. My example project is set to 480×320 so my cube fills the screen at Scale X:15, Scale Y:10. Since we confirmed in step 2 that our Maya to Unity scale is 1:1, now we know how big to make the image plane in the next step.
  5. In Maya, create a plane Create –> Polygon Primitives –> Plane and then drag a plane out on the grid. Set the Translate X, Y and Z to 0 and set Rotate X to 90. Under polyPlane1′s INPUTS, set Width to 15 and Height to 10 (assuming your project is 480×320 like mine).
  6. With the plane selected in Maya, right click + hold on the plane and then go to Assign New Material –> Lambert. In the Attributes editor, click on the the little black/white checkerboard icon next to Color to bring up the Create Render Node window and then click on File. Now click on the the little folder icon next to the Image Name filed and browse to the location of the Screenshot.png we created in step 1 and click ok. You should see the .png on your plane, if you don’t press 6 on the keyboard to switch to texture view.
  7. Go to Create UV’s –> Planar Mapping and adjust the Projection Attributes in the Attributes Editor until the image looks correct on the plane. Click here to see what mine looks like.
  8. Now we’re finally ready to create the collision to match the sprite. Switch to the Front camera so that you’re looking at an orthographic view of the image. Go to Mesh –> Create Polygon Tool and trace out the shape of the sprite. Once you have the shape you like, you need to extrude the object to give it depth so that objects in your scene will be able to collide with it in 3D space. Go to Edit Mesh –> Extrude and extrude the mesh on the Z axis only so that it has about 1 unit of depth.
  9. You also need to make sure that the normals on the collision are facing out. With the object selected, open the Attribute Editor and then under Render Stats, make sure that “Double Sided” is unchecked. Now you should be able to see the actual polygon faces on your object. If any faces are pointing inward, you need to select those faces and then go to Normals –> Reverse.
  10. Center the pivot on your mesh and then snap the object to 0,0,0 on the grid to make sure that it’s perfectly centered in the scene and then Freeze Transforms to zero out the transforms.
  11. Now you could just save the scene into your project folder to import it into Unity. But the scene also has a plane with Screenshot.png on it which we don’t want in our scene – our sprites are being drawn with Sprite Manager so we don’t want this textured model in there too. Select the object in Maya and then go to File –> Export Selection, then click Export Selection and browse to the location in your Unity project where you want to save the model.
  12. Switch back to Unity and drag the collision object (“rocket” in my case) from the Project view into the Scene view. Set the Transform X, Y and Z to zero and you might also need to rotate the object 180 on the Y – I think the camera in Maya is on the opposite side as the camera in Unity so you can end up with mirrored results if everything isn’t setup properly.
  13. One more thing, we need to generate colliders on the mesh. With the object selected in the Project view in Unity, you should see the FBXImporter settings in the Inspector. Click the Generate Colliders checkbox and then click Apply.

Here’s what my finished collision looks like in Unity (I put a transparent material on the model so you can see the sprite through it).

Collision object in Unity

Whew. That looks like a lot of work, but once you do it a few times it’s a pretty quick process. As always, if anyone knows of a quicker way to do this please let us know in the comments.

What you have now is a collision object that’s very much like a stock Unity cube or sphere Game Object which means you can treat it like any other object in your scene. I’m not going to go into detail on how to make this new collision object into a playable character, but basically you just need to add your player sprite object as a child of the collision so that the sprite will move with the collision, uncheck the Mesh Renderer on the collision so it’s not visible and then add your control script to it. Again you can download the project here to see exactly how I have my scene setup.

Pachinko Thing, Example 2

Here’s another example that applies the techniques from above to static and animated level geometry. You can download the “2DPachinko” example here (again, you need to provide your own Sprite Manager plugin).

Click the image to load the example game in a new window:
Pachinko Thing collision example

And here’s what the collision looks like in Maya and in Unity.

Maya and Unity collision

Conclusion

This post demonstrated a couple of the possibilities when combining 2D art with 3D collision objects in Unity3D. I’m always looking for ways to improve my own workflow, so if you see any errors or have any suggestions, please feel free to post in the comments. Oh and the little kitty cat that’s flying the red rocket is from the Open Clip Art Library.

This post is part of iDevBlogADay, a group of indie iPhone development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, or Twitter.

More Tutorials In This Series

Creating 2D Games with Unity3D Part 1
Creating 2D Games with Unity3D Part 2
Creating 2D Games with Unity3D Part 3
Creating 2D Games with Unity3D Part 4
Creating 2D Games with Unity3D Part 5

And here’s another more recent tutorial series that uses Orthello (free) for the sprite display and animation duties:
Make A 2D Game in Unity3D Using Only Free Tools Part 1
Make A 2D Game in Unity3D Using Only Free Tools Part 2
Make A 2D Game With Unity3D Using Only Free Tools Part 3
Make A 2D Game With Unity3D Using Only Free Tools Part 4
Make A 2D Game With Unity3D Using Only Free Tools: Beginning Enemy AI With A* Pathfinding

Show Your Support

If you find these tutorials useful, please considering buying one or more of our games and apps for iPhone and iPad. Your support helps to keep the tutorials flowing!

  • Giant Moto: High flying arcade style motocross action!
  • Small Space: Fly a spaceship, eat space creatures, score point!
  • Holeshot Drag Racing: High speed drag racing action!
  • Alien Booth: Transform pictures of your friends into awesome aliens!
  • iSpoof Walken: A hilarious look into the world of Christopher Walken!
  • Gaga Eyes: Transform pictures of your friends to give them huge anime eyes!

About the author

Tim MillerTim Miller is a veteran game developer with over 15 years experience in the video game industry working as a Level Designer and Lead Level Designer at LucasArts, Secret Level and Nihilistic Software. He co-founded Rocket 5 Studios with his wife Cathy and their dog Rocket in 2009. Twitter, LinkedIn, Portfolio

Share/Bookmark
  • Valemming

    Really great stuff :)

    Thanks so much!!

  • Pingback: PUCHEPE'S(プチピィーズ) - Unity関連で使っているものを、リンクしてみました。

  • http://www.nuverian.net Gavalakis Vaggelis

    top

  • ravin

    Thank you, you helped me so much. I just having issues where the player walks left or right and the animation loop freezes then continues when the player stops.

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

    I don’t quite understand the issue.  Can you give me some more information?

  • ravin

    Yeh, I have tried to by pass the issue with my current code, but it still happens. Walking left for example shows frame ONE of the walk left animation until you stop, then it plays the loop of walk left, until a new direction is entered.

    The code:using UnityEngine;using System.Collections;public class Controls : MonoBehaviour {        public PackedSprite playerSprite; // assign your sprite to this in Unity      public float speed = 6.0F;    //  public float jumpSpeed = 8.0F;    public float gravity = 20.0F;      private Vector3 moveDirection = Vector3.zero;       void Update()  {           CharacterController controller = GetComponent(); if (controller.isGrounded)  {            moveDirection = new Vector3(Input.GetAxis(“Horizontal”), 0, Input.GetAxis(“Vertical”));            moveDirection = transform.TransformDirection(moveDirection);            moveDirection *= speed;             // if (Input.GetButton(“Jump”))        //        moveDirection.y = jumpSpeed;                    }        moveDirection.y -= gravity * Time.deltaTime;        controller.Move(moveDirection * Time.deltaTime);        DetermineCurrentMoveDirection(); } public void DetermineCurrentMoveDirection() {            var forward = false;            var backward = false;            var left = false;            var right = false;        // move left          if(moveDirection.x > 0.01f)  {            left = true;          }            // move right          else if(moveDirection.x 0.01f)  {            forward = true;        }            // move down          else if(moveDirection.z < -0.01f)  {            backward = true;        }        else             {            forward = false;            backward = false;            left = false;            right = false;            }        if (left == true)        {            playerSprite.PlayAnim(3);        }        // move right          if (right == true)        {            playerSprite.PlayAnim(2);        }        // move up          if (forward == true)        {            playerSprite.PlayAnim(0);        }        // move down          if (backward == true)        {            playerSprite.PlayAnim(1);        }     }      }  

  • ravin

     I have tried to by pass the issue with my current code, but it still happens. Walking left for example shows frame ONE of the walk left animation until you stop, then it plays the loop of walk left, until a new direction is entered.
    I need a way to call the animation that will allow the animation to play once for that direction until the player picks another direction and then uses it again.

    sorry for the other post.

  • ravin

    End result of what I am looking for: Able to walk up, down, left, right, and the loop for the directions play as the player dose them. As it is now, the animation will not play the loop until the player lets go of the key. This issue has come up with the “GetKey” command as well. Unless I am missing something.  Thank you for any help you could provide.

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

    Ok I understand the problem now, but I can’t debug the code you pasted above because the formatting was lost in the comment (not your fault).  

    Can you post you code in http://pastebin.com/ and then post the link back here so we can see the properly formatted code?

  • ravin

    http://pastebin.com/rSfBAAgs
    Ok, thanks for the help, and sorry about the delays in posts, I work 3 jobs.

  • ravin

    I fingered it out, my teacher showed me how to do it. Thanks any who

  • ravin

    http://pastebin.com/F9qeBHUG

    This is my teachers solution. I will be adding in code to force up and down animation for when the player hits Left+Down as an example.

  • Pingback: Creating 2D Games With Unity3D Part 4 | Rocket 5 Studios

  • Pingback: Creating 2D Games With Unity3D Part 1 | Rocket 5 Studios