[C#] Change all sprites in a list to a specific sprite

Hello Unity Community, I’ve been looking everywhere for an answer to this but I can not find it. basically my betweenTiles grabs all the sprites I need and adds them to its list. Now the problem occurs when I want to change every sprite renderer in betweenTiles to a certain sprite. I’m going to list the code below, and I can provide my full scripts for clarification if needed. Thank you!

Here is what is declared:

csharp* *public List<GameObject> betweenTiles; public Sprite Foundation;* *

And here is the code sample which is called in a void.

csharp* *betweenTiles[i].GetComponent<SpriteRenderer>().sprite = Foundation;* *

This is what the manual says about it, did you follow that procedure for getting the new sprite?

@fire7side , Yes however, from looking at that it seems like it is for changing a single sprite and being able to change it to multiple different sprites. What I am trying to do is change all my sprites in a list, and change them to a sprite I have declared. My current code will only change the first sprite in the list, interestingly.

Code seems fine. You haven’t posted enough to help us diagnose.

Are you looping through your list and changing each sprite?

No, he’s right, I tried it. The only way I could get it to work was by instantiating the sprite for the next one.

    public List<SpriteRenderer> mySprites;
    public Sprite newSprite;
    private void Awake()
    {
        for(int x = 0;x <mySprites.Count;x++)
        {
            mySprites[x].sprite = newSprite;
        }
    }

This worked perfectly fine. All the sprites in the list were changed to the new sprite. Tested in 2017.2 at least.

I think foreach is more visual in this case:

foreach(Sprite sp in mySprite){
 sp.sprite = newSprite;
}

I don’t know what happened because I could only get it to work by instantiating, I tried it about 3 times. Now I opened up the same thing, it works fine with one sprite. Maybe I’m just losing it. It’s just weird though, I only used 2 sprites, but one would change and the other wouldn’t. Then I just instantiated the second one and they both changed. Maybe I was hallucinating or something.

Halloween gremlins most likely.

Yeah. I think something was out of sync because when I tried to save the file with the little save icon, it didn’t save. I had to use save all files. Now I can just click on the icon and it saves.

Hello @Brathnann and @fire7side here are my full scripts for clarification:

This first script detects a click on an existing sprite.

using UnityEngine;
using UnityEngine.EventSystems;

public class TileData : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler
{

    public void OnPointerClick(PointerEventData eventData)
    {
        TileManager tm = GameObject.Find("GameMaster").GetComponent<TileManager>();
        //Accessing the 'AddSprite' function of the 'TileManager' to add the selected object.
        tm.AddTile(eventData.pointerPress.gameObject);
    }

    public void OnPointerDown(PointerEventData eventData)
    {

    }

    public void OnPointerUp(PointerEventData eventData)
    {

    }
}

This second script compiles it, and will then change all the sprites within the list it has created between two points:

using System.Collections.Generic;
using UnityEngine;

public class TileManager : MonoBehaviour
{
    // A list of the two selected tiles
    public List<GameObject> selected;
    // A list of all the tiles
    public List<GameObject> allTiles;
    // A list of the tiles in-between the two selection points
    public List<GameObject> betweenTiles;


    // Other variables
    public Sprite Foundation;
    public List<GameObject> renTiles;
    public bool pickedFoundation = false;

    int i;

    private void Start()
    {
        // Creates an array of every tile and adds it to the 'allTiles' array.
        GameObject[] tile = GameObject.FindGameObjectsWithTag("Tile");

        for (int i = 0; i < tile.Length; i++)
        {
            allTiles.Add(tile[i]);
        }
    }

    // This function that adds the tiles within the selection
    // points to the 'betweenTiles' list.
    public void AddTile(GameObject tile)
    {
        selected.Add(tile);

        // When the selected points is = 2
        if (selected.Count == 2)
        {
            // Calculate the minimum coordinate
            Vector2 minCoord = new Vector2(Mathf.Min(selected[0].transform.localPosition.x, selected[1].transform.localPosition.x), Mathf.Min(selected[0].transform.localPosition.y, selected[1].transform.localPosition.y));
            // Calculate the maximum coordinate
            Vector2 maxCoord = new Vector2(Mathf.Max(selected[0].transform.localPosition.x, selected[1].transform.localPosition.x), Mathf.Max(selected[0].transform.localPosition.y, selected[1].transform.localPosition.y));

            // Loop through each tile in 'allTiles' and see if the tile is = or
            // within the minCoord and maxCoord.
            for (i = 0; i < allTiles.Count; i++)
            {
                if (allTiles[i].transform.localPosition.x >= minCoord.x && allTiles[i].transform.localPosition.x <= maxCoord.x && allTiles[i].transform.localPosition.y >= minCoord.y && allTiles[i].transform.localPosition.y <= maxCoord.y)
                {
                    // Adds to the 'betweenTiles' list
                    betweenTiles.Add(allTiles[i]);
                    Debug.Log("Bet with All: " + betweenTiles.Count);

                   // Problem right below here.
                    betweenTiles[i].GetComponent<SpriteRenderer>().sprite = Foundation;
                    //BuildFoundation();
                }
            }
        }
    }

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

    public void PickFoundation()
    {
      
    }
  
    public void BuildFoundation()
    {
        Debug.Log("Bet with All: " + betweenTiles.Count);
        selected[i].GetComponent<SpriteRenderer>().sprite = Foundation;

        // It only will grab the first sprite
        betweenTiles[i].GetComponent<SpriteRenderer>().sprite = Foundation;
        Debug.Log("It worked");
    }
}
for (i = 0; i < allTiles.Count; i++)
            {
                if (allTiles[i].transform.localPosition.x >= minCoord.x && allTiles[i].transform.localPosition.x <= maxCoord.x && allTiles[i].transform.localPosition.y >= minCoord.y && allTiles[i].transform.localPosition.y <= maxCoord.y)
                {
                    // Adds to the 'betweenTiles' list
                    betweenTiles.Add(allTiles[i]);
                    Debug.Log("Bet with All: " + betweenTiles.Count);
                   // Problem right below here.
                    betweenTiles[i].GetComponent<SpriteRenderer>().sprite = Foundation;
                    //BuildFoundation();
                }
            }

This creates issues. You’re looping through allTiles. Now, let’s say your first tile matches and is added to betweenTiles. Ok, no issues there.

But then if your second tile doesn’t match, it isn’t added. But if your third tile is added, oops. Issue. At this point i =2. but betweenTiles only has 2 entries in it, which means at most i can only be 1 or else you’ll get an error.

So, if you plan to keep it this way, you either should change allTiles[ i ] instead of betweenTiles[ i ] or you need to access the last index of betweenTiles.

betweenTiles[betweenTiles.Count -1]

I was going to write more, but…
Does betweenTiles ever get cleared?
I really think you shouldn’t use the ‘i’ variable there for betweenTiles, as the loop counter may be different than the betweenTiles index.

lol… too slow :slight_smile:

You did add the other point I forgot to add, which is how does betweenTiles get cleared or selected for that fact.

@OP, what you could do is populate betweenTiles first, then after that is done, loop through it and switch all the sprites in it instead of trying to do it all in one pass. Just another possible option.

But some of this depends on your mechanics to if you want to clear the list or not.

@Brathnann - betweenTiles[betweenTiles.Count -1][

This sounds about right, considering that one sprite does change, and an error is thrown. For betweenTiles[betweenTiles.Count -1], is that being replaced with the allTiles.Count? Because betweenTiles is empty at that point?

@Brathnann + @methos5k
Yes I do plan to clear this list. However, I was just looking to do a dry run and make sure I ironed out the selection process.

If your if statement is always false, you’ll never access betweenTiles. But once you add 1 item to it, betweenTiles.Count is 1. Then you need to subtract 1 to get the last index available. (in this example, index 0). Because you are adding to the list before changing it’s last objects sprite, Count will always go up by 1 and you’ll always access the last index of the list.

I’m not sure what you mean by it being replaced by allTiles.Count.

Also since you mentioned clearing the list, you could just as easily loop through betweenTiles in a different method and change the sprites there as per my other suggestion.

1 Like

@Brathnann - yep your solution is definitely the way I am going to do it, as well as clearing it. Thank you for all your help!

Glad ya got it resolved :slight_smile: