Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Question Multiple CircleCastAll but only hit the same object once

Discussion in 'Scripting' started by Autoface, Aug 6, 2023.

  1. Autoface

    Autoface

    Joined:
    Sep 23, 2013
    Posts:
    112
    Hi, I have a question about Raycasts/CircleCastAll. When my character swings a sword/weapon/punch, I want to be able to use Raycasts/CircleCastAll multiple times as the sword is moving, and if the ray/circle hits an enemy, I don't want the casts/circles that follow to hit the same enemy untill the player swings the sword again.
    I do however want to be able to hit multiple enemies in a single swing/hit.

    So previously I had this working with a simple collider set as a trigger on the sword, and then used an OnTriggerEnter which worked fine as once the enemy entered the trigger it wouldn't trigger again until the player attacked again.

    But for reasons Ive decided to switch to CircleCastAll but I'm not sure how I should go about making the enemy only get hit once and not again until the player attacks again.

    So this is where Im at so far.
    In the player script:
    Code (CSharp):
    1.  
    2. RaycastHit2D[] hits = Physics2D.CircleCastAll(rayPos, 0.25f, Vector2.zero);
    3. if (hits.Length > 0)
    4.     {
    5.         weaponHand.GetComponent<PlayerWeaponCollision_Script>().RayHit(hits);
    6.     }
    7.  
    In the PlayerWeaponCollision_Script script (still named collision as was previsouly using a trigger):
    Code (CSharp):
    1.  
    2. public void RayHit(RaycastHit2D[] hits)
    3.     {
    4.         if (HitContainsTag(hits, "Mob"))
    5.         {
    6.             if (inventory_Script.heldItem != null)
    7.             {
    8.                 hits[hitIndex].collider.GetComponent<MobStats_Script>().GetHit(inventory_Script.heldItem);
    9.             }
    10.             else
    11.             {
    12.                 hits[hitIndex].collider.GetComponent<MobStats_Script>().GetHit(null);
    13.             }
    14.         }
    15.     }
    16.  
    17. int hitIndex;
    18. bool HitContainsTag(RaycastHit2D[] hits, string tag)
    19. {
    20.     bool containsTag = false;
    21.     hitIndex = 0;
    22.  
    23.     for (int i = 0; i < hits.Length; i++)
    24.     {
    25.         if (hits[i].collider.tag == tag)
    26.         {
    27.             hitIndex = i;
    28.             containsTag = true;
    29.         }
    30.     }
    31.     return containsTag;
    32. }
    33.  

    I was thinking maybe store all of the hit enemies that have been hit in a list and then setting something like "bool canGetHit = fase" in the MobStats_Script (attached to the enemy). Then once that attack is over I can loop though the all of the hit objects in the list and set "canGetHit = true".

    OR

    I could add each hit enemy to a list and check if that same enemy is currently inside the list for the following casts. If the enemy is in the list then don't do anything. When the attack has finished the list gets cleared.

    I'm coming up with a few ideas, I'm just wondering if theres a better way of doing this.

    Thanks
     
  2. Autoface

    Autoface

    Joined:
    Sep 23, 2013
    Posts:
    112
    ugh, totally answered my own question as I was writing it.

    I decided to go with the second idea as it seamed simpler.
    When an enemy gets hit, they get added to a list. Only when they are not in that list are they able to be hit. At the end of each "swing" the list gets cleared.

    Still open to other suggestions though.
     
    Kurt-Dekker likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    Seems like you nailed it.

    The only thing you may wish to consider is if you have some crazy multi-swipe "power" sword attack in the future and want to clear the list of hit enemies mid-stream through.

    Imagine a big swashbuckling figure-8 sword slash, right to left going down, then back up and left to right to finish. You'd want to hit the same guy both coming and going.
     
    Autoface likes this.