Clicking a UI Panel

Hey there,

I am like an absolute beginner, so please bear with me, if this question is really stupid. But I can’t figure it out by myself.

I am (trying to) developing a 2D Mobile Game. The catch is that the way you move your character constantly changes from level to level. To make that possible I want to create areas and when you click them, a certain thing happens (like player moving to the left). I could obviously just use buttons to do so, but the way you interact with these areas to get them to function also changes (it could be click, click and hold, click repeatedly, drag/swipe, you get the idea…). Also the area changes position and size in the levels (sometimes the area to move left is on the left side, sometimes it’s on the right side, sometimes it’s the whole left side, sometimes it’s just a tiny space, whatever).

Now, the way I wanted to achieve that is that I created two panels on a canvas (because I want the areas to scale with the screen) and get their positions when the level is started like so:

RectTransform lefti = leftMovement.GetComponent<RectTransform>();

leftleft = leftMovement.transform.position.x;
leftright = leftMovement.transform.position.x + lefti.rect.width;
leftbottom = leftMovement.transform.position.y;
lefttop = leftMovement.transform.position.y + lefti.rect.height;

(I have never inserted code into a forum before, idk if thats how you do it lol)

And then I check whenever the screen is clicked, if the coordinates are within this area like so:

if (screenPos.x > leftleft && screenPos.x < leftright && screenPos.y > leftbottom && screenPos.y < lefttop)
{

    playerScript.moveLeft();
} 

Technically this works, but also it doesn’t, and here is where I need your help. The values I get back from the panels do not match the real screen values. This is what I receive from the left panel that covers the full left side of the screen with a resolution of 2160x1080:

leftleft: 340 leftright: 740 leftbottom: 1080 lefttop: 2680
UnityEngine.Debug:Log (object)
MMTap:Awake () (at Assets/Code/MoveManager/MMTap.cs:69)

in this case, leftleft and leftbottom should be 0, but they are not. I tried to fix it, by just taking away 340 and 1080 to all the variables and it works when it’s static, but as soon as I change the size of the panels (which is the whole reason I am doing this) the numbers don’t match again. Same thing applies when I change resolution.

I originally worked with

leftleft = Camera.main.WorldToScreenPoint(leftMovement.transform.position).x;

but that gave me real funky values that didn’t match the feedback I got from the InputAction at all.

Please help me ._____. (or let me know that the way I am approaching this problem is stupid in itself and I should just do it differently all together)
thx

Fiddling with RectTransforms numerically:

Supplying positions to anything in UI space via code is almost always an exercise in futility. This is due to the inscrutable nature of the RectTransform object and how it interacts with other RectTransforms, anchors, and the CanvasScaler as well as the canvas mode.

Instead of supplying positions, either use a flavor of the Layout family of components to position things automatically, or else use invisible pre-existing Transforms in your UI as positional inputs and then compute positions from those pre-authored corner positions.

By this I mean compute your positions as Lerp()-ed from other RectTransforms properly anchored in the corners of your UI in order to have the highest chances of success.

Here’s why RectTransform stuff is hard: it takes 15+ lines of code just to move the anchors to the corners:

Now if you REALLY want to mess with computing your own UI positions, by all means go right ahead. But just know that there is almost ZERO support out there, as well as extremely few examples. Almost nobody does things this way, so be prepared to do it all alone and figure it out yourself.

It is on you to test on EVERY possible combination of aspect ratio and resolution to verify your positioning and anchoring. Expect it to fail if you do not do this testing.

Thanks for your answer. I am trying to understand it. I think you are telling me, that I shouldn’t try to position a UI element via code. Did I get that right?
Because this is not what I am trying to do. I have placed a UI panel on the screen (not via code), and I want to know when the screen is being touched if the touch is happening on the area of said UI panel. And if so, I want to move my player.
I am basically trying to build a button. Just that the functionality of a button as it is doesn’t give me enough freedom to process different types of input.

Button is purpose built to do one thing: report that a finger went down on it and then was soon thereafter lifted off of it. That’s it.

It sounds like you have a button of some slightly-larger size and you want touches in different parts of it to do different things… is that what you want? Eg, you touch left side, move left, touch right side, move right?

That is not generally handled by a button although I suppose you could do the math. I would not and instead just use a purpose-built thing, usually called a virtual joystick, or virtual analog button, or touch joystick.

There’s a ton of tutorials out there for these things, all constructed in many different ways. I made my own touchscreen controls and have a bunch of example games using them… you’re welcome to look at what I did in my Proximity Buttons project.

I happen to call my virtual analog Button a VAButton in here… look for full game examples inside to show off how to set it up and respond to it:

proximity_buttons is presently hosted at these locations:

Thank you so much for all the effort trying to help me with my problem!

I think raycasting will help me achieve what I want - see if I touched (or dragged, or touched multiple times, etc) the screen where the 2D area is, to trigger my player movement.
I haven’t managed yet to get it to work, but I think I am now trying it the correct way.

I finally got it, after almost 4 days of struggeling. I cannot believe it was so easy in the end.
The solution was to transform the screen point into the local rectangle space, instead of trying to do it the other way around:

Vector2 localPoint;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
    leftMovement, touchPositionAction.ReadValue<Vector2>(), Camera.main, out localPoint))
{
    // Check if the local point is inside the rectangle
    if (leftMovement.rect.Contains(localPoint))
    {
        Debug.Log("UI Element Clicked: " + leftMovement.name);
    }
}

That’s it. That’s all I needed. Wow.