I track a button click that other objects fly through with OnPointerDown, OnPointerUp, OnTriggerStay, and OnTriggerExit. The idea is to destroy the object when passing through the button. Below is the code I am trying to use:
public void OnPointerDown(PointerEventData eventData)
{
_isMouseDown = true;
if (!_isTriggered)
{
Debug.Log("Fail!");
}
}
public void OnPointerUp(PointerEventData eventData)
{
_isMouseDown = false;
}
private void OnTriggerStay(Collider collision)
{
_isTriggered = true;
if (_isMouseDown)
{
Destroy(collision.transform.gameObject);
_isTriggered = false;
}
}
private void OnTriggerExit(Collider collision)
{
_isTriggered = false;
}
I am getting two problems. The first is that when I press and hold the button, objects are destroyed as soon as they hit the trigger. The second problem is that if I press the button right before the object flew up to the trigger, two conditions are triggered at once: Debug.Log with a fail and destroy the object in OnTriggerStay, and the goal is to track only fail clicks and clicks when the trigger fires.
I assume that I need to somehow track the duration of the button click and then change from mouse down to false so that the trigger does not have time to fire. Would it be correct to do this, for example, through a coroutine?
Instead of using OnTriggerStay
at all rather only go for the two single-time events OnTriggerEnter
and OnTriggerExit
and rather store the object you are currently colliding with.
Then handle the button event directly:
private GameObject currentColliding;
public void OnPointerDown(PointerEventData eventData)
{
if(currentColliding != null)
{
Destroy(currentColliding);
currentColliding = null;
Debug.Log("Destroyed!");
}
else
{
Debug.Log("Failed!");
}
}
public void OnPointerUp(PointerEventData eventData)
{
// doing nothing but afaik required by the event system for OnPointerDown to work (documentation isn't so clear about that)
}
private void OnTriggerEnter(Collider collider)
{
currentColliding = collider.transform.gameObject;
}
private void OnTriggerExit(Collider collider)
{
currentColliding = null;
}
if you rather need to be able to handle various objects simply convert it to a collection and do e.g.
private readonly HashSet<GameObject> currentColliding = new ();
public void OnPointerDown(PointerEventData eventData)
{
if(currentColliding.Count > 0)
{
foreach(var obj in currentColliding)
{
Destroy(obj);
}
currentColliding.Clear();
Debug.Log("Destroyed!");
}
else
{
Debug.Log("Failed!");
}
}
public void OnPointerUp(PointerEventData eventData)
{
// doing nothing but afaik required by the event system for OnPointerDown to work (documentation isn't so clear about that)
}
private void OnTriggerEnter(Collider collider)
{
currentColliding.Add(collider.gameObject);
}
private void OnTriggerExit(Collider collider)
{
currentColliding.Remove(collider.gameObject)
}