- Home /
Why is OnTriggerEnter2D executing multiple times before I get an OnTriggerExit2D?
So basically I'm working on a 2D game and trying to make it so that when my character is standing in fire he loses 1 HP every 1 second, and when he gets out he stops losing HP. I got everything working by basically connecting this script to the fire...
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.name == "character")
{ InvokeRepeating("HealthChange", 1, 1); }
}
Which calls this function...
void HealthChange ()
{ ScreenInterface.playerhealth += healthamount; }
And is killed by this...
void OnTriggerExit2D (Collider2D other)
{
if (other.gameObject.name == "character")
{ CancelInvoke ("HealthChange"); }
}
My fire, for now, is a single sprite with a simple Box Collider 2D attached to it, and my character is a single sprite with a Polygon Collider 2D and a Rigidbody 2D. No animations or anything yet.
I have been working under the (possibly mistaken?) notion that every OnTriggerEnter2D requires an OnTriggerExit2D before there can be another OnTriggerEnter2D. In other words, one collider can come "in" to another collider, but it can't come "in" again until it goes "out" first. But upon testing I realized that I'm actually getting about 5-10 (it seems to vary) OnTriggerEnter2D executions right away when I come in to the collider before I get a single OnTriggerExit2D when moving out. This is, of course, making my character lose 5-10 times as much health since InvokeRepeating gets executed 5-10 times.
Obviously my question is... what am I doing wrong? Although another question related to that might be... am I on the right track, or should I be doing something completely different to make this fire thing work? I looked at OnTriggerStay2D but I wasn't sure how to make that work with the 1 second period, not to mention that I suspect that if OnTriggerEnter2D is getting executed many times, OnTriggerStay2D might end up messy like that as well. I guess there might be some issue with my colliders themselves?
PS. I literally just started game development with Unity 4.3 and my only real programming background is web programming so a lot of this is very, very new stuff to me...
Yes OnTriggerEnter/Exit() fire once. Also better using tags ins$$anonymous$$d of names. Can't see the problem though
$$anonymous$$y issue was that when I moved into the fire "OnTriggerEnter2D" executed 5-10 times even though I just moved in and haven't moved out (gotten a single "OnTriggerExit2D") yet. They all seemed to be running parallel-ish to each other too? so ins$$anonymous$$d of 1 health being subtracted every second 5-10 were subtracted in bursts. I want something that will only execute once upon moving in and then stop executing when moving out.
I've made some progress, so that is no longer the case, but there is still an issue...
I tried using a bool to make sure that the stuff in OnTriggerEnter2D won't execute multiple times without an OnTriggerExit2D in between which seems to have helped a little... so now my character loses 3 health instantly and then it appears to work correctly after that. I don't think it is running my InvokeRepeating multiple times anymore because my "enter count" and "exit count" are adding up now and it is only right at the start that it does that -3 burst but... I still can't explain why it does that at the start.
Here is the whole file being called by the fire object, if that helps...
using UnityEngine;
using System.Collections;
public class Collectible : $$anonymous$$onoBehaviour
{
public int healthamount;
public bool itemdestroy;
public bool onetime;
public bool iscollision = false;
public int entercount = 0;
public int exitcount = 0;
void HealthChange ()
{
Debug.Log ("Health amount: " + healthamount);
Debug.Log ("Inside Health Change!");
ScreenInterface.playerhealth += healthamount;
}
void OnTriggerEnter2D (Collider2D other)
{
Debug.Log ("Enter collision!");
Debug.Log (iscollision);
if (!iscollision)
{
iscollision = true;
if (other.gameObject.name == "character")
{
//ScreenInterface.playerhealth += healthamount;
Debug.Log ("Collision with player!");
if (itemdestroy)
{ Destroy (gameObject); }
if (onetime)
{ HealthChange (); }
else
{ InvokeRepeating ("HealthChange", 0, 1); }
entercount += 1;
Debug.Log ("Enter count: " + entercount);
}
}
}
void OnTriggerExit2D (Collider2D other)
{
iscollision = false;
if (other.gameObject.name == "character")
{
exitcount += 1;
Debug.Log ("Exit count: " + exitcount);
CancelInvoke ("HealthChange");
}
}
}
Hmm) Could you upload your project? I'm curious what's happening
How would I go about doing that? I'm a bit of a n00b here, not really sure how to upload an entire project.
put your assets folder into archive and upload it somewhere) mediafire for example Or you can make unitypackage Assets-> ExportPackage
Answer by prof · Nov 21, 2013 at 05:59 AM
Problem in InvokeRepeating. Apparantly, you can't set 0 as start time. change it to 0.1f for example and it will work properly.
P.S. Your code is a MESS. Seriously, do not show it to anybody... ever.
Oooh that totally worked, thanks! I have no idea WHY it worked, but it worked. And yeah, I know my code is messy, I've mostly just been trying to figure out what the F I'm doing and haven't been too concerned about keeping it clean. But I plan to clean everything up before I start any serious development. In fact I'll probably just start from scratch.
No problem, by the way http://forum.unity3d.com/threads/24154-Inheriting-functions-like-Start-or-Update
Your answer
Follow this Question
Related Questions
Weird OnTriggerEnter / Exit behavior 1 Answer
Help with OnTriggerExit never being called? 1 Answer
On trigger exit not working 2 Answers