Search Unity

Discussion Combat raycast

Discussion in 'Scripting' started by Deleted User, Feb 11, 2023.

  1. Deleted User

    Deleted User

    Guest

    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 by a moderator: Feb 11, 2023
  2. samana1407

    samana1407

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

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    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.
     
    Deleted User likes this.
  4. Deleted User

    Deleted User

    Guest

    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. Deleted User

    Deleted User

    Guest

    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 by a moderator: Feb 12, 2023