- Home /
Is it possible to combine child trigger of a object to only trigger OnTriggerEnter once?
Hello, i want to hit monsters with a sword, the sword has a collider and i use the OnTriggerEnter to deal damage, my monsters have different shapes and a default collider/trigger doesn't fiit that's why i use multiple trigger on the monsters to fill the monster shape.
But the problem is, because there a multiple triggers my sword OnTriggerEnter sometimes triggers twice in the same "swing". For example let's say a human like enemy which has a trigger on the head and body, if my sword would swing from the top to bottom it would trigger the had and body and get the OnTriggerEnter call twice.
Is there a way to combine the monster child triggers into a single trigger so that my sword slash in the example above would only trigger when i hit the enemy head and call trigger enter when i leave the body trigger?
Answer by oStaiko · Nov 21, 2016 at 07:35 PM
Well, complex triggers have their disadvantages of course. There is no "easy" way to do this.
I'm going to guess a few things about your game. The player isn't constantly attacking, and has to do something to initiate an attack. An enemy should only be hit once per attack by the sword, and there's no spinning attacks that would hit them twice per swing. Lastly, all damageable entities descend from the same class inheritance.
If those assumptions are true, a simple thing to do would be whenever your sword hit an enemy, to deactivate its collision box after applying damage. This would prevent hitting an enemy twice with one swing. You could then reactivate the collision detection when you initiate a new swing.
But then lets say there's 3 enemies in a row, and you want to be able to hit all of them with one swing. If you deactivate the sword collision on the first one, it'll simply pass through the others, so that wont do here!
For every swing of a sword, you can store a reference to each entity hit. If you are using instances of an enemy script or such, you can do something like:
using System.Generic.Collections;
List<EnemyScript> hits;
void Swing ()
{
hits = new List<EnemyScript> ();
//Do your swing stuff here
}
void OnTriggerEnter (Collider other)
{
EnemyScript script = other.GetComponent<EnemyScript>();
//Depending on your set up, getting the reference may need to be done differently
if (script != null && hits.Exists(script)))
{
hits.Add(script);
//ApplyDamage and such here
}
}
This prevent the same instance of an enemy from being hit twice by any collider with that script, per Swing(). I didn't test it, but it should work.
If you have different types of enemies, with different scripts, this can be done with something called inheritance. There's a nice Unity guide Here that covers it, just make a new class "Damgeable" that has an "OnDamage" function, and make every damageable entity inherit the Damageable class. You can then call OnDamage(params) in the script above, easy as that! Any other questions on inheritcance should be answerd by the video.
Hello, thanks for the long answer, i thought that maybe there is a "simple" way to combine the triggers without extra code in the Trigger $$anonymous$$ethods but i guess there is not? $$anonymous$$y collider objects have a "HitBox" Script which has a reference to the parent character/enemy, I have a Interface IRpgCharacter for them.
$$anonymous$$y triggers are big enough so that they always overlap a little.
I expanded your example a little for my needs, i made a Dictionary which has a IRpgCharacter as $$anonymous$$ey and a list of HitBox (the colliders) as value. Now OnTriggerEnter i check if there is already a key for the character, if there is it means that im already inside a trigger of this character and i don't deal damage and just add the collider to the list, otherwise i create a new dictionary entry and also add the collider to the list of the new character entry
OnTriggerExit i check if there is a character in the dictionary for the hitbox, if there is not, then i don't do anything (this should never happen in theory, because OnTriggerEnter would be called first and should add a entry for the character) If there is a character then i remove the current hitbox collider from the list and check the list count, if there list is empty it means that i left the last trigger of the character and i remove the character from the dictionary so that the next "new" OnTriggerEnter can deal damage again.
This soltuion works good so far for my project but its important that this only works because my trigger are big enough to overlap, if they wouldn't overlap then it wouldn't work
Your answer
Follow this Question
Related Questions
Trigger doesn't work 100% of the time. 1 Answer
Rigidbody.SweepTest Hit Trigger Colliders 0 Answers
OnTriggerEnter problems 3 Answers
Simple Triggers problem. 1 Answer
Physics Possibilities?: Angles, Penetration, Exceptions 4 Answers