Search Unity

Reenabling disabled gameobject does not call ontriggerenter.

Discussion in 'Physics' started by Yukken, Oct 23, 2019.

  1. Yukken

    Yukken

    Joined:
    Jul 12, 2015
    Posts:
    93
    I am trying to implement hitboxes by toggling trigger colliders on and off. The trigger colliders are attached to a parent rigidbody. This is the code I'm using to detect enemy hitboxes inside the collider.
    Code (CSharp):
    1. public abstract class TriggerTracker2D<T> : MonoBehaviour
    2. {
    3.     public List<T> trackedList = new List<T>();
    4.  
    5.     public Collider2D col;
    6.  
    7.     private void OnEnable()
    8.     {
    9.         clear();
    10.     }
    11.  
    12.     private void OnDisable()
    13.     {
    14.         clear();
    15.     }
    16.  
    17.     public void clear()
    18.     {
    19.         trackedList.Clear();
    20.     }
    21.  
    22.     public abstract void onTrackerAdd(T newlyTrackedObject);
    23.     public abstract void onTrackerRemove(T newlyTrackedObject);
    24.  
    25.     private void OnTriggerEnter2D(Collider2D collision)
    26.     {
    27.         Debug.Log(gameObject.name + " collides with " + collision.gameObject.name);
    28.         T trackedComponent = collision.GetComponent<T>();
    29.         if (trackedComponent != null)
    30.         {
    31.             if (!trackedList.Contains(trackedComponent))
    32.             {
    33.                 Debug.Log(gameObject.name + " to track" + collision.gameObject.name);
    34.                 trackedList.Add(trackedComponent);
    35.                 onTrackerAdd(trackedComponent);
    36.             }
    37.         }
    38.     }
    39.  
    40.  
    41.     private void OnTriggerExit2D(Collider2D collision)
    42.     {
    43.         Debug.Log(gameObject.name + " stops colliding with " + collision.gameObject.name);
    44.         T trackedComponent = collision.GetComponent<T>();
    45.         if (trackedComponent != null)
    46.         {
    47.             Debug.Log(gameObject.name + " stops tracking " + collision.gameObject.name);
    48.             trackedList.Remove(trackedComponent);
    49.             onTrackerRemove(trackedComponent);
    50.         }
    51.     }
    52. }
    Code (CSharp):
    1. public class Hitbox: TriggerTracker2D<Damagable>
    2. {
    3.  
    4.     public DamageInfo damagePerHit = new DamageInfo();
    5.  
    6.     public override void onTrackerAdd(Damagable newlyTrackedObject)
    7.     {
    8.         newlyTrackedObject.takeDamage(damagePerHit);
    9.     }
    10.  
    11.     public override void onTrackerRemove(Damagable newlyTrackedObject)
    12.     {
    13.      }
    14. }
    15.  
    Basically, the hitbox is derived class that hooks on to the onTrackeradd() calls and deals damaged to the object. The abstract class takes care of checking the components.

    I control this script by enabling the gameobject the hitbox(and the corresponding trigger collider) is attached to when I need to start damaging and disable the gameobject when I need to stop.

    The first time I toggle the gameobject on and off, it calls ontriggerenter and exit events properly. BUT every time I try to toggle the hitbox gameobject afterwards, the ontrigger events are NOT called unless I move the character.

    AFAIK ontriggerenter and exit calls should be called every time when a gameobject is turned on/off. So I'm not sure why this is not working. I've used a similar method previously to implement hitboxes and it worked.

    If it matters,I am using rb.moveposition to move my player and it has a kinematic rb attatched. The hitbox gameobject is a child of the player gameobject.
     
    Kiremoe likes this.
  2. Kitsuba

    Kitsuba

    Joined:
    Mar 5, 2015
    Posts:
    17
    I think it's a unity bug. Moving the GameObject probably resets some internal state which allows the the enter/exit functions to be called again. However disabling/enabling gameobjects or scripts does not.

    I'm also hitting this problem and havent found an acceptable solution besides using OnTriggerStay2D and managing the objects that enter/exit manually. Have you come up with a better solution since the creation of this thread?
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,498
    No bug that I know of. If you have a simple reproduction case then please report a bug otherwise nobody knows about it.

    Feel free to post the case number here too.
     
  4. kopeur13

    kopeur13

    Joined:
    Mar 28, 2023
    Posts:
    1
    I have the exact same problem !
    I have an object with trigger area, that is disable. When the attack button is pressed the object is enabled then the OnTriggerEnter2D is triggered, at the end of the animation the object is automatically disabled. When i repress the button i see the object being enabled but the function is not called anymore, till i let my character at the same position.
    At the moment i move (a little bit is enaugth) my character, the function is finally called on attacking...
     
  5. KevinCastejon

    KevinCastejon

    Joined:
    Aug 10, 2021
    Posts:
    109
    Some of my students encountered the same issue and, as far as I can tell, it is related to the Rigidbody falling asleep, looks like a sleeping rb will not detect any trigger. The only solution I found till now is to set the Sleeping Mode to Never Sleep, which is not really optimal...

    Simple reproduction steps:
    - Create new 2D project
    - Create two objects into the scene (let's say a square that will "attack" and a circle that will "be hit") with trigger colliders and dynamic Rigidbodies (set gravity scale to 0)
    - Create and attach the following "Attacker" script to the square.
    - Create and attach the following "Hitbox" script to the circle.
    - Make the two objects colliders overlapping
    - Play the scene and hit the Space key input -> no triggerenter happens.
    - Now try the same but with the circle's rigidbody Sleeping Mode set to Never Sleep --> triggerenter happens

    Attacker script:

    Code (CSharp):
    1. using UnityEngine;
    2. public class Attacker : MonoBehaviour
    3. {
    4.     private Collider2D _collider;
    5.     private void Awake()
    6.     {
    7.         _collider = GetComponent<Collider2D>();
    8.     }
    9.     private void Update()
    10.     {
    11.         if (Input.GetKeyDown(KeyCode.Space))
    12.         {
    13.             _collider.enabled = true;
    14.         }
    15.         if (Input.GetKeyUp(KeyCode.Space))
    16.         {
    17.             _collider.enabled = false;
    18.         }
    19.     }
    20. }
    Hitbox script:
    Code (CSharp):
    1. using UnityEngine;
    2. public class Hitbox : MonoBehaviour
    3. {
    4.     private void OnTriggerEnter2D(Collider2D collision)
    5.     {
    6.         Debug.Log("Enter");
    7.     }
    8. }
     
    Last edited: May 29, 2023
  6. KevinCastejon

    KevinCastejon

    Joined:
    Aug 10, 2021
    Posts:
    109
    @MelvMay can you, or someone from Unity, confirm that this behaviour is intended by design?
     
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,498
    Assuming it's the same issue, this was fixed in 2022.2.16f1 onwards.
     
  8. Benjamin6868

    Benjamin6868

    Joined:
    Sep 1, 2022
    Posts:
    1
    Had the same issue, you just need to wake up the rigidbody before the attack