Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

OnTriggerEnter and Exit too slow: what to do?

Discussion in 'Scripting' started by Thomas12, Dec 25, 2014.

  1. Thomas12

    Thomas12

    Joined:
    Dec 24, 2014
    Posts:
    36
    Hello everyone,

    I have some issues with OnTriggerEnter and OnTriggerExit.

    The situation is the following: the player is able to place objects on the ground, the object to place following the mouse along the ground. Of course, if another object already occupies the spot where the player wants to place a new object, it should not work. To detect this, I use OnTriggerEnter and OntriggerExit. The object the player tries to place turns red as soon as it enters the collider of another object. It goes back to normal as soon as the object exits the collider of the other object. When the object the player wants to place is red, if the player clicks to place it, the placement of the object is denied. Otherwise the object is placed where the player clicked.

    Everything works fine... except if the player goes too fast. If for instance he moves the mouse fast enough and clicks, it can happen that the object to place did not had the time to turn red as it should, and it's therefore placed on another object, which is not allowed... Also, it can happen that the object to place, after turning red, does not go back to white as it should. Again, if the player move the mouse fast enough, OnTriggerExit is never called and the object to place is stuck in the red color.

    I'm new to unity and I'm quite surprised by these issues. I researched if it was possible to manually detect collisions, all I found was the possibility to grow a sphere around the object to place to detect collisions => not a very good option for my case as most of my objects are not spherical at all.

    Any suggestion would be very much appreciated.
     
  2. toreau

    toreau

    Joined:
    Feb 8, 2014
    Posts:
    204
    I've never experienced these being "too fast", but I seldom use OnTrigger*. I wonder, though, why you use OnTrigger*, as you are trying to detect collision for which OnCollision* is a better choice?
     
  3. Thomas12

    Thomas12

    Joined:
    Dec 24, 2014
    Posts:
    36
    I'm sorry I used the word collision in the post: all I want to detect is if two objects overlap or not, not really if there is a collision.
     
  4. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    it's not too slow. What's happening is your object moves too quickly so it's coordinates might never overlap since it moved too far since the previous time it moved.
     
    Mycroft likes this.
  5. Thomas12

    Thomas12

    Joined:
    Dec 24, 2014
    Posts:
    36
    This is so weird, because the mouse click, on the other end, does correspond to coordinates where trigger events should have been called.

    In any case, I solved the problem by adding a small script to any gameobject just placed: the script will attempt to detect a OnTriggerStay event during 0.075seconds. If after that time, nothing is detected, then it is concluded the object was placed somewhere were it was allowed to be placed, and the script is destroyed. Otherwise the gameobject just placed is destroyed. Here is the code for anyone interested:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class RedOnContactLate : MonoBehaviour {  
    5.  
    6.     bool detected=false;
    7.     float currentTime=0F;
    8.  
    9.     void Update() {
    10.     if (detected) {
    11.             Destroy (gameObject);
    12.     } else {
    13.             currentTime+=Time.deltaTime;
    14.     }
    15.     if (currentTime > 0.075F) {
    16.             Destroy (gameObject.GetComponent<RedOnContactLate>());
    17.     }
    18.  
    19.  
    20.  
    21.     }
    22.  
    23.    
    24.     void OnTriggerStay(Collider other) {
    25.         if (!detected) {
    26.             detected=true;
    27.         }
    28.     }
    29. }
     
  6. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Looks like a bunch of horrid hacks.

    Are you aware that when moving a collider, it is updated within the FixedUpdate() loop and not Update() and therefore subject to how often FixedUpdate updates in time manager? You should read all the physics related docs.
     
    Mycroft and toreau like this.
  7. xantyleonhart

    xantyleonhart

    Joined:
    Aug 9, 2015
    Posts:
    1
    Wow, thanks, i was having a similar problem, but you just gave me a great idea: Each frame i'll launch a raycast from the position the object was in the previous frame to the position in the current frame. That way i can detect anything the object could have collided with in its trajectory.
     
  8. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    If one of the objects in question has a rigidbody, you could also consider changing your collision detection mode to Continuous or Continuous Dynamic for exactly that kind of "skipped over" detection. That said, a raycast from the previous to current position isn't a bad hack, though it's still completely possible to "skip over" the raycast area. You could also maybe have a second identical collider on an empty child object that trails 1 frame or 1/30th of a second behind the parent object or something, as that would be a "compound collider" and trigger the same functions as the parent collider would.
     
  9. CesarCanto

    CesarCanto

    Joined:
    Dec 28, 2016
    Posts:
    2
    I know this is quite old, but just for the sake of the next people to find this thread. I had the same issue and I solved it by using the following:

    Code (CSharp):
    1.     Rigidbody2D rb;
    2.     rb.WakeUp();
    I use enable and disable for the attack colliders of my player and the enemies, and sometimes the OnTriggerEnter or OnTriggerStay activate too slow for me.

    Waking up my RigidBody after enabling my collider solved that problem for me (Y)
     
    Stexe likes this.