NOTE: See bottom of the question as I have managed to use a workaround which works to press the two buttons at once on Android (thanks to Douglas Potestas help)
I've struggled with this in the past and got it working. But its been a long time since I have used raycasts and I have mostly forgotten. Quick summary before people tell me to use OnPointerEnter
etc is that on all of my Android games using pointer events you cannot press the two buttons (eg. imaging a NES gamepad pressing A and B with the same thumb like when you play Mario or something). You cannot slide the thumb to press both it only registers the first button hit, and this is not adequate for most of my game ideas.
Basically, I want to check if the thumb is over any amount of buttons at every frame of the game loop.
So I have this very basic code which I hoped would work, but the hit only returns anything if it hits a physical game object such as Cube or Capsule.
I want it to return if it hits a UI Image/Panel/Button (it matters not which one really).
I've tried adding 2D box collider and a 3D cube collider both as trigger and not trigger and made sure they're big enough. I've tagged the image/button. I've checked the "Raycast Target" box. Here is update loop of my OnScreenControlManager.cs
void Update () {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
float rayLength = Mathf.Infinity;
if (Physics.Raycast(ray, out hit, rayLength))
{
Debug.Log("hit coll = " + hit.collider.tag);
if (hit.collider.tag == "LeftButton")
{
Debug.Log("hit coll = " + hit.collider.tag);
}
}
}
I definitely had this working about a year ago in Unity 5. I'm now using Unity 2017, hope that isn't anything to do with it.
Have also tried Physics2d.Raycast:
private void Update()
{
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if (hit.collider != null)
{
Debug.Log("Target tag: " + hit.collider.tag);
}
}
Solution which works using new Rects and the Overlaps method. (Note , you cannot use this if the buttons are small and close together
public class OnScreenController : MonoBehaviour
{
Rect touchRect;
public float touchRectExtents;
Bounds buttonLeftBounds;
public GameObject buttonLeft;
Rect buttonLeftRect;
Bounds buttonABounds;
public GameObject buttonA;
Rect buttonARect;
Bounds buttonBBounds;
public GameObject buttonB;
Rect buttonBRect;
public Text aPressed, bPressed;
private void Start()
{
buttonLeftBounds = buttonLeft.GetComponent<Collider2D>().bounds;
buttonABounds = buttonA.GetComponent<Collider2D>().bounds;
buttonBBounds = buttonB.GetComponent<Collider2D>().bounds;
}
private void Update()
{
touchRect = new Rect(Input.mousePosition.x - touchRectExtents, Input.mousePosition.y - touchRectExtents, touchRectExtents * 2, touchRectExtents * 2);
buttonLeftRect = new Rect(buttonLeftBounds.center.x - buttonLeftBounds.extents.x, buttonLeftBounds.center.y + buttonLeftBounds.extents.y, buttonLeftBounds.size.x, buttonLeftBounds.size.y);
buttonARect = new Rect(buttonABounds.center.x - buttonABounds.extents.x, buttonABounds.center.y + buttonABounds.extents.y, buttonABounds.size.x, buttonABounds.size.y);
buttonBRect = new Rect(buttonBBounds.center.x - buttonBBounds.extents.x, buttonBBounds.center.y + buttonBBounds.extents.y, buttonBBounds.size.x, buttonBBounds.size.y);
if (touchRect.Overlaps(buttonLeftRect))
{
Debug.Log(" LEFT PRESSED");
}
if (touchRect.Overlaps(buttonARect))
{
aPressed.text = "A PRESSED";
}
else
{
aPressed.text = "A NOT PRESSED";
}
if (touchRect.Overlaps(buttonBRect))
{
bPressed.text = "B PRESSED";
}
else
{
bPressed.text = "B NOT PRESSED";
}
}
}
EDIT: Still doesn't work :[ although I can now press the two buttons at once with the same touch, I need to add a way to check for other touches. For example if I am using the D-Pad with left thumb, this code doesn't even detect the hit on the buttons because Mouse.inputPosition
is still over at the D-Pad.