0
\$\begingroup\$

I have two GameObjects tagged "Point", each with a Collider 2D set to Is Trigger.

Inspector configuration of the Point asset

I have another GameObject, "pencil", which also has a Collider2D set to Is Trigger

Inspector configuration of the Pencil asset

I want to move the pencil the first point to the start drawing a line, and then stop drawing when it hits the second point.

My problem is that when the pencil hits a point, it calls OnTriggerExit2D multiple times. How can I only detect first contact with the point?

Pencil script:

private void OnTriggerExit2D(Collider2D collision)
{
    if (!collision.isTrigger)
    {
        if (collision.gameObject.tag == "Point")
        {
            writing = !writing;
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Can you unpack what you mean by "when the pencil hits the points it triggers multiple triggers"? Do you have more than one trigger collider on each point? If so, why? Are the functions of these multiple triggers separable? (eg, could we separate the line-drawing trigger colliders from a second type of trigger collider on a different object/layer?) \$\endgroup\$ – DMGregory Sep 1 '19 at 12:47
  • \$\begingroup\$ I have two points on the screen and I have a pencil that I animate over the points. When the pencil collides with the first point I start the drawing and when it collides with the second point it stops. I have attached some screen shots of the point prefab and the pencil. My problem is when I collide with the first point it triggers multiple times. I only want on trigger event \$\endgroup\$ – Keith Power Sep 1 '19 at 13:00
1
\$\begingroup\$

It looks like your Pecil needs some memory, so it can disregard repeated contacts with the same collider multiple times in a row.

This is related to the idea of "debouncing" a switch - the input to our systems, especially when they come from players or physics - can be messy. The mouse cursor might hover just at the border of a zone for several frames, alternately entering and exiting. So we often need to make our trigger responses "sticky", by remembering we've been activated, and requiring a larger action to deactivate/reset, something called hysteresis.

Collider2D _lastPointTouched;

void OnTriggerExit2D(Collider2D other)
{
    // Disregard collisions with anything but our points.
    if(other.gameObject.CompareTag("Point") == false)
        return;

    // Disregard repeated visits to the same point.
    if(other == _lastPointTouched)
        return;

    // Toggle our writing state, and remember this point for future events.
    writing = !writing;
    _lastPointTouched = other;
}

If you want, you can clear this memory if a condition is met (like the mouse button/touch is released, or the pencil gets far enough away, or if a certain amount of time passes) to allow starting a new line at this point when the player does so deliberately, without accidentally triggering it from a brushing contact.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ thank you, makes sense. Is there a way to save it to a list because the pencil hits the first point latter on but only remembers that last point \$\endgroup\$ – Keith Power Sep 1 '19 at 13:32
  • 1
    \$\begingroup\$ Yes, you can literally use a List. Or, you could delegate the job of remembering to the Point. Then instead of the pencil searching its list of points it's hit to figure out if this one is new, it just asks the point "hey, have we met?" and each point just has to remember "yes" or "no" ;) \$\endgroup\$ – DMGregory Sep 1 '19 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.