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.

Discussion Combat raycast

Discussion in 'Scripting' started by Alvare32, Feb 11, 2023.

  1. Alvare32

    Alvare32

    Joined:
    May 26, 2020
    Posts:
    57
    Hey forum,
    I'm currently trying to do a raycast covering the weapon base to the weapons tip transforms.

    Code (CSharp):
    1.  
    2. private IEnumerator DealingDamage(float attackDuration, float attackDelay)
    3. {
    4.     yield return new WaitForSeconds(attackDelay);
    5.     List<GameObject> hitObjects = new List<GameObject>();
    6.     //Do some raycasting between the sword's base and the sword's tip as long as we're doing the attack.
    7.     for(float t=0.0f; t<1.0f; t+=Time.deltaTime/attackDuration)
    8.     {
    9.         Vector3 weaponBasePos = weaponBase.transform.position;
    10.         Vector3 weaponTipPos = weaponTip.transform.position;
    11.         float bladeLength = Vector3.Distance(weaponBasePos, weaponTipPos);
    12.         RaycastHit hitData;
    13.         if (Physics.Raycast(weaponBasePos, (weaponBasePos - weaponTipPos).normalized, out hitData, bladeLength, combatLayer))
    14.         {
    15.             if (!hitData.collider.isTrigger && hitData.point.y> Motor.TransientPosition.y+.1f)
    16.             {
    17.                 if (!hitObjects.Contains(hitData.collider.gameObject))
    18.                 {
    19.                     Debug.Log("We hit "+ hitData.collider.gameObject.name);
    20.                     hitObjects.Add(hitData.collider.gameObject);
    21.                 }
    22.             }
    23.         }
    24.         yield return null;
    25.     }
    26. }
    27.  
    Is this a terrible way of doing it? Also, does creating a list of GameObjects for checking which objects have been hit bloat the garbage collection? Is there anything necessary to get rid of the list other than clearing it? Or is it better to have the list be created once in the character controller and then re-used instead of being created in the void?
     
    Last edited: Feb 11, 2023
  2. samana1407

    samana1407

    Joined:
    Aug 23, 2015
    Posts:
    36
    In your code, the coroutine is interrupted immediately after the first collision found (line 19). Why is there a list at all?
     
    Alvare32 and PraetorBlue like this.
  3. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,562
    Several problems here:
    1. yield return [URL='http://www.google.com/search?q=new+msdn.microsoft.com']new[/URL] WaitForEndOfFrame();
      should be
      yield return null;

    2. As mentioned above, your list is pointless since you're
      yield break
      ing as soon as you add the first element to it. I think you should remove line 19.
    3. If you want to know which unique objects have been hit, you should probably use
      Code (CSharp):
      1. HashSet
      instead of List. Then you won't need to do the Contains check you have there and it will be faster.
    4. There is no need to Clear the list at the end since it is going to cease to exist entirely at that point since the coroutine ends there and it's a local variable.
    5. And of course.. it doesn't seem like you're doing anything with the list, though i assume you intend to change that at some point.
     
    Alvare32 likes this.
  4. Alvare32

    Alvare32

    Joined:
    May 26, 2020
    Posts:
    57
    Yes, I intended the collisions being added to cease for the already found object. And later, I must determine which surface type the object has. Wood, Stone or Enemy. (So I can do a particle effect and different hit sounds)
    A hash set? Never heard of those until just a few days back. I will look up what those are. :confused:
     
  5. Alvare32

    Alvare32

    Joined:
    May 26, 2020
    Posts:
    57
    Ah wait, so a hash can be unique somehow and still be coupled with that object?
    I'm very curious to learn more about the hash set you mentioned. Can you please elaborate on how that looks in a similar case?
    Simply like this? And it wouldn't allow for duplicates so I remove the Contains line?

    Code (CSharp):
    1. private IEnumerator DealingDamage(float attackDuration, float attackDelay)
    2. {
    3.     yield return new WaitForSeconds(attackDelay);
    4.     HashSet<Collider> hitObjects = new HashSet<Collider>(); //HashSets don't allow duplicates. So we don't need to check if it already contains the same...?
    5.     //Do some raycasting between the sword's base and the sword's tip as long as we're doing the attack.
    6.     for(float t=0.0f; t<1.0f; t+=Time.deltaTime/attackDuration)
    7.     {
    8.         Vector3 weaponBasePos = weaponBase.transform.position;
    9.         Vector3 weaponTipPos = weaponTip.transform.position;
    10.         float bladeLength = Vector3.Distance(weaponBasePos, weaponTipPos);
    11.         RaycastHit hitData;
    12.         if (Physics.Raycast(weaponBasePos, (weaponBasePos - weaponTipPos).normalized, out hitData, bladeLength, combatLayer))
    13.         {
    14.             if (!hitData.collider.isTrigger && hitData.point.y> Motor.TransientPosition.y+.1f)
    15.             {
    16.                 Debug.Log("We hit "+ hitData.collider.gameObject.name);
    17.                 hitObjects.Add(hitData.collider);
    18.             }
    19.         }
    20.         yield return null;
    21.     }
    22. }
     
    Last edited: Feb 12, 2023