Alternate for OnTriggerExit???

As many of us already discussed OnTriggerExit is being a son of a bitch by not working properly. I guess its a bug or whatever.Anyways, i have an object(“GameObject”) that spawns lots of static cubes. The cubes have a Tag(“Block”). I put a script on “GameObject”…

var coll : boolean = false;

function OnTriggerEnter(other : Collider)

{

if(other.gameObject.CompareTag("Block"))

{

coll = true;

}

}

function OnTriggerExit(other : Collider)

{

if(other.gameObject.CompareTag("Block"))

{

coll = false;

}

}

OnTriggerEnter works fine. But OnTriggerExit dosent. Is there another way i can do this? Sincerly, Kibbles (-.-)

I suspect that your problem has a different cause: since there are several Block objects around, the trigger Enter and Exit events may get fooled: coll becomes true when any Block enters the trigger, and turns to false when any Block exits - no matter how many Block objects are inside the trigger.

Anyway, you could try something like @DaveA suggested:

var coll = false;
var stay = false;

function OnTriggerStay(other: Collider){
    if (other.CompareTag("Block")){
        stay = true; // set stay if any Block inside the trigger
    }
}

function FixedUpdate(){
    if (stay){ // if any Block inside the trigger...
        coll = true;  // set coll
        stay = false; // and prepare flag for next cycle
    } else {   // if stay not set, no Blocks are inside
        coll = false; // thus clear coll
    }
}

This code sets coll when the Block enters the trigger, and clears it when the Block exits. You must use FixedUpdate to control coll because Trigger events occur in the physics cycle. Use Update to do the rest - including to read coll.

I suppose that coll will become false only when no more Blocks are inside the trigger (I didn’t test this).

EDITED: Triggers are good for detecting when things enter and exit, but if something is created or teleported inside the trigger, nothing happens.

There are several ways to detect if there are objects in a given volume, but I think the easiest is to use Physics.OverlapSphere: you inform radius and position of an imaginary sphere, and the function returns all colliders that touch or are inside it. Since other objects - like the ground or scene details - may be also detected, you must tag each cube you create with a specific word - “Cube”, for instance - so you can check if any “Cube” is returned by OverlapSphere and ignore the rest.

Place the code below in your cube creator script, and call the function SpawnCube when you want to create a new cube. The routine checks if some object tagged “Cube” intersects the sphere, and aborts if any one found, otherwise it instantiates the object referenced by prefab in the current position.

var prefab: GameObject; // drag your cube prefab here
var radius: float = 2;  // cube-free sphere radius

function SpawnCube(){
    var cols = Physics.OverlapSphere(transform.position, radius);
    for (var col: Collider in cols){
        if (col.tag == "Cube"){ // if any cube intersects sphere... 
            return;             // abort instantiation
        }
    }
    // no Cube found, instantiate new cube:
    var cube = Instantiate(prefab, transform.position, transform.rotation);
    cube.tag = "Cube"; // and tag the new cube as "Cube"
}

You could monitor OnTriggerStay from Update. See when it is/was/is-no-longer ‘staying’

I guess you just forgot to add a rigidbody to your cubes? It can be kinematic but you need one on the object that is moving or the collision system won’t work. What Unity version do you use? One of the recent releases have a fix for OnTriggerExit when you destroy an object.

An alternate method would be to have OnTriggerStay set a timer to 0.1 seconds (or so), while having an Update function constantly subtracting Time.deltaTime from that timer. If OnTriggerStay can no longer set that timer to 0.1 seconds, then Update() will win, and get that timer to 0.0

Once the timer is at 0.0 or less, then Update() can call OnTriggerExit() manually.

I had issues with OnTriggerEnter/Exit being inconsistent, and I was trying to use the triggers as zones for my players. I couldn’t use the approach Aldo Naletto suggested because that would limit me to spherical zones, and my trigger objects can be all kinds of shapes (mostly rectangular).

In the end the solution I came up with was to put all the triggers in a layer called “Zone” and then in Update for the player object do a 1 unit OverlapSphere with the Zone layer. You could optimise this by then adding a delay before it checks again.

If you wanted you could probably even get this to call “OnZoneEnter”, “OnZoneStay” (if you do the check every frame) and “OnZoneExit” in the trigger object whenever its zone changes, and now you’ve got exactly the behaviour triggers were supposed to have in the first place :slight_smile:

In case anyone’s curious, in places where the player was touching two zones I used GetClosestPointOnBounds to determine which zone edge is closest to the centre of the player.