OnTriggerEnter2D gets executed repeatedly by each collided object with the same Tag
I'm trying to increase a variable (deaths) when the player collides with a wall (or "enemy"). For save time counting square spaces for the player, I duplicate the wall prefab (I don't know if It's bad, but I don't get bad performance) . The problem is when the player collides between two walls objects, the code gets executed two times, counting two deaths:
function OnTriggerEnter2D(coll : Collider2D){
var respawn = GameObject.Find("respawn");
if (coll.gameObject.tag == "enemy"){
deaths += 1;
transform.position = Vector2(respawn.transform.position.x, respawn.transform.position.y);
}
}
Here is the example:
I don't know if I'm doing something wrong, the player have the "Is Trigger" and the wall not, the wall prefab and the enemy prefab (moving squares) have the "enemy" tag.
Answer by seth_slax · Oct 23, 2015 at 04:36 AM
I'm not entirely sure, but it could be that the player has a child with the same tag. Add in a Debug.Log in your OnTiggerEnter2D function along the lines of:
Debug.Log(coll.transform.name);
To check to see if it is in fact the same gameobject triggering twice. If it is, a workaround I can suggest is to track player death with a boolean and add it to the if statement, ensuring the code doesn't get run twice. Something like this:
var hasDied : boolean; //Declare wherever you want.
function OnTriggerEnter2D(coll : Collider2D){
var respawn = GameObject.Find("respawn");
if (coll.gameObject.tag == "enemy" && !hasDied){
hasDied = true;
deaths += 1;
transform.position = Vector2(respawn.transform.position.x, respawn.transform.position.y);
hasDied = false;
}
}
Also, pro-tip, if you're adding or subtracting '1' to a variable, a shortcut is to use ++ or --. Shorthand for writing += 1 or -= 1.
Answer by Corberius · Oct 23, 2015 at 05:29 AM
It keeps counting two deaths, here is the inspector details of the player and the wall:
And this is the ugly script of the player:
#pragma strict
public var points : int = 0;
public var deaths : int = 0;
var speed : float = 5f;
var dir : String = String.Empty;
var lastDir : String = String.Empty;
var moveType : String = "normal";
var newPos = Vector2.zero;
var state : int = 0;
var isDead : boolean = false;
private var sfx : AudioSource[];
sfx = GetComponents.<AudioSource>();
function Start (){
if (moveType == "slide"){
newPos = Vector2(transform.position.x, transform.position.y);
}
}
function Update (){
direction ();
}
function FixedUpdate (){
movement ();
}
function direction (){
if (state == 0 || state == 2){
if (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A)){
dir = "l";
}
if (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D)){
dir = "r";
}
if (Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.W)){
dir = "u";
}
if (Input.GetKeyDown(KeyCode.DownArrow) || Input.GetKeyDown(KeyCode.S)){
dir = "d";
}
}
if (Input.GetKeyDown(KeyCode.Escape) && state != 1){
lastDir = dir;
dir = "i";
state = 1;
}
}
function movement (){
var damp : float = 0.1f;
var velocity = Vector3.zero;
if (dir != String.Empty || dir != "i"){
if (dir == "l"){
if (moveType == "normal"){
transform.Translate(-speed * Time.deltaTime, 0f, 0f, Space.World);
}
else if (moveType == "slide"){
newPos.x -= speed * Time.deltaTime;
}
transform.eulerAngles = Vector3(0f, 0f, 180f);
}
if (dir == "r"){
if (moveType == "normal"){
transform.Translate(speed * Time.deltaTime, 0f, 0f, Space.World);
}
else if (moveType == "slide"){
newPos.x += speed * Time.deltaTime;
}
transform.eulerAngles = Vector3(0f, 0f, 0f);
}
if (dir == "u"){
if (moveType == "normal"){
transform.Translate(0f, speed * Time.deltaTime, 0f, Space.World);
}
else if (moveType == "slide"){
newPos.y += speed * Time.deltaTime;
}
transform.eulerAngles = Vector3(0f, 0f, 90f);
}
if (dir == "d"){
if (moveType == "normal"){
transform.Translate(0f, -speed * Time.deltaTime, 0f, Space.World);
}
else if (moveType == "slide"){
newPos.y -= speed * Time.deltaTime;
}
transform.eulerAngles = Vector3(0f, 0f, 270f);
}
}
if (moveType == "slide"){
if (dir != "i"){
transform.position = Vector3.SmoothDamp(transform.position, newPos, velocity, damp);
}
}
}
function OnTriggerEnter2D(coll : Collider2D){
var respawn = GameObject.Find("respawn");
if (coll.gameObject.tag == "enemy" && !isDead){
isDead = true;
sfx[0].Play();
deaths ++;
dir = "i";
transform.position = Vector2(respawn.transform.position.x, respawn.transform.position.y);
newPos = Vector2(transform.position.x, transform.position.y);
isDead = false;
}
if (coll.gameObject.tag == "slide"){
newPos = Vector2(transform.position.x, transform.position.y);
moveType = "slide";
}
}
function OnTriggerExit2D(coll : Collider2D){
if (coll.gameObject.tag == "slide"){
moveType = "normal";
}
}
function LateUpdate(){
var cam = GameObject.Find("MainCamera");
var hud = GameObject.Find("HUD");
//var controls = GameObject.Find("Controls");
var hudPos = cam.GetComponent.<Camera>().ScreenToWorldPoint(Vector2(32f, Screen.height - 32f));
//var conPos = cam.GetComponent.<Camera>().ScreenToWorldPoint(Vector2(Screen.width - 96f, 96f));
hud.transform.position = hudPos;
//controls.transform.position = conPos;
cam.transform.position = Vector3(transform.position.x, transform.position.y, cam.transform.position.z);
}
function pointSound(point : int){
if (point == 5){
sfx[1].Play();
}
if (point == 10){
sfx[2].Play();
}
if (point == 50){
sfx[3].Play();
}
if (point == 100){
sfx[4].Play();
}
}
I cant' see anything in the code that would cause this. Are there any children on the Player object, and if so, do any have colliders and share the same tag? Put the Debug.Log I posted above into the OnTriggerEnter2D function to print out the names of the objects that are being triggered. Only other solution I can think of at the moment is disabling the colldier of the Player object at the start of OnTriggerEnter2D, then re-enabling it after you've moved the object. Either that or adding a - yield WaitForSeconds(0.1); After moving it (and before switching the boolean again).
Also, just noticed something else; you mentioned the walls also have the "enemy" tag? From the image posted above, the player could be hitting two walls in the same frame, thus triggering it twice. If this is the case, there are a few solutions I can think of off the top of my head:
Parent all walls to a single gameobject with the "enemy" tag. This will compound all the colliders into one and register only one trigger.
As above, disable the Player collider on trigger (might not actually work though).
As above, add a delay before switching the boolean back.
$$anonymous$$ake different tags for the walls. (Again, might still call multiple triggers).
In the console, I get two messages:
wall_1_v (2) (UnityEngine.BoxCollider2D) UnityEngine.Debug:Log(Object) Player:OnTriggerEnter2D(Collider2D) (at Assets/Scripts/Player.js:108) wall_1_v (3) (UnityEngine.BoxCollider2D) UnityEngine.Debug:Log(Object) Player:OnTriggerEnter2D(Collider2D) (at Assets/Scripts/Player.js:108)
Those walls are the duplicated vertical wall prefab (7 squares, xD), I will try to make a parent object for all the walls, but doing that... the walls will have a local coordinate from the parent, and not from the world. I prefer to change their position in 1 unit as 1 square... lol.
BTW, thank you very much for your help seth_slax :3 and I'm sorry for my bad english, spanish is my native language.
Yeah, the Log definitely suggests that it's hitting two walls simultaneously. You could unparent them, move them and re-parent them afterwards to keep their space local. There's probably an alternative, but I can't think of any at this point. Not a problem! Hope this helped.
Well, thank you very much for your help buddy, I will try to search more about it on google.
Answer by epistomai · Nov 10, 2016 at 05:27 PM
I had the same issue, but worked for me. Now counts only once every instantiated gameObject:
void OnTriggerEnter2D(Collider2D other) {
if (!dead) {
Destroy (other.gameObject);
dead = true;
Points++;
Debug.Log (Points);
}
}
void Update () {
x -= 0.1f; //from right to left
if (Convert.ToInt16 (((Time.time / 0.1f) * 2) % 3) == 0 || (y >= 3.8 && !(y < 3.8)) || (y <= -3.8 && !(y > -3.8))) {
advance = advance * -1; //to switch upside/downside
}
y += 0.1f * advance;
if (gameObject.activeInHierarchy) {
gameObject.transform.position = new Vector3 (x, y, gameObject.transform.position.z);
}
if (x < -11) {
Destroy (gameObject);
}
dead = false;
}
Your answer
Follow this Question
Related Questions
How To Add Multiple 2d Box Colliders on Same Object for Different Effects 0 Answers
2D Colliders don't actually touch, causing problems 0 Answers
SImple but IMPOSSIBLE Enemies keep dying way ahead of time ! 0 Answers
NullreferenceException dealing damage to a child of the enemy 0 Answers
Need 2D help - Want to have object move towards point when it touches a trigger. 0 Answers