Unity- Adding to list in one instantiated objects script is adding to all instances

49 Views Asked by At

Hi i am new to unity and this is my first try to make my own program on it so any other tips than my problem would also be appreciated :)

scene-view-screenshoot

I am using unity to make a program which uses a simple genetic algorithm to get a square (ai) from one side of a platform to the other once it goes through one generation and moving right is determined the best and all the new instantiated prefabs are created and there Aimovement list variable set to move right (as indecated with number 1 in side of code) at point 2 all is correct until this for loop where it should be giving each ai a single extra random movement however instead each time it executes: instancesScipt.AiMovements.Add(possibleMovements[randomNum]); it adds that movement to every ais scripts variable and then goes onto the next ai which has the one already added and then adds another one and the problem repeats so by the end of the loop each ai which was only meant to have gained a random movement instead has 10 movements added and is the exact same as every other ai.

Main control script- attached to empty object


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

public class AiManager : MonoBehaviour
{
    public GameObject AiPrefab;

    private string[] possibleMovements = { "MoveRight", "MoveLeft", "Jump" };
    public int startingAiNum = 50;
    public int currentAiNum;
    public int generation = 1;
    public List<GameObject> Ais = new List<GameObject>();
    private bool completed = false;
    private int waiting = 200;
    public float sideSpeed = 2f;
    public float jumpSpeed = 4f;
    public int movementNum = 0;
    private Vector2 velocityCheck = new Vector2(0f, 0f);
    private Rigidbody2D randomAiRb;
    public List<string> optimalMovements;

    private void Awake()
    {
        for (int turn = 0; turn < startingAiNum; turn++)
        {
            GameObject newInstance = Instantiate(AiPrefab) as GameObject;
            Ais.Add(newInstance);
            GenerateMovement(turn);

        }
        currentAiNum = startingAiNum;

    }

    // Update is called once per frame
    void Update()
    {

        if (waiting < 200)
        {
            waiting++;
        }
        else
        {
            randomAiRb = Ais[Random.Range(0, Ais.Count)].GetComponent<Rigidbody2D>();
            waiting = 0;
            for (int turn = 0; turn < currentAiNum; turn++)
            {
                Rigidbody2D AiRigidBody = Ais[turn].GetComponent<Rigidbody2D>();
                if (AiRigidBody.transform.position.x < -6f)
                {
                    GameObject placeHolderAi = Ais[turn];
                    //Ais[turn].active = false;
                    Ais.Remove(placeHolderAi);
                    Destroy(placeHolderAi);
                    currentAiNum--;
                    turn--;
                    continue;
                }
                AiAtributes instancesScipt = Ais[turn].GetComponent<AiAtributes>();
                if (movementNum < instancesScipt.AiMovements.Count)
                {
                    CompleteMovement(turn, movementNum);
                    if (turn == currentAiNum - 1)
                    {
                        movementNum++;
                    }
                }
                else if (movementNum >= instancesScipt.AiMovements.Count - 1
                && (randomAiRb.velocity.x != 0 && randomAiRb.velocity.y != 0)
                && (turn == currentAiNum - 1))
                {
                    if (turn == currentAiNum - 1)
                    {
                        movementNum++;
                    }

                }
                else if (turn == currentAiNum - 1)
                {
                    currentAiNum = startingAiNum;
                    movementNum = 0;
                    generation++;
                    CalculateBestMovements();
*1                  ResetAis();
                    print("here");
                    break;
                }

            }
        }



    }

    private void GenerateMovement(int turn)
    {
        AiAtributes instancesScipt = Ais[turn].GetComponent<AiAtributes>();
        //
        int randomNum = Random.Range(0, 3);
        //
        instancesScipt.AiMovements.Add(possibleMovements[randomNum]);
    }

    private void CompleteMovement(int turn, int movement_Num)
    {
        AiAtributes instancesScipt = Ais[turn].GetComponent<AiAtributes>();
        //instancesScipt.AiMovements
        string movement = instancesScipt.AiMovements[movement_Num];
        Rigidbody2D AiRB = Ais[turn].GetComponent<Rigidbody2D>();
        if (movement == "MoveRight")
        {
            AiRB.velocity = new Vector2(AiRB.velocity.x + sideSpeed, AiRB.velocity.y);
        }
        else if (movement == "MoveLeft")
        {
            AiRB.velocity = new Vector2(AiRB.velocity.x + -sideSpeed, AiRB.velocity.y);
        }
        else
        {
            AiRB.velocity = new Vector2(AiRB.velocity.x, AiRB.velocity.y + jumpSpeed);
        }
    }

    private void ResetAis()
    {
        for (int turn = 0; turn < currentAiNum; turn++)
        {
            GameObject placeHolderAi = Ais[0];
            Ais.Remove(placeHolderAi);
            Destroy(placeHolderAi);
        }
        Ais = new List<GameObject>();
        for (int turn = 0; turn < startingAiNum; turn++)
        {
            GameObject newInstance = Instantiate(AiPrefab) as GameObject;
            newInstance.name = "Ai" + turn.ToString();
            Ais.Add(newInstance);
            AiAtributes instancesScipt = Ais[turn].GetComponent<AiAtributes>();
            instancesScipt.AiMovements = optimalMovements;
        }
*2      for (int turn = 0; turn < startingAiNum; turn++)
        {
            GenerateMovement(turn);
        }

        currentAiNum = startingAiNum;
    }

    private void CalculateBestMovements()
    {
        float bestFitness = -10000f;
        for (int turn = 0; turn < currentAiNum; turn++)
        {
            AiAtributes instancesScipt = Ais[turn].GetComponent<AiAtributes>();
            float fitness = Ais[turn].transform.position.x * 15f;
            if (instancesScipt.collectedCoin)
            {
                fitness = fitness + 120f;
            }
            else if (instancesScipt.finished)
            {
                fitness = fitness + 1000000f;
            }
            if (fitness > bestFitness)
            {
                bestFitness = fitness;
                optimalMovements = instancesScipt.AiMovements;
            }
        }
    }
}

script atatched to each instance


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

public class AiAtributes : MonoBehaviour
{
    public List<string> AiMovements = new List<string>();
    public bool finished = false;
    public bool collectedCoin = false;

    private void OnCollisionEnter2D(Collision2D other)
    {
        if (other.gameObject.name == "Finish")
        {
            finished = true;
        }
    }
}

a have put lots of print statements to find out what is going on to be able to single out that the for loop (tagged with astrix and a 2) is the problem currently i give each instance a name to determine that when the script is opened in the generatemovement procedure it is doing it to each separate ai so as far as i can tell they have not combined or something but i am lost as to why it is happening and can't find anything online to help or that gives an explanation as to why it is occurring.

thank you for any help.

0

There are 0 best solutions below