Unity 4.3 2D Tutorial: Physics and Screen Sizes

Learn how to use Unity’s 2D physics engine for collision detection, and deal with different screen sizes and aspect ratios. By Chris LaPollo.

Leave a rating/review
Save for later
Share
You are currently viewing page 4 of 6 of this article. Click here to view the first page.

Dealing with Screen Boundaries

When making games, you’ll often want to position sprites so they look good when running on devices with different aspect ratios. For example, imagine trying to display the player’s score in the upper right corner of the screen. If you positioned the score a fixed number of units away from the screen’s center, it would appear to be in different spots on devices with different aspect ratios, such as a 3.5″ iPhone, a 4″ iPhone and an iPad.

The following images demonstrate this point:

Score Label positioned at (3.5, 2.75) on iPhone 4

Score Label positioned at (3.5, 2.75) on iPhone 4

Score Label positioned at (3.5, 2.75) on iPhone 5

Score Label positioned at (3.5, 2.75) on iPhone 5

Respawning the enemy just off screen so she can walk into view poses the same problem as positioning a score label. You can’t pick a specific location because it might be off screen on a small device, but visible on a larger device, as shown in the following images:

bad_spawn_iphone4

Point positioned at (5.5, 0) on iPhone 5

Point positioned at (5.5, 0) on iPhone 5

To solve the above situation, you might think to try placing the spawn point further to the right to account for the largest possible device. However, that would also be incorrect because the game would then play differently on different devices, because the enemy would spend more time off screen on smaller devices than on larger ones. The following images show why:

Point at (7.5, 0). Enemy needs to traverse 2.7 units to appear on screen on iPhone 4.

Point at (7.5, 0). Enemy needs to traverse 2.7 units to appear on screen on iPhone 4.

Point at (7.5, 0). Enemy needs to traverse 1.82 units to appear on screen on iPhone 5.

Point at (7.5, 0). Enemy needs to traverse 1.82 units to appear on screen on iPhone 5.

Neither of those two scenarios is acceptable.

In this section, you’ll create a script that you can attach to a GameObject and it will position the object relative to one of the edges of the camera’s view.

If you don’t know how to do that, take a look at Unity’s tutorial video on cameras.

Note: This script will only work if your camera has an orthographic projection. Unity allows you to have more than one camera in a scene, so if you’re working on a game using a perspective camera, simply add a separate camera with an orthographic projection and set up your cameras so the second camera only renders the user interface.

Go to the Scripts folder in the Project browser, right-click and choose Create\C# Script. Name the new script ScreenRelativePosition.

Open ScreenReltaivePosition.cs in MonoDevelop and add the following instance variables to the script:

public enum ScreenEdge {LEFT, RIGHT, TOP, BOTTOM};
public ScreenEdge screenEdge;
public float yOffset;
public float xOffset;

This first line defines an enum type used to identify the four sides of the screen. You’ll assign screenEdge in the Inspector to position an object at the center of that edge of the screen, and you’ll set xOffset and yOffset to adjust the object’s position away from that point.

Add the following code inside Start:

// 1
Vector3 newPosition = transform.position;
Camera camera = Camera.main;

// 2
switch(screenEdge)
{
  // 3
  case ScreenEdge.RIGHT:
    newPosition.x = camera.aspect * camera.orthographicSize + xOffset;
    newPosition.y = yOffset;
    break;

  // 4
  case ScreenEdge.TOP:
    newPosition.y = camera.orthographicSize + yOffset;
    newPosition.x = xOffset;
    break;
}
// 5
transform.position = newPosition;

To keep things easier to digest, the above code only includes the logic for positioning along the right and top sides of the camera’s view. Here is what it does:

  1. It copies the object’s current position, ensuring the object maintains whatever z position you set in the editor. It also gets a reference to the scene’s main camera, which it needs to calculate the new position. If you ever use this script in a scene with more than one camera, modify it so you can specify which camera it should use.
  2. It uses a switch statement to calculate the correct position based on screenEdge. All calculations assume the center of the screen is at position (0,0) because that keeps the sample code the simplest. However, it means that if the camera in your game moves, as it will in Zombie Conga, then this version of the script will only work on child objects of the camera. You’ll see more about this in a bit.
  3. If screenEdge equals ScreenEdge.RIGHT, it positions the object based on the camera’s orthographicSize. Remember, the orthographic size is half the view’s height, so multiplying it by the camera’s aspect value gives you half the width, to which you add xOffset. You assign the result as newPosition‘s x value.

    As for newPosition‘s y value, you simply use yOffset because you know the center of the right side of the view has a y value of zero.
  4. If screenEdge equals ScreenEdge.TOP, it simply adds yOffset to the camera’s orthographicSize and assigns the result as newPosition‘s y value. Because you know the center of the top of the view has an x value of zero, you simply use xOffset for newPosition‘s x value.
  5. Finally, it updates the object’s position with newPosition.

Before moving on with this script, you should test your code. Save the file (File\Save) and go back to Unity.

Choose GameObject\Create Other\Cube to add a cube to your scene. Don’t worry, it’s just for a quick test.

Now drag ScreenRelativePosition from the Project browser onto Cube in the Hierarchy.

Inside the Inspector, set Screen Edge to RIGHT in the Screen Relative Position (Script) component, as shown below:

cube_position_settings

Make a note of the cube’s position within the scene, then play the scene and notice that the cube centers itself on the center of the right edge of the Game view, as shown below:

cube_right_in_game

Feel free to try out some other settings, remembering that you’ve only implemented RIGHT and TOP thus far. The following shows the cube positioned with Screen Edge set to RIGHT, YOffset set to 2, and XOffset set to -1.5:

cube_right_with_offset

Once you’re satisfied that your code works, right-click on Cube in the Hierarchy and choose Delete.

With positioning along the top and right edges working, switch back to MonoDevelop and try to add the cases for the left and bottom edges yourself. Check out the Spoiler below for a solution.

[spoiler title=”Need help finding the left or bottom of your screen?”]Inside ScreenRelativePosition.cs, add the following two case statements to the switch statement in Start:

case ScreenEdge.LEFT:
  newPosition.x = -camera.aspect * camera.orthographicSize + xOffset;
  newPosition.y = yOffset;
  break;
case ScreenEdge.BOTTOM:
  newPosition.y = -camera.orthographicSize + yOffset;
  newPosition.x = xOffset;
  break;

The only difference between the case for ScreenEdge.LEFT and the case you wrote earlier for ScreenEdge.RIGHT is that you want to move in the opposite direction before applying xOffset. You accomplish this by using negative camera.aspect rather than positive camera.aspect.

Likewise, the ScreenEdge.BOTTOM case uses negative camera.orthographicSize rather than the positive value used by the case for ScreenEdge.TOP.
[/spoiler]

When you’re done with the script, save it (File\Save) and switch back to Unity.

With ScreenRelativePosition.cs complete, you can now position objects in the same place regardless of screen size. You’ll use this in Zombie Conga to place the enemy’s spawn point just off the right edge of the screen.

Contributors

Over 300 content creators. Join our team.