Making Things Move

This is an excerpt chapter from my Weekend Code Project: Unity’s New 2D Workflow book. I hope you enjoy this free content on how to use Unity’s new 2D features. If you like what you see, please pick up a copy of the book to get access to the artwork, source code and a PDF/ePub version of the book.

Working with Box2D

With the addition of the new 2D workflow in Unity, there is now Box2D to handle all of your in-game physics. This is great news because you can take advantage of a common 2D physics engine, as well as avoiding the overhead of the built-in 3D physics engine. To get started, let’s add a new component onto our Player prefab. Select the Player in the Prefab folder, not the one in the Hierarchy tab, and in the Inspector panel click Add Component. From there, select Physics 2D to see all of the options.

To get started, we are going to add Rigidbody 2D to our Player prefab. By adding a Rigidboxy 2D component we are telling our GameObject that it needs to obey the laws of physics in our game. We will have the ability to manage the GameObject’s Mass, Drag, Gravity Scale and a few other important properties that help make up the physics of the Box2D engine. Now that you have the Rigidbody 2D added to our prefab, you should see these new properties.

Try to run the game. At this point we would expect the player to fall since it has a Gravity Scale of 1 but it just floats in one place. To fix this, make sure you go into the Animation settings on the Player prefab and uncheck Apply Root Motion, which is selected by default. This is a setting that is normally used in conjunction to Unity’s 3D animation system, Mecanim and is set to true by default. We will need to disable this since our sprite animation doesn’t have any motion data attached to it.

Once this is fixed and you run the game, the Player will fall off the screen since gravity is being applied to it. To counter this, we are going to want to make the ground GameObject solid. Select the ground instance in the Hierarchy view, or in the Scene itself, and add a Box Collider 2D component to it.

Here you will see we can define the size of the collider and its offset. Before we move on, we are going to want to clean this collider up a little. We want the player to look like he is walking inside of the ground area, not on top of it. To make this happen, we will need to modify the Size and Center of the collider. The Size X value should be 12.8 and the Y value is 0.8. Likewise the Center X value will be 0 and the Y value is -0.75 like so:

Now, if you look at the ground, you will see that the green box that helps us visualize the collider is now closer to the bottom of the image.

The last thing we need to do is go back into our Player prefab and add a Box Collider 2D to it. Once you have added the collider, you should be able to test the game again and see that the Player now falls onto the ground and no longer goes through it. We’ll just need to make sure the player’s collider has the same dimensions as the artwork. If your collision box is not the same size as the sprite, set its Size X value to 1.6 and the Y value to 2.4 like so:

Now try running your game and you will have the Monster fall into the correct position.

Right now the Player is kind of boring when he drops. We should add a little bounce to him. To do this, we will need to create a special kind of component called a Physics2D Material. To do this, we will need to click on the Create button in the Project tab and add this to our Misc folder.

Name it GroundBounce and change the Bounciness to .3.

 

Now we can add this to our ground GameObject’s Box Collider 2D component. Select the ground from the Hierarchy tab and click on the little circle next to the Material input field on the Box Collider 2D component. You will get the following menu that allows you to pick from any GameObject in the current scene, or from our Assets folder.

 

Select GroundBounce and then run the game. Your Player should do a nice bounce when he hits the ground. 

The last thing we are going to want to do is set up our bad guy to be able to collide with the player later on when we start to move him. Select the Knight prefab and let’s add some components to it. Start with adding a Rigidbody 2D then setting Gravity Scale to 0, and checking Fixed Angle. Also, add to Box Collider 2D a Size of X to .24 and Y to.0.6. In the end, it should look like this:

By setting the Gravity Scale value to 0 we insure that it will not fall no matter where we end up spawning him on the screen and checking off Fixed Angle insures that he will always stay upright no matter what he collides with. Now let’s talk about how to move the player and the bad guys. Before we do that, just put the instance of the Knight prefab in the scene closer to the ground so he will be ready to move in the next section.

Moving the Bad Guys

At this point, we are ready to start coding. We’ll begin with getting our bad guys to walk forward. To do this, we will write a simple script in C#. Let’s create this in the Scripts folder and call it MoveForward.

Once you have your new class open in your code editor, add the following property:

public float speed=.3f;

You can also remove the Start method; we won’t be using it. Now add the following code to the Update method:

rigidbody2D.velocity=new Vector2(this.transform.localScale.x, 0) * speed;

Basically, what this script is doing is setting the velocity of the default Rigidbody 2D component to match the localScale multiplied by speed. This will move the Knight forward since the default localScale x value is 1. So every frame we are basically setting the velocity to .3. I’ll show you why multiplying the speed by the localScale is important after we finish setting it up. All we need to do now is open up the Knight prefab and add this script as a component.

Now, if we run the game, you should see your Knight move forward. You can always adjust the speed value by changing it on the instance itself, the prefab so all newly created instances get the new value, or finally in the code itself. Later on, when we dynamically spawn these Knights, you can play around with assigning a new speed to them via code.

There is one more thing I want to go over with the knight, which is how to control what direction he is moving in. You may have noticed that we are taking the localScale and multiplying it by the speed to set the velocity. If you select the instance of the Knight in the Scene and look at the top of the Inspector panel, you will see the Transform component. The last value here Scale. A neat trick for making any GameObject face to the left, assuming their default position is to face right, is to change the Scale X to -1.

Here you will see that the Knight is now facing left. If you run the game, he will automatically move to the left now. This is because we set him up to use Scale as the speed modifier. If you think about it, positive velocity will move him to the right and negative velocity will move him to the left. Now we can start talking about moving the player.

Controlling the Player

Let’s create a new script that we will use to manage our player’s movement. Call the script Player and attach it to the Player prefab. Add the following properties to the class:

public float speed=200;
public float maxSpeed=5;
int moving=0;

This movement script is going to be a little different. Not only will we have a speed, but also since we will be applying a force to move the player, we will need to make sure that the player doesn’t exceed the maximum speed we want it to move at. In addition, since we don’t want to be applying that force when the player doesn’t have a key down, we will need to know when we want to be moving or when we should stop.

Now let’s start handling the basic logic to change the direction the player is facing. Delete the Start method, since we don’t need it, and add the following to the Update method:

if (Input.GetKey("right"))
{
 moving=1;
}
else if (Input.GetKey("left"))
{
 moving=-1;
}
else
{
 moving=0;
}

Here you can see we are going to change the value of the moving property based on the key being pressed. In Unity, it is very easy to get the current key being pressed. Simply ask the Input class for the key and pass in the key you want. Here we are simply looking for the right key to set moving to 1, the left key sets it to -1, and if neither key is pressed we set it to 0. Now add the following code after the conditional we just added:

if (moving !=0)
{
 var velocityX=System.Math.Abs(rigidbody2D.velocity.x);
 if (velocityX < .5)
 {
 rigidbody2D.AddForce(new Vector2(moving, 0) * speed);
 if (this.transform.localScale.x
 Vector3(moving, 1, 1);
 }
 if (velocityX > maxSpeed)
 rigidbody2D.velocity=new Vector2(maxSpeed * moving, 0);
}

There is a lot going on here, but we’ll talk through what is going on. First, we test to see what the value of moving is. If the Player should be moving, we get the absolute value of the Player’s current velocity. Remember back to our knight that we use positive for right and negative for left. Using System.Math.Abs will always turn a value as a positive number, so it will easier for us to get an accurate idea of the actual velocity and not the direction it is being applied in. Now, with the velocityX value, we can test to see if we should apply a force.

Let’s talk about velocity for a second here. Up until this point, we have always been applying a constant value to a GameObject’s velocity, but if we stopped applying that force, it would gradually ramp down to 0. For our player, we are simply testing to see if the velocity is at half of its value before we are able to apply a force to our Player instance. In the next line, you will see how we move a Box2D object by simply calling AddForce on the rigidbody2D property. This method accepts a Vector2 representing the force’s x and y values. Since we just want to move the player along the x-axis, we will set the X value of the Vector2 to 1 and leave the Y value at 0.

Now we do a quick test to see if the Player’s localScale.x does not equal the moving value. If it doesn’t, we simply update the localScale to match the direction the Player instance is moving in. And, at the end of all of this, we make sure that the Player’s velocity is not greater than the maxSpeed we allow the Player to move at. If the value is greater, we simply reset the rigidbody2D’s velocity to the maxSpeed. The end result should give the effect that the player is sliding forward based on the direction of the key that was pressed. This will be a little different then what you may be used to in a game since we want the monster to appear like it is lunging towards the bad guys.

While it may look like a lot of code, it’s actually very straightforward, and these are the basics of how movement works in Unity. The best part is that we now have two encapsulated scripts we can reuse in other games if we ever need an enemy to simply move forward or want to move a Player left and right along the x axis. 

You may have noticed that the Player can be knocked down if you run into the Knight too quickly.

Since we are using Box2D physics, objects in the game world are going to react a little differently than you may expect in a normal 2D environment. As you may remember, we had set the Knight to have a Fixed Angle. This locks it into place so any other GameObject that collides with it will attempt to move around the smaller GameObject. In this case our Player will try to fall over the Knight. To help fix this, let’s open up our Player prefab and check the Fixed Angle toggle option in the Rigidbody 2D component.

Now the Player GameObject will not fall over the Knight. You may want to do the same thing for the Knight prefab as well, if it’s not already checked. 

Now there is one last thing we should do when it comes to controlling our player. We saw how easy it was to use the keyboard but eventually we will want to publish this game to mobile or maybe the player likes using the mouse. To handle this we can use a few extra lines of code to add basic mouse/touch controls for our game. The idea will be that we will capture the mouse press and detect if it’s on the left hand side of the screen or the right hand side of the screen. From there we can detect which direction to move the player in. Let’s modify our Player script with an extra property:

float mouseX=0;

Then at the top of our Update method, before where we test for the keyboard input add the following conditional:

if (Input.GetMouseButtonDown (0)) {
  mouseX=90 * ((Input.mousePosition.x - Screen.width / 2) / (Screen.width / 2)); 
} else {
  mouseX=0;
}

What this does, which is similar to how we captured the keyboard event, is look for the mouse button to be down. In this case the 0 represents the left mouse button. From there we divide the screen’s width in half. This will determine if the value is negative or positive. If the mouse is not down we simply set the mouseX to 0. Now we can simply test the value of mouseX and deduce what direction the player should move in. To do this we need to modify the next conditional. We’ll need to make the following change from:

if (Input.GetKey("right"))
{
 moving=1;
}
else if (Input.GetKey("left"))
{
 moving=-1;
}

to this:

if (Input.GetKey("right") || mouseX > 0)
{
 moving=1;
}
else if (Input.GetKey("left") || mouseX &lt;0)
{
 moving = -1;
}

If you run the game now, you should be able to use the mouse to move the player left and right in addition to the keyboard. Now we can talk about the camera and how to make it follow the Player GameObject as it moves around the screen.

Touch Controls

We cheated a little in our game by only relying on a single point of input, the mouse. The good news is that you should get touch support built in when you run it on touch enabled devices like Android, iOS, Windows 8 and Windows Phone. Unity supports a multi-touch API but we will not be covering it here. I just wanted to bring this up as you create more complex games that you will need to consider what input looks like across multiple devices. In my games, as you can see, I always try to keep the input to a single source so it works seamlessly across multiple devices well while offering keyboard or controller support on platforms that can support it. Make sure to check out Unity’s input documentation at http://docs.unity3d.com/Documentation/Manual/Input.html.

Subscribe To My Mailing List

Want to learn how to make a game? Not sure where to start? Even if you are a seasoned game maker there is still a lot you can learn from my mailing list. I'll be covering tips and tricks for how to build, release and market games each month.

Simply sign up for my mailing list and also get access to a 50% off discount code for my eBooks and other content. I promise to not spam your inbox!

Join Now