Issue with Chain Lightning spell using the list feature

Hi I am making a Chain Lightning spell that needs to bounce from one unit to the nearest, and so on, never hitting the same unit twice. I have done it using the code below. The issue I have is that the only way I could get it to work (im not experienced with lists) is to change the units tag when hit, and then run the find nearest unit again. However that will cause issues for other parts of my game, so I am looking to make a list that doesn’t just find the nearest unit, but also the next nearest unit and so on.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChainLightningBounce : MonoBehaviour
{
    GameObject targetObject;
    Vector2 moveSpot;
    public float speed;
    public float bounceNumber;
    public float damage;

    public List<GameObject> targetsToAttack;

    TakeDamage takeDamageScript;

    public bool findTarget;

    bool triggered;

  AudioSource audioEffect;


    void Start()
    {
        StartCoroutine(nameof(WaitGoTarget));
        GetClosestObjectDamage();

        audioEffect = GameObject.Find("Chain Lightning Audio").GetComponent<AudioSource>();
          
    }

    IEnumerator WaitGoTarget()
    {
        yield return new WaitForSeconds(0.15f);
        findTarget = true;
        audioEffect.Play();
    }

  
    void Update()
    {
        if(findTarget == false)
        {
            return;
        }
      

        transform.position = Vector2.MoveTowards(transform.position, targetObject.transform.position,
        speed * Time.deltaTime);

        // rotate object in direction it is travelling  //

        Vector2 dir = targetObject.transform.position - transform.position;

        float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;

        transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);

        //----------------------------------------------//

        if (transform.position == targetObject.transform.position && bounceNumber > 0 && targetsToAttack.Count > 0)
        {
            if(triggered == false)
            {
                triggered = true;
                AttackingEnemyDamage();
            }
        
        }

  
       

        if(bounceNumber <= 0 || targetsToAttack.Count == 0)
        {
            Destroy(gameObject);
        }
       
      
    }

    public GameObject GetClosestObjectDamage()
    {
        targetsToAttack = new List<GameObject>();

        targetsToAttack.AddRange(GameObject.FindGameObjectsWithTag("EnemyUnits"));


        float closest = 1000; //add your max range here
        GameObject closestObject = null;
        for (int i = 0; i < targetsToAttack.Count; i++)  //list of gameObjects to search through
        {
            float dist = Vector3.Distance(targetsToAttack[i].transform.position, transform.position);
            if (dist < closest)
            {
                closest = dist;
                closestObject = targetsToAttack[i];
            }

        }

        if (targetsToAttack.Count != 0)
        {
            moveSpot = closestObject.transform.position;
            targetObject = closestObject;

        }

        return closestObject;

    }

    public void AttackingEnemyDamage()
    {
      

        takeDamageScript = targetObject.GetComponent<TakeDamage>();

        if (takeDamageScript.currentHealth > damage)
        {
            bounceNumber -= 1;
        }

        takeDamageScript.NPCTakeDamageChainSpell(damage);

       

        StartCoroutine(nameof(WaitNextZap));

    
    }

    IEnumerator WaitNextZap()
    {
        yield return new WaitForSeconds(0.1f);
     
       
        GetClosestObjectDamage();

        triggered = false;

      

    }



}

One approach is to create a temporary list and put all your chain-lightning-target candidates in that list.

Now iterate that list and choose the next closest candidate from the list.

As you find each candidate, remove him from the temporary list and add him to a new list which is your “sequence of zappy parts”

When you either run out of “how many chain steps can I do” or else run out of candidates, now you have a list of points to feed into your lightning spell and off you go.

1 Like

Hi thanks for the help, could you perhaps show some code snippers/examples of how this is done? This is my current list code, where I have issues getting 2nd or 3rd closest etc.

 public GameObject GetClosestObjectDamage()
    {
        targetsToAttack = new List<GameObject>();

        targetsToAttack.AddRange(GameObject.FindGameObjectsWithTag("EnemyUnits"));


        float closest = 1000; //add your max range here
        GameObject closestObject = null;
        for (int i = 0; i < targetsToAttack.Count; i++)  //list of gameObjects to search through
        {
            float dist = Vector3.Distance(targetsToAttack[i].transform.position, transform.position);
            if (dist < closest)
            {
                closest = dist;
                closestObject = targetsToAttack[i];
            }

        }

        if (targetsToAttack.Count != 0)
        {
            moveSpot = closestObject.transform.position;
            targetObject = closestObject;

        }

        return closestObject;

    }

Definitely go look up some basic C# tutorials on how to use a List, how to search for nearest objects, etc… No sense me retyping them all here!

I’ll give you an extra hint as well, search up how to use foreach loops with lists.