How can I get Rect.Contains to work properly with touch input?


So I’ve just finished a lovely 2D tutorial by, which I highly recommend. I thought a good way to get some extra practice and experience before starting on my own game would be to take the tutorial project, and add touch controls so that it can be played on an Android or iOS device.

Right now, I’ve got the game using GUI.Box to render visible buttons, however these are just something for the player to see. The actual controls are handled by simple rectangles, then using the Rect.Contains method. People have said that with rectangles, Unity uses a bottom-left to top-right coordinates system, rather than top-left to bottom-right. This would be fine, but I can’t get my rectangles to move in the y axis at all…

Here’s the code:

public Rect thrustButton = new Rect(0, 0, 200, 200);
public Rect leftButton = new Rect(Screen.width - 400, 0, 200, 200);
public Rect rightButton = new Rect(Screen.width - 200, 0, 200, 200);

if (Input.touchCount > 0) {
var touchPos = Input.GetTouch (0).position;

if (thrustButton.Contains (touchPos))
moving.y = 1;

if (leftButton.Contains(touchPos))
moving.x = -1;

if (rightButton.Contains(touchPos))
moving.x = 1;

Now, this works, except that I absolutely CANNOT get the rectangles to draw in the right spot. They’re supposed to be along the bottom of the screen, with the thrustButton on the left, and the leftButton and rightButton side by side on the right. There in the correct spot in the x axis, but always at the very top of the screen. I found this by trial and error (dragging my finger around the screen until it hit a button). Now, no matter what I change the y coordinate value to, it never ever moves. 0 should be correct, if it’s moving up from the bottom and I want it to draw at the bottom, but it still draws at the top. I’ve tried changing it to 500, -500, Screen.height, Screen.height - Screen.height, Screen.height + 100, Screen.height - 100. And still, it’s always at the exact same spot at the top of the screen. It’s incredibly frustrating (especially since I have to compile for Android each time to test it), and I’m absolutely at a loss. Any help would be massively appreciated. Thanks.

I only got one response on the forum, to setup a new Vector2(touchPos.x, Screen.height - touchPos.y), tried it, and it made the whole screen work as that button. :confused:

GUI coordinates start in the upper left corner of the screen and are measured in pixels. Screen coordinates (including touch coordinates) start in the lower left corner of the screen and are also measured in pixels. The Rect you use for GUI coordinates is anchored in the upper left corner. So in order to display your buttons at the bottom of the screen you must change something like this:

public Rect thrustButton = new Rect(0, 0, 200, 200);

…to this:

 public Rect thrustButton = new Rect(0, Screen.height - 200, 200, 200);

Note that since the rectangle is anchored at the top, we must subtract the height of the button from Screen.height to position the button at the bottom.

Now for detecting the hit, you must convert the Screen coordinates to GUI coordinates before using Rect.Contains(). So do this to touchPos before calling Rect.Contains:

touchPos.y = Screen.height - touchPos.y;