sarah mientka
sarah mientka

Reputation: 3

how to remove a specific game object (that is in an array) from a list?

my goal with the code is to have multiple skulls appear on screen for comparison. Depending on number of skulls on screen (1-6) they change position and size, Ive done this through the use of an array of gameObjects (the skulls) and a list that can keep track of which skull is in which "position".

The code works if you are adding, but runs into problems when you remove the object. It "works" on RemoveAt only if you remove the GameObjects in the same order that they were added. IE: The list is always removing element 0(first item in list) rather than the specific gameObject that is instigating the RemoveAt function.

While I have found many answers on how to remove specific individual gameObjects, They dont work since my gameObjects are in an array- I cant simply say remove gameObject name. Which leads me to my question of how to remove a specific gameObject[] from a list?

either remove or removeAll run these two errors:

error CS1502: The best overloaded method match for System.Collections.Generic.List<UnityEngine.GameObject>.RemoveAll(System.Predicate<UnityEngine.GameObject>)' has some invalid arguments.
Error CS1503: Argument
#1' cannot convert int' expression to typeSystem.Predicate'

Here are my two scripts for all this:

Script on each bird skull named birdController:

public int myBirdID;
public int orderInList;

//bool to keep track of object active or not
public bool whoAmIReally;
//potentially redundant; allows game object to see if hes on or not
public GameObject IAmMe;

// Use this for initialization
void Start () {
    //fixingIntOrder();
}

public void OnEnable(){
    //when object is on check bool
        whoAmIReally = true;
        Debug.Log("IM ON");
}
    public void OnDisable(){
    //when object is turned off uncheck bool, change list value to 0
            //**this wont change actual list order or value in cubeplacement script- my hope is that it might have- likely missing a step somewhere
        whoAmIReally = false;
        orderInList = 0;
        Debug.Log("IMOFF");
}

Script on empty with all of my array and list info named cubePlacement:

    public int numberSkullOnScreen;
    public bool[] skullOn;
    public GameObject[] allSkulls;

    public GameObject listHolder;

    public List<GameObject> birdsOnScreen = new List<GameObject>();


//declaring the script to avoid NullReferenceEcxeption where I reference it 
public birdController _birdController;


    // Use this for initialization
    void Start () {
        //only way I can get my list to work: have an object act as a placeholder onStart
        birdsOnScreen.Add(listHolder);
    }

//turning on and off the skulls
    public void toggleBirdSkull(int mySkull){
        if (skullOn[mySkull] == false){
            //set specific gameObject active
            allSkulls[mySkull].SetActive(true);
            //make skull on bool true 
            skullOn[mySkull] = true;
            //add one to the number on screen
            numberSkullOnScreen++;

            //reference int orderInList from Bird controller script
            allSkulls[mySkull].gameObject.GetComponent<birdController>().orderInList = numberSkullOnScreen;

            //add skull to list when turned on THIS WORKS YAY
            birdsOnScreen.Add(allSkulls[mySkull]);
            //Run function to place skulls
            placementSkulls();
        }

        else{
            allSkulls[mySkull].SetActive(false);
            skullOn[mySkull] = false;
            numberSkullOnScreen--;

            //remove skull from list when turned off-- THIS DOESNT WORK... 
            birdsOnScreen.RemoveAt(allSkulls[mySkull].gameObject.GetComponent<birdController>().orderInList);


            //Run function to place skulls based on the int number skulls on screen
            placementSkulls();
        }
    }

Upvotes: 0

Views: 2423

Answers (2)

Dmitriy Kirakosyan
Dmitriy Kirakosyan

Reputation: 615

Have you tried to remove objects using Remove method? Like this:

birdsOnScreen.Remove (allSkulls[mySkull]);

Your birdsOnScreen.RemoveAt version also looks correct. If you want to use RemoveAll method, you should pass predicate, which returns bool, eg:

birdsOnScreen.RemoveAll (bird => { return bird == allSkulls[mySkull]; } );

I would suggest to use Remove in your case, since you know the object you're removing.

Read more here: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.remove?view=netframework-4.7.2

Also, try to increase your numberSkullOnScreen after you assign its value to the object's property:

allSkulls[mySkull].gameObject.GetComponent<birdController>().orderInList = numberSkullOnScreen;

numberSkullOnScreen++;

This way you won't need to use a placeholder anymore, because your indices will be correct.

Upvotes: 2

dan_wipf
dan_wipf

Reputation: 141

I guess you're looking for a similar function like in an List. You could use this:

public static void RemoveAt<T>(ref T[] arr, int index) {
        for (int a = index; a < arr.Length - 1; a++)
        {
            arr[a] = arr[a + 1];
        }
        Array.Resize(ref arr, arr.Length - 1);
    }

or if you know the Object:

public static T[] RemoveObjectArray<T> (this T[] arr, T ObjToRemove) {  
        int numIdx = System.Array.IndexOf(arr, ObjToRemove);
        if (numIdx == -1) return arr;
        List<T> tmp = new List<T>(arr);
        tmp.RemoveAt(numIdx);
        return tmp.ToArray();
    }

Upvotes: 0

Related Questions