Reputation: 4729
I have been wracking my brain and using every Google search phrase I can think of and have yet to find a solution.
I have a Unity app with a 3D scene and UI elements that float over it. There is one UI element that is an image of a protractor. That image needs to be drug around the scene, rotated, and scaled. All of that works, the only catch is that is doesn't matter if the user touches the protractor or somewhere else, the protractor always reacts.
I started by looking for something along the lines of Swift's someCGRect.contains(someCGPoint)
so that I could ignore anything that isn't in the bounds of the protractor. Image doesn't seem to have such a property so I did lots of other searching.
I finally found this video; https://www.youtube.com/watch?v=sXc8baUK3iY that has basically what I'm looking for… Except is doesn't work.
The video uses a collider and rigid body and then in code checks to see if the collider overlaps the touch point. Looks like exactly what I need. Unfortunately, no touches ever overlap with the collider no matter where they are. After some Debug.Log
I found that the extents of the collider are reported as (0, 0, 0)
. This is clearly why none of the touches overlap with it, but I can't figure out how to make the extents be anything other than 0.
Here is the info from the colliders and rigid body attached to the image:
There is a button that turns the protractor on and off by use of the following code:
public void toggle() {
this.enabled = !this.enabled;
this.gameObject.SetActive(this.enabled);
}
The protractor starts life visible but Start()
calls toggle()
straight away so the user sees it as starting out off.
This is the code that performs the test to see if the touches should be responded to:
void checkTouches() {
if (Input.touchCount <= 0) {
return;
}
bool oneTouchIn = false;
Collider2D collider = GetComponent<Collider2D>();
Debug.Log("🔵 The bounds of the collider are: " + collider.bounds);
// The above always logs the extents as (0,0,0).
foreach (Touch touch in Input.touches) {
Vector2 touchPos = Camera.main.ScreenToWorldPoint(touch.position);
if(collider.OverlapPoint(touchPos)) {
// Since the extents are all 0 we never find any overlaps
oneTouchIn = true;
break;
}
}
if (!oneTouchIn) {
return; // Always ends up here
}
// We must have at least one touch that is in our bounds.
// Do stuff with the touch(es) here…
}
I've been doing iOS development with Objective-C since the SDK was released and with Swift since it come out but I'm very new to Unity. I'm sure the issue is me missing something silly, but I can't find it.
Does anyone know what I'm missing to make the current version work or an alternate way of only responding to touches that are in bounds?
Upvotes: 1
Views: 333
Reputation: 90629
Image doesn't seem to have such a property
No the Image
componemt itself doesn't have that ...
But the rect
property of the RectTransform
component each UI GameObject
has.
It is called Contains. So you could do e.g.
RectTransform imgRectTransform = imageObject.GetComponent<RectTransform>();
Vector2 localTouchPosition = imgRectTransform.InverseTransformPoint(Touch.position);
if (imgRectTransform.rect.Contains(localToichPosition)) { ... }
Alternatively you could use the IPointerEnterHandler and IPointerExitHandler Interfaces in a component on the target Image like e.g.
public class DragableHandler : MonkBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public bool IsHover {get; private set; }
//Detect if the Cursor starts to pass over the GameObject
public void OnPointerEnter(PointerEventData pointerEventData)
{
//Output to console the GameObject's name and the following message
Debug.Log("Cursor Entering " + name + " GameObject");
IsHover = true;
}
//Detect when Cursor leaves the GameObject
public void OnPointerExit(PointerEventData pointerEventData)
{
//Output the following message with the GameObject's name
Debug.Log("Cursor Exiting " + name + " GameObject");
IsHover = false;
}
}
and than in your script check it using
if(imageObject.GetComponent<DragableHandler>().IsHover) { ... }
just also make sure that we the EventSystem
you also add Touch Input Module
and check the flag Force Module Active
.
Upvotes: 2