Search Unity

OnTriggerEnter2D hits two colliders same time, how do I tell the difference between them?

Discussion in '2D' started by guildmaster2017, Aug 8, 2018.

  1. guildmaster2017

    guildmaster2017

    Joined:
    Apr 5, 2018
    Posts:
    5
    Hi guys,

    I’m working on a 2d rpg similar to the old school Zelda if it met Skyrim. We have blocking and deflections but they only seem to work when they want to work. I have a player parent that holds the dynamic rigid body collider that will take damage when hit by the enemies sword static trigger collider. And the player has shield and sword children attached that have kinematic trigger colliders. When the block animation is called it enables the collider and when the sword animation is called it enables the collider for one frame. Only problem is when the player and enemy are too close and I block when he attacks then it should knock him back and register as a shield hit. However, the sword collider appears for just one frame and triggers the players collider and shield collider at the same time so it mostly takes the players collider as precedence. It was working with the shield for a long time but just stopped working yesterday even though I haven’t messed with it.

    Any advice as to whether some trigger interactions take precedence over others?

    PS: The triggers hit at the exact same time every time since the sword trigger is activated on one frame during animation.

    Any and all advice helps, thank you.

    Oliver
     
  2. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    One way you might be able to solve it is to do a raycast towards the player from the enemy, and see if you hit shield or player.

    Another way would be to not use the shield as a collider, and have a boolean on the player for "shielded" or something, and then check the angle of impact for directional blocking.

    Another way would be to not use the built-in events, but rather do your own checking with an OverlapAll function, so you can get all the triggers in one go and then loop through them.

    Hope that helps.
     
    Last edited: Aug 9, 2018
    guildmaster2017 likes this.
  3. guildmaster2017

    guildmaster2017

    Joined:
    Apr 5, 2018
    Posts:
    5
    Thanks! I was thinking of trying the ray cast idea as well. I like the directional blocking idea as well, what methods could I use to make that happen?
     
  4. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    For that, you'll want to first get the attack collision with the player as usual, and use GetComponent to get the component holding the state of the player. Check if they're blocking, if they are, then you want to compare the position of the enemy relative to the player, with the facing direction of the player.

    You can get fancy with the angles you want to block, like if the shield is on the left hand, it blocks the left side more, etc, but I'm guessing you want a pretty straightforward blocking range in front of the player

    You can compare the two angles like this:
    Code (CSharp):
    1. // convert world position of enemy to player's local space
    2. Vector2 enemyPositionRelativeToPlayer = player.transform.InverseTransformPoint(enemy.transform.position);
    3.  
    4. // get a value between 0 and 180
    5. float angle = Vector2.Angle(player.transform.forward, enemyPositionRelativeToPlayer);
    6.  
    7. // check if the hit was from behind
    8. if(angle > 90) // implies 180 degree field of blocking in front of the player
    9. {
    10.     // get hit
    11. }
    12. else
    13. {
    14.     // block hit
    15. }
    If you care about which side the enemy is on, you can use Vector2.SignedAngle to get a value between -180 and 180.
     
    Last edited: Aug 13, 2018