Introduction
Unity is a well known, well documented, and very recognised game engine. It's a multi-platform solution, and it also allows you to create games or applications aimed at several platforms (iOS, Android, Web, and PC, among others). Originally, Unity was focused on 3D development, but recent releases provide tools for 2D development.
Unity is a great choice for aspiring game developers, since it works for most mobile, desktop and console platforms, and even better, it is free to use for lower-revenue developers and studios.
One of the key components of Unity are physics joints. Those joints have physical properties (as the name suggest) and let you create several connections between objects within your scene.
Using joints, you can describe a connection between two objects, which means you can simulate the physics of almost any multi-part object you can think of, including doors, sliding platforms, chains, or even wrecking balls!
This tutorial will focus on explaining how 2D physics joints work and how to use them to achieve great effects (without sacrificing the game performance).
Prerequisites
First, ensure you have the latest version of Unity, which you can download here. In this tutorial we're using the version 5.4.1f1. Make sure that you are using the latest Unity version; otherwise you may have problems following the tutorial and using the physics joints.
Before we start, I would also like to give special thanks to Ryukin Studio for letting us use their package 2D Platformer Art Pack - Demo for this tutorial.
Next, download the Unity2DJointsStarter file. Unzip and open the project in Unity. The Demo scene should open automatically, but if not, you can open it from the project’s Scene folder.
The scene should look as follows:
As you can see, we have a character and several static platforms placed around the scene. The idea behind this tutorial is to create a small 2D platform game while using the 2D joints to create obstacles for the player to overcome. Throughout this tutorial, you’ll get to try out each of Unity’s 2D joint types and see how they work, with the exception of the Wheel Joint 2D.
If you press play, you’ll see that all the basic gameplay functionalities for the game are already implemented. You can use the keyboard arrows to move the character and the spacebar key to jump.
Distance Joint 2D
The distance joint allows a sprite controlled by 2D physics to rotate around a specific point, while maintaining a certain distance from that point. You’ll use the distance joint 2D to create the first obstacle, a swinging blade. Create a new GameObject in the Position (4.75, -1.25, 0) and call it Blade.
Next, expand the GameAssets folder and open the Platforms folder. There you will find several prefabs used for creating the level platforms. Drag the Platform6 prefab from the folder and drop it over the BladeGameObject. This will make it a child of that object.
Now you need to edit some of the properties of this new game object. First, change the Platform6 name to Platform and then its position to (-0.07042211, 3.60032, 0). Now set the Order in Layer to 3 in the Sprite Renderer component.
Inside the Box Collider 2D, disable the Used by Effector parameter and remove the attached Platform Effector 2D component. Finally, add a Rigidbody 2D, set Is Kinematic to true, and turn Freeze Rotation on in Z.
The platform that will hold the blade is ready. It is time to add the blade itself. Inside the Free Assets\Sprite folder, select the AxeBlade sprite and drag it over the Blade GameObject, creating a new child.
As you've probably noticed, the sprite is too big, and it’s not in the right place. Change the Position to (-0.11, 3.56, 0) and the Scale to (0.5, 0.5, 1). Also, set the Order in Layer to 2.
Before you can make the blade work, you will need to add several components to it. Start by adding a Polygon Collider 2D and a Rigidbody 2D. Make sure that the Mass is set to 10.
You are now ready to add the Distance Joint 2D. Add the Distance Joint 2D component. As you may notice, this new component has several parameters that you can adjust to produce the best result for your game.
Fear not, you’ll soon learn what all these parameters do and how you can adjust them. You’ll also notice that once you have the component attached to the AxeBlade, a green line extends from the AxeBlade to the center of the screen. This is the origin point, the Connected Anchor property.
Run the scene, keeping your eye on the blade. Right away, you’ll notice that the blade flies across the screen until it stops near the origin point, then begins to roll back and forth on the joint. You will need to fix this issue.
Turn your attention to the Distance Joint 2D component in the Inspector. The first parameter is Enable Collision. This determines whether or not the two objects connected by the joint can collide with each other. In this case, you don’t want this to happen, so leave it unchecked.
The second parameter is Connected Rigid Body. While one end of the distance joint always remains connected to the object that contains the component, you can use this field to pass a reference to an object for the other end of the joint’s connection. If you leave this field empty, Unity will simply connect the other end of the joint to a fixed point in the scene.
You want to connect AxeBlade to Platform in this case, so drag Platform to the Connected Rigid Body field.
With the connection set up and AxeBlade still selected, you should now see the two objects connected by the joint in the Scene view. You can check the connection by changing the Y value of the AxeBlade. Don't forget to set the AxeBlade Position back to (-0.11, 3.56, 0) once you have finished playing with it.
The next parameter of the component is Auto Configure Connected Anchor. You should check this box if you want Unity to automatically set the anchor location for the other object this joint connects to. What’s the anchor, you may ask? Well, we will talk about it in a moment, but for now, you need to learn that the anchor point can be set manually or automatically (by Unity).
In this case you want to leave this field unchecked, since we are going to set the anchor manually.
The following parameter is Anchor. This one indicates where the endpoint of the joint attaches to the GameObject as specified in the object’s local coordinate space. In the Scene view, with AxeBlade selected, you can see the anchor point as an unfilled blue circle centered over AxeBlade. Leave the default value unmodified (0, 0).
Note that the unfilled blue circle representing the joint’s first anchor point may appear filled if you currently have the Transform tool selected in the Scene view. Likewise, you will see a white square if you have the Scale tool selected. In either case, moving the anchor away from (0, 0) will show that it is indeed an unfilled circle.
The Connected Anchor parameter specifies the anchor point of the other end of the joint. If the Connected Rigid Body field is empty, this value is in the scene’s coordinate system. However, when Connected Rigid Body is set, as it is now, the Connected Anchor coordinates refer to the connected rigid body’s local coordinate space. This anchor point appears in the above image as a solid blue circle centered over the Platform game object. Once again, you can leave this value at (0, 0).
As with the Anchor parameter, you can let Unity automatically set the distance of the joint by enabling the Auto Configure Distance field. When this option is on, Unity will automatically detect the distance between the two objects and set it as a distance that the joint keeps between them. In our specific case, we want this feature on.
The Distance parameter, as the name suggests, indicates the distance to maintain between both objects. Back in the Scene view, you can see a small green line intersecting the line connecting the two objects. This can be easily seen if you move the AxeBlade object from the Platform, as in the image below.
This line indicates the distance enforced by the joint. When you run the scene, the joint will move AxeBlade so that the Anchor you defined is at the point where the small line is. You can increase or decrease this value by turning Auto Configure Joint off. Remember to set the AxeBlade position back to (-0.11, 3.56, 0) once you have played with its values. Auto Configure Distance should also be checked.
The next parameter is Max Distance Only. If enabled, the joint will only enforce a maximum distance, meaning that the objects can get closer to each other, but never further away than the value specified in the Distance field. In this example, you want the distance to be fixed, so leave this parameter unchecked.
Finally, the last parameter is Break Force. Here you can specify the force level you want to use to break the joint. Basically, if the force level is reached, the joint will be deleted and the connection between the two objects will disappear. When the value is set to Infinity, it means that the joint is unbreakable. For this scenario, you want it to be unbreakable, so leave the field as it is.
Since you want the blade to swing like a pendulum, change its Rotation to (0, 0, 310).
Now, press Play, and you will see the AxeBlade hanging on the Platform.
Ok, so the blade is swinging, but when it hits the player, nothing happens. You want to kill the player and make it restart on the latest checkpoint. To do this, go to the GameAssets folder, and open the Scripts folder. Grab the Blade script and add it to the AxeBlade. If you press Play again, the player should now die when the blade hits.
The final configuration is the following:
To finish, grab the Blade GameObject from the Hierarchy and drop it in the Obstacles folder. This will create a prefab of the swinging blade.
Hinge Joint 2D
The Hinge Joint 2D component allows a GameObject controlled by rigid-body physics to be attached to a point in space around which it can rotate. The rotation can happen in response to a collision or be started by a motor torque provided by the joint itself. You can and should set limits to prevent the hinge from making a full rotation.
In order to learn the basics of the hinge joint, you will create a dual trapdoor mechanism where the player has to drop to continue the level. Let’s do it!
Add a new empty GameObject, name it Hinge, and place it in the Position (18.92, 0, 0). Then, open the Assets\Free Assets\Sprites and drag two MetalPlatform sprites into the Hinge GameObject. Name the first HingePlat1 and the second HingePlat2.
Place them side by side; the HingePlat1 should be placed at Position (0, 0, 0) and the HingePlat2 at (2.5, 0, 0). Change the Order in Layer of both to 2.
In order to add the Hinge Joint 2D component, you need to add two additional components to the sprites. Select the HingePlat1 and add a Box Collider 2D and a Rigidbody 2D. Under the Rigidbody 2D parameter, check the Is Kinematic property. Now, repeat the same steps for the HingePlat2 (without checking the Is Kinematic property).
You may also notice that the Size of the Box Collider 2D is bigger than the HingePlat1 sprite, thus leading to incorrect collision detection between the player and the platform. To fix the issue, change the property Size (inside Box Collider 2D) of both HingePlat1 and HingePlat2 to (2.45, 0.5).
This HingePlat2 will be the initial trapdoor. Therefore, you need to assign a new component called Hinge Joint 2D. This component has several new properties; we will only cover the new ones.
Enable Collision means that the two connected objects can collide between them. Connected Rigid Body specifies where the other object is that this joint connects to. Add the HingePlat1 to this field. Use Motor specifies if the hinge motor should be enabled. You should check this property. Motor Speed specifies the target motor speed in degrees/sec. Set it to -100 (to return to the original position from the upward position).
Maximum Motor Force represents the maximum torque (or rotation) the motor can apply while attempting to reach the target speed. You should set it to 25. Use Limits, as the name suggests, represents the rotation angle limit threshold. Check it!
Lower Angle is the lower end of the rotation arc allowed by the limit, while Upper Angle is the upper end of the rotation arc allowed by the limit. Change the Upper Angle to 60. Break Torque is similar to Break Force and specifies the rotation level needed to break and delete the joint. Again, Infinity means it is unbreakable.
Now uncheck the Auto Configure Connection. You must set the Anchor and Connected Anchor manually. The former should be set to (-1.12,0), and the latter to (1.09,0). Your Scene should now look like the following image:
The final HingePlat2 configuration is:
Run your game, and let's test the first trapdoor.
If everything is OK, it is now time to move on and create the second trapdoor. The procedure is exactly equal to the aforementioned description; the only difference lies in the configuration details of the Hinge Joint 2D. The main steps are:
- Add two additional MetalPlatform sprites to the Hinge GameObject.
- Name them HingePlat3 and HingePlat4, and set the Order in Layer to 2 and the Position to (4.87, 0, 0) and (7.25, 0, 0) respectively.
- Add a RigidBody 2D and a Box Collider 2D to both platforms.
- Change the Size of both Box Collider 2D to (2.45,0.5).
- HingePlat4 should have Is Kinematic enabled.
- Add the Hinge Joint 2D property to the HingePlat3.
- Add the HingePlat4 into the Connected Rigid Body of the HingePlat3.
- Uncheck the Auto Configure Connection.
- Change the Anchor to (1.5, 0) and the Connected Anchor to (-1, 0).
- Check the Use Motor property and set the Motor Speed to 100 and the Maximum Motor Force to 25.
- Check the Use Limits, and the Upper Angle should be -60.
Run your game, and let's test the dual trapdoor.
Since we want to force the player to pass through the dual trapdoor, we must create some walls around it. Select the Hinge GameObject and from the Assets\Free Assets\Sprites folder add six MetalPlatform into the Hinge GameObject. Name them from Wall1 to Wall4 and change the Order in Layer to 2.
Place the Wall1 in the Position (-0.9, -1.43, 0) and change the Z Rotation to 90. The remaining should be configured as follows:
Wall2 Position: (-0.9, -3.8, 0), Z Rotation: 90
Wall3 Position: (8.2, 1.55, 0), Z Rotation: 90
Wall4 Position: (8.2, 3.95, 0), Z Rotation: 90
Now, for each wall you should add one additional component, a Box Collider 2D. For each Box Collider 2D change the Size to (2.21, 0.63). Next add a Platform Effector 2D to each wall and set the Surface Arc to 360 and the Side Arc to 180. Go back to the Box Collider 2D and turn Used By Effector on.
The final result should be similar to:
Finally, drag the Hinge GameObject into the GameAssets\Obstacles folder to create your second prefab.
Target Joint 2D
The Target Joint 2D connects to a specific target, rather than another rigid body object, as other joints normally do. We will apply this joint to create an obstacle platform that moves upwards and downwards.
The first thing you need to do is to create the platform itself. On the Free Assets/Sprites folder, there you will find the MetalPlatform sprite. Drag it and place it on the scene.
Change its name to RisingPlatform and its Position to (35, -6, 0), and set the Order in Layer to 2. You need some components to make this work. Add a Rigidbody 2D and a Box Collider 2D. Next, set the Mass to 20 and check Freeze Position X and Freeze Rotation Z. On the Box Collider 2D, make sure the Size is set to (2.35, 0.55). Finally, set the Gravity Scale to 0 so that the object is not affected by gravity.
The basic components are now ready. It is now time for you to add the Target Joint 2D component. As aforementioned, the Target Joint 2D does not connect to another object with a rigid body; instead, it connects to a specific target. This is a spring type joint and can be used for picking up and moving objects acting under gravity, like our moving platform.
Let’s take a closer look at the component itself. The Anchor works exactly like in the previous joints, so there is no need to explain it. The Target sets the world coordinates towards which the joint attempts to move. This is a very important field, since this joint will try to keep zero linear distance between the Anchor and the Target points. For this example, you want the Target to be (35, -6).
Next, you have Auto Configure Target. If this property is enabled, the joint will calculate the target by itself. If you leave this option on, the target will change as the platform moves. Since you don’t want that to happen, leave this box unchecked (uncheck Auto Configure Target).
The following is Max Force; here you set the force that the joint can apply while trying to reach the target position. Set this value to 80.
The Damping Ratio is the degree to which you want to suppress spring oscillation. This value can go from 0 to 1, where 1 means no movement. You want the platform to move freely, so set this field to 0. Next, you have Frequency which, as the name suggests, sets the frequency at which the spring oscillates while trying to reach the target. Set this parameter to 5.
Finally, the last one is Break Force, which is identical to the previous joints, so let the value stay at its default.
Since you want your platform to keep moving over time, you need to change the Target position from time to time. Fortunately, you already have the script to handle that. Go to the Scripts folder, find the TracktorPlatform script, and add it to your game object. Set Target A to (35, -6) and Target B to (35, 0). The Time should be 2.
By the end, your component should look like this:
If you press Play, you should be able to see the resulting target joint working as intended. Don’t forget to create a prefab, as you did with the previous obstacles, and place it in the Obstacles folder.
Fixed Joint 2D
The Fixed Joint 2D is used to keep two objects controlled by rigid-body physics relative to each other. Therefore, both objects are always offset at a given position and angle.
To use this joint, you will create a metal platform that can only be moved when the player moves a magnet attached to it. The player will have to push the magnet in order to remove the platform from its way and then progress on the level.
Start by creating an empty GameObject, name it MagnetPlatform, and set its Position to (41.81, 5.22, 0). Next, grab the Magnet sprite from the Sprites folder and drop it over the MagnetPlatform. Set the Magnet Position to (0.55, 3.15, 0) and the Order in Layer to 3.
Next, add a Rigidbody 2D component and a Circle Collider 2D. Set the Mass to 200 and turn Freeze Rotation Z on. Make sure the Radius on the Circle Collider is set to 0.4. By the end, your Magnet should look something like this:
Now, from the Sprites folder, drag the MetalPlatform sprite into the MagnetPlatform GameObject. Set the Position of the MetalPlatform to (0.57, -1.73, 0), the Rotation to (0, 0, 90), and the Scale to (2, 1, 1). Set the Order in Layer to 3.
Next, add the following components: Rigidbody 2D, and a Box Collider 2D. On Rigidbody 2D, set the Mass to 1000 and enable Freeze Rotation Z. Finally, on BoxCollider 2D, set the Size to (2.31, 0.52).
Now that everything is ready, it’s time for you to configure the Fixed Joint 2D and establish the connection between the magnet and the metal platform. With MetalPlatform selected, add the FixedJoint 2D component.
This new joint allows two game objects with a rigid body to maintain a relative linear and angular offset to each other. In this case, you want the metal platform to keep a certain distance from the magnet.
These linear and angular offsets are set on the relative positions and orientations of the two connected game objects. This means that when you change the position of one of the objects in the Scene View, you will also update the offsets.
This joint uses a simulated spring that is configured to be as stiff as possible. However, it’s possible to change the spring’s strength and make it weaker. This simulated spring applies its force between the objects, and it’s responsible for keeping the offsets you desire.
Taking a look at the component itself, you will find several fields that you are already familiar with.
With the exception of two of those fields, all parameters work exactly like on the other joints, so there is no need to explain them again. Regarding the Damping Ratio, this parameter represents the degree to which you want to suppress spring oscillation. You can set values from 0 to 1, where 1 means no movement.
The Frequency is the frequency at which the spring oscillates while the two connected objects are approaching the separation distance. This parameter can take values from 1 to 1000000. The higher the value, the stiffer the spring will be.
Note that, although higher values mean a stiffer spring, if you set the Frequency to 0, the spring will be completely stiff.
Now, regarding the obstacle you are trying to build, all you need to do is to drag the Magnet game object to the Connected Rigid Body field. All the other parameters can be left with their default values.
Press Play and test the new obstacle.
Now that the obstacle is ready, create a prefab of it by dragging the GameObject to the Obstacles folder.
Conclusion
This concludes the first tutorial about Unity Joints 2D. You learned about four joints, namely the distance, hinge, target, and fixed joints. With this knowledge you can already start creating your 2D worlds filled with dynamic and complex objects. In the second tutorial, you'll learn about the slider, relative, spring, and friction joints.
If you have any questions or comments, as always, feel free to drop a line in the comments.