I’m moving my old UI to the new one, and I got to my DPad controller. So basically, my DPad is a rectangle that is divided in 4 triangles. I used a awesome script provided by the community to do so RayCastMask.
The game is for mobile, which means touch input. On my old UI, I would test if there was a touch on the screen and if it hit any of those triangles. So basically the user could put the finger on the “down button” and the character would move down, and then if he dragged the finger to the “right button” the character would move right. There was no need for the user to lift the finger and touch the button again.
I’m trying to replicate this with the new UI and event system and I’m failing to do so. My first approach was to use the PointerEnter event, but from what I tested this event is like a “MouseHover” event, which means that it doesn’t work on mobile. Then I tried different combinations of events (PointerEnter + Drag), but all with no success.
Is there an easy way of doing this with the current events?
Hrmm, so lets figure out an elegant way to do this…
So the InputModule sends PointerEnter / Exit events when you move between things, and it also sends Press and release when you release things.
So to do this you could set it up like so:
Dpad Controller (has a script with Pointer Press / Release)
—Left button (has an enter / exit script that tells the controller script which one is currently set)
– Right button (same as above)
– Down
– Up
When you press the dbad controller set a bool saying “Hey I’m active now” this will be passed up from any of the buttons so long as they don’t have a press or click handler. Use the enter / exit events on the dpad buttons to control which direction is configured for movement.
DPad Controller, which is a panel with the dpad buttons as children, has:
IPointerDown
IPointerUp
Each Dpad button has:
IPointerEnter
IPointerExit
With the Standalone Input Module it works, I tested both on PC and with Unity Remote. But with the Touch Input Module, or when I run the game on my device it doesn’t work, basically this happens:
I touch the screen on the down button, it detects:
IPointerDown on DPadController
IPointerEnter on Down Button
When I move from Down Button to Right Button it only detects the IPointerExit on the Down Button. If then I return back to Down Button it detects again the IPointerEnter on the Down Button. So from what I understood it only catches the events on the button that received the IPointerDown from the DPadController.
Also I tested using the Standalone Input Module with the “Allow Activation On Mobile Device” on my mobile, and it worked…
Is there any drawback from using the Standalone Input Module on mobile?
Not really, it has a little bit more overhead. There is actually a bug in the touch module at the moment which we havn’t gotten around to looking at. When it’s fixed your issue should go away
Just found another problem, and this one might be a bug:
To make it easier we have a button with 3 handlers, IPointerDown, IPointerUp and IPointerEnter.
I touch the button and release, it receives: PointerDown, PointerEnter, PointerUp. If I touch the button again, it just receives: PointerDown and PointerUp. From what I could test, it only receives the PointerEnter after a PointerExit on the same button, or after a PointerEnter on another button. Is it supposed to work like this?
What’s happening on my game is that I can’t click two times on the same direction, or it won’t move.
No, this was with the Standalone Input Module with the option “Allow Activation On Mobile Device” enabled. With the Touch Input I have the problem that I mentioned before.
Is there something I can call to reset the button status? So that it receives the PointerEnter event again?
Ok so, I managed do make a work around. Basically on the OnPointerDown I also set the direction of movement
I’m not really satisfied with it because I’m still using the Standalone Input on a mobile, but I’ll look into this again after the final version, when hopefully the bug that you mentioned is already fixed.
Here’s the code:
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class DPad : MonoBehaviour, IPointerEnterHandler, IPointerUpHandler, IPointerDownHandler{
public static Vector2 MoveDirection = Vector2.zero;
private static bool _pressed;
public Vector2 Direction;
public void OnPointerEnter(PointerEventData eventData){
if(_pressed) MoveDirection = Direction;
}
public void OnPointerUp(PointerEventData eventData){
_pressed = false;
MoveDirection = Vector2.zero;
}
public void OnPointerDown(PointerEventData eventData){
_pressed = true;
MoveDirection = Direction;
}
}
Then on my character controller script I use the DPad.MoveDirection to move it.