Austin Seymour
Austin Seymour

Reputation: 3

Unity list item not added

So basically I have 2 static lists I use as an object pool and 3 functions to interact with those lists. I've been storing the script attached to the gameObject because that what I want to do all the work on.

One to add the object to the list

public static void AddLightning(Lightning newLightning)
{
    lightningList.Add(newLightning);
}

One to remove the object from the active list, deactivate it and move it to the dead list

public static void RemoveLightning(Lightning oldLightning)
{
    lightningList.Remove(oldLightning);
    deadLightningList.Add(oldLightning);
    Debug.Log("Dead number in list: " + oldLightning.number);
    oldLightning.gameObject.SetActive(false);
    //Debug.Log("adding dead Lightning" + deadLightningList.Count);
}

One To fetch a dead instance or make a new one if there are no dead ones left.

public static Lightning GetLightning()
{
    Lightning retLightning;
    //Debug.Log(deadLightningList.Count);
    if (deadLightningList.Count > 0)
    {
        //Debug.Log("Using dead Lighting");
        retLightning = deadLightningList[0];
        deadLightningList.RemoveAt(0);
        lightningList.Add(retLightning);
        return retLightning;
    }
    //Debug.Log("Adding New Lighting");
    GameObject newObject;
    newObject = Instantiate<GameObject>(lightningFab);
    retLightning = newObject.GetComponent<Lightning>();
    lightningList.Add(retLightning);
    retLightning.gameObject.SetActive(true);
    return retLightning;
}

This is the only code that requests a lightning instance

                float dmgMult = 1;
            float chainDamage = damage;

            Lightning lightning;
            lightning = GetLightning();
            lightning.SetTower(tower);
            lightning.SetNumber(lightningNum);
            lightningNum++;
            lightning.setTargets(chainList);

            foreach (mobBase mob in chainList)
            {
                chainDamage *= dmgMult;
                mob.DamageMob(chainDamage);
                //Debug.Log("Damage: " + chainDamage);
                dmgMult *= 0.8f;
            }

The lightning is set to kill itself after a fixed time and re-add itself to the dead list.

void OnEnable () {
    ProjectileBase.AddLightning(this); //Added to see if it would help, it doesnt
    lightningLine = GetComponent<LineRenderer>();
    timeKill = .2f;
}

// Update is called once per frame
void FixedUpdate () {
    setLine(targets);
    timeAlive += Time.deltaTime;
    if (timeAlive >= timeKill)
    {
        Debug.Log("Dead number Adding: " + number);
        ProjectileBase.RemoveLightning(this);
    }

}

The lightning properly deactivates itself when it's dead. But the list never seems to have more than one instance of the object inside it. I added the lightningNum to see if there was any pattern when it made a new one and it seems to be re-using the lightning at least once then forgetting about it all together.

ProjectileBase is where the static lists are held

Upvotes: 0

Views: 453

Answers (1)

Milan Egon Votrubec
Milan Egon Votrubec

Reputation: 4059

From the looks of things, the solution is a two-step process. First, have it so the your lightning isn't added to the pool during OnEnable(). When you create the Lightning, call an additional method, something like Setup(). The reason being, the Lightning will add itself to the pool EVERY time you re-activate it.

void Setup()
{
    ProjectileBase.AddLightning(this); //Added to see if it would help, it doesnt
    lightningLine = GetComponent<LineRenderer>();
    timeKill = .2f;
}

The second step is to actually re-activating your object when you remove it from your dead list.

public static Lightning GetLightning()
{
    Lightning retLightning;
    //Debug.Log(deadLightningList.Count);
    if (deadLightningList.Count > 0)
    {
        //Debug.Log("Using dead Lighting");
        retLightning = deadLightningList[0];
        deadLightningList.RemoveAt(0);
        lightningList.Add(retLightning);
        retLightning.gameObject.SetActive(true); // <-- Reactivate the object
        return retLightning;
    }
    //Debug.Log("Adding New Lighting");
    GameObject newObject;
    newObject = Instantiate<GameObject>(lightningFab);
    retLightning = newObject.GetComponent<Lightning>();
    lightningList.Add(retLightning);
    retLightning.gameObject.SetActive(true);
    return retLightning;
}

Alternatively, make sure you re-activating the lightning after you've gotten it. Either-or, but in the code you've supplied you haven't shown us re-activating it.

Now, although this wasn't asked by your question, have you considered a Queue<Lightning> collection, if you're simply taking the first, and adding it to the end of a list when finished with? It looks like every 0.2 seconds, you're deactivating the lightning and re-using an old one anyway. Two List<Lightning> collections may be adding more complexity than the problem warrants..?

Upvotes: 2

Related Questions