- Home /
*** Trigger Collider2D event only once ***
Hello there,
I have some difficulties executing a Collision2D trigger event only once. For a top-down 2D game with melee fight, I am using a Capsule Collider 2D for dealing damage to the enemy. Whenever the attack key ('Space') is pressed, the Capsule Collider2D attached to the player is activated and any enemy within the range of this collider is damaged.
Now this part of the script works fine. The problem is, that when the OnTriggerEnter2D event is triggered, it should be executed only once and decrease enemy health by 1. The code in the script looks like this:
public class enemyControl : MonoBehaviour {
public int enemyHealth = 3;
public GameObject enemy;
public SpriteRenderer enemySprite;
public Sprite enemyDead;
public Collider2D enemyCollider;
public Collider2D damageCollider;
public Collider2D playerAttack;
void OnTriggerEnter2D (Collider2D playerAttack) {
if (playerAttack.tag == "plrAttack") {
enemyHealth-=1;
}
}
void Start () {
enemySprite = GetComponent<SpriteRenderer> ();
}
void Update () {
if (enemyHealth <= 0)
{
enemySprite.sprite = enemyDead;
enemyCollider.enabled = false;
}
}
}
The problem is that whenever I press the attack key ('Space'), the collision trigger starts a very fast loop that decreases the enemy's health to zero immediately. Is there some way to break this "loop" after only one execution?
I have to add, that I have searched the forum for possible solutions, including using OnTriggerExit and introducing a boolean value for checking the state of the trigger, but none of that seemed to work as the loop just goes on.
The attack action script looks like this, btw.:
if (Input.GetKey (KeyCode.Space) && !moving) {
playerAnimator.SetBool ("isAttacking", true);
attack.enabled = true;
fighting = true;
}
"attack.enabled = true" is the row that enables the Capsule Collider 2D that is dealing the damage.
I would really appreciate any help or hints as I am stuck with this unnerving problem for days...
Many thanks!
You could:
Use Input.Get$$anonymous$$eyDown ($$anonymous$$eyCode.Space) ins$$anonymous$$d of Input.Get$$anonymous$$ey ($$anonymous$$eyCode.Space)
Use an animation event as part of the attack animation, and do an overlap test.
Also try:
if (!attack.enabled)
attack.enabled = true;
to avoid setting it to enabled each frame.
Answer by unidad2pete · Aug 09, 2017 at 08:06 PM
Try making a new bool to check if collider has been triggered on each hit.
public bool hitCheck;
void OnTriggerEnter2D (Collider2D playerAttack) {
if (playerAttack.tag == "plrAttack" && !hitCheck) {
enemyHealth-=1;
hitCheck = true;
}
}
set hitCheck to false again on your Input Space for example.
Hello! Thanks for the reply, I really appreciate your help!
I tried the following:
public bool takingDamage;
void OnTriggerEnter2D (Collider2D playerAttack) {
if (playerAttack.tag == "plrAttack" && !takingDamage) {
enemyHealth-=1;
takingDamage = true;
}
}
And I have added this to the playerControl script:
if (Input.Get$$anonymous$$eyDown ($$anonymous$$eyCode.Space) && !moving) {
enemy.takingDamage = false;
playerAnimator.SetBool ("isAttacking", true);
attack.enabled = true;
fighting = true;
}
Now this seems to successfully stop the loop after one frame and hit; the enemy suffers one health damage as intended, but the takingDamage bool just won't flip back to false (even though I also changed the input method to Get$$anonymous$$eyDown from Get$$anonymous$$ey) after executing the loop once.
why enemy.takingDamage = false;?? its takingDamage = false;
Because it is in a different script (the one controlling the player) attached to a different game object (the player object). I aim to change the Boolean variable of the script controlling the enemy from within my player controller script. Am I doing it wrong?
Answer by merkaba48 · Aug 09, 2017 at 09:55 PM
If you've tried using a bool state to track if it's been hit that frame or not, and it still doesn't work, the problem might be elsewhere. Have you tried using the debugger and putting a breakpoint in the OnTrigger method, then seeing how many times it's called? Or even just printing something to the console inside the method.
Hi there! Thanks for your reply!
I did - the loop executes 8 to 10 times per button hit.
Answer by szaboa22 · Aug 10, 2017 at 06:22 PM
@unidad2pete I think I have found the root problem why the boolean checker value ("takingDamage") won't flip back to "false" when hitting the attack button.
All the enemies are instantiated as clones from a prefab at random points inside the procedurally generated dungeon. Even though I reference the GameObject / prefab in the script, the variable change won't apply to the clones. I have searched through the forum, but couldn't find any viable solution.
Could you please look at my below script and provide me with any hints regarding how could I reference the prefab clone variables?
Many thanks!
/* I have removed some of this script for now as it is irrelevant to the question */
public class playerControl : MonoBehaviour {
public GameObject enemy;
enemyControl ec; //for referencing another script
public Animator playerAnimator;
private bool moving = false;
private bool fighting = false;
public Collider2D attack; // referencing the attack collider
void Start () {
playerAnimator = GetComponent<Animator>();
playerAnimator.SetBool ("isMoving", false);
playerAnimator.SetBool ("isAttacking", false);
attack.enabled = false;
ec = enemy.GetComponent<enemyControl> ();
}
void Update ()
{
if (Input.GetKey (KeyCode.Space) && !moving) {
ec.takingDamage = false; //it won't flip back to false on the clones!
playerAnimator.SetBool ("isAttacking", true);
attack.enabled = true;
fighting = true;
}
}
}
Your answer
Follow this Question
Related Questions
Trigger2D not working 0 Answers
Creating 'redstone' like wires 1 Answer
Problem with collision with two colliders simultaneously in Unity 2D 1 Answer
Unity 2D Collider Safe Sizes 0 Answers