What I try to achieve: Toothbrush should show up wherever the user clicks inside BoxCollider
A
, including space inside BoxCollider
B
What is the intended functionality here? I'm suspecting that you want the toothbrush to display anytime a user clicks within the mouth space?
If so, then one fun way to fix this would be to adjust the ordering of the 'B' objects to be above the 'A' object in the Hierarchy so that they overlay the A collision area. This in turn will allow their interaction to block the interaction of the area defined underneath the collision area define by each 'B' collider.
What we're doing with this methodology is forcing the OnPointerDown event to occur with the 'B' collider before it has a chance to collide with the 'A' collider.
Let me know if that makes sense and feel free to ask follow up questions about the method.
Still not sure if your case is what I think it is, but here's a video of the method i mentioned: Demo Video
One of the good and advantages of the EventSystem is that events don't go through GameObjects. The first one that is hit is returned. Although, it looks like you don't want that. It complicated to make EventSystem return multiple GameObjects,
There two solutions for you:
1.Get ride of EventSystem
(OnPointerDown
and IPointerDownHandler
) and use the old school raycast system.
Physics2D.RaycastAll
and Physics2D.RaycastNonAlloc
can do this. This example will use RaycastNonAlloc
for performance reasons. It's very easy.
Attach to only one GameObject(empty GameObject):
public class HitAll : MonoBehaviour
{
//Detect up to 100 Objects
const int raycastAmount = 100;
RaycastHit2D[] result = new RaycastHit2D[raycastAmount];
void Update()
{
#if UNITY_IOS || UNITY_ANDROID
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
checkRaycast(Input.GetTouch(0).position);
}
#else
if (Input.GetMouseButtonDown(0))
{
checkRaycast(Input.mousePosition);
}
#endif
}
void checkRaycast(Vector2 mousePos)
{
Vector3 origin = Camera.main.ScreenToWorldPoint(mousePos);
int hitCount = Physics2D.RaycastNonAlloc(origin, Vector2.zero, result, 200);
Debug.Log(hitCount);
for (int i = 0; i < hitCount; i++)
{
Debug.Log("Hit: " + result[i].collider.gameObject.name);
}
}
}
2.Continue using EventSystem
but rethrow the event.
First, you throw raycast with EventSystem.current.RaycastAll
then you manually invoke the event with ExecuteEvents.Execute
.
Attach to all the GameObject with 2D Collider and make sure that Physics2DRaycaster
is attached to the camera:
public class ThroughEventScript : MonoBehaviour, IPointerDownHandler
{
public void OnPointerDown(PointerEventData eventData)
{
rethrowRaycast(eventData, eventData.pointerCurrentRaycast.gameObject);
//DO STUFF WITH THE OBJECT HIT BELOW
Debug.Log("Hit: " + eventData.pointerCurrentRaycast.gameObject.name);
}
void rethrowRaycast(PointerEventData eventData, GameObject excludeGameObject)
{
PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
pointerEventData.position = eventData.pressPosition;
//pointerEventData.position = eventData.position;}
//Where to store Raycast Result
List<RaycastResult> raycastResult = new List<RaycastResult>();
//Rethrow the raycast to include everything regardless of their Z position
EventSystem.current.RaycastAll(pointerEventData, raycastResult);
//Debug.Log("Other GameObject hit");
for (int i = 0; i < raycastResult.Count; i++)
{
//Debug.Log(raycastResult[i].gameObject.name);
//Don't Rethrow Raycayst for the first GameObject that is hit
if (excludeGameObject != null && raycastResult[i].gameObject != excludeGameObject)
{
//Re-simulate OnPointerDown on every Object hit
simulateCallbackFunction(raycastResult[i].gameObject);
}
}
}
//This causes functions such as OnPointerDown to be called again
void simulateCallbackFunction(GameObject target)
{
PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
//pointerEventData.ra
RaycastResult res = new RaycastResult();
res.gameObject = target;
pointerEventData.pointerCurrentRaycast = res;
ExecuteEvents.Execute(target, pointerEventData, ExecuteEvents.pointerDownHandler);
}
}