Search code examples
c#arraysbuttonunity-game-enginetextures

Changing texture of pressed button in array - Unity c#


I have an array of buttons being created and I want to make it so when I click on a button the texture of the button changes. The code I have changes the texture of all the buttons when I click any of the buttons.

Is there a way to code it so that if I click a button then the texture of that buttons changes from texA to texB and the rest of the buttons stay as texA?

public Texture texA;
public Texture texB;
static Vector2[] loc = new Vector2[25]; 
bool visited = false;

void Start () {
    int i = 0;
    while (i < loc.Length){
        loc [i] = new Vector2 (Random.Range (Screen.width * 0.1f, Screen.width * 0.9f), Random.Range(Screen.height * 0.1f, Screen.height * 0.9f));
        i = i + 1;
    }
}

void OnGUI(){
    for (int i = 0; i < loc.Length; i++) {
        if (GUI.Button (new Rect (loc [i].x, loc [i].y, Screen.width * 0.025f, Screen.height * 0.05f), visited ? texA:texB, "")) {
            visited = !visited;
        }
    }
}

Solution

  • There are many ways to do this. You cab use data structure to store info about buttons that are clicked. The easiest method would be to use array.

    Simply make the visited variable into an array and replace everywhere you used it with visited[i]. That's it.

    public Texture texA;
    public Texture texB;
    static Vector2[] loc = new Vector2[25];
    
    bool[] visited = new bool[25];
    
    void Start()
    {
        int i = 0;
        while (i < loc.Length)
        {
            loc[i] = new Vector2(Random.Range(Screen.width * 0.1f, Screen.width * 0.9f), Random.Range(Screen.height * 0.1f, Screen.height * 0.9f));
            i = i + 1;
        }
    }
    
    void OnGUI()
    {
        for (int i = 0; i < loc.Length; i++)
        {
            if (GUI.Button(new Rect(loc[i].x, loc[i].y, Screen.width * 0.025f, Screen.height * 0.05f), visited[i] ? texA : texB, ""))
            {
                visited[i] = !visited[i];
            }
        }
    }
    

    That solves your problem but you need to abandon your current code and use Unity's new UI system with the Button component and its event system. You can learn more about the new UI events here.


    With The New UI:

    public Texture texA;
    public Texture texB;
    
    const int buttonCount = 25;
    
    public GameObject buttonPrefab;
    public Canvas canvasForButtons;
    
    Button[] buttons = new Button[buttonCount];
    static Vector2[] loc = new Vector2[buttonCount];
    bool[] visited = new bool[buttonCount];
    
    
    void Start()
    {
        int i = 0;
        while (i < loc.Length)
        {
            loc[i] = new Vector2(Random.Range(Screen.width * 0.1f, Screen.width * 0.9f), Random.Range(Screen.height * 0.1f, Screen.height * 0.9f));
            i = i + 1;
        }
    
        createButtons();
    }
    
    void createButtons()
    {
        for (int i = 0; i < loc.Length; i++)
        {
            //Instantiate Button
            GameObject tempButtonObj = Instantiate(buttonPrefab, canvasForButtons.transform) as GameObject;
            Button tempButton = tempButtonObj.GetComponent<Button>();
            buttons[i] = tempButton;
    
            //Create rect for position
            Rect buttonRect = new Rect(loc[i].x, loc[i].y, Screen.width * 0.025f, Screen.height * 0.05f);
    
            //Assign Position of each Button
            buttons[i].GetComponent<RectTransform>().position = buttonRect.position;
            //buttons[i].GetComponent<RectTransform>().sizeDelta = buttonRect.size;
    
            //Don't capture local variable
            int tempIndex = i;
            //Add click Event
            buttons[i].onClick.AddListener(() => buttonClickCallBack(tempIndex));
        }
    }
    
    //Called when Button is clicked
    void buttonClickCallBack(int buttonIndex)
    {
        Debug.Log(buttonIndex);
    
        //Get Texture to change
        Texture textureToUse = visited[buttonIndex] ? texA : texB;
    
        //Convert that Texture to Sprite
        Sprite spriteToUse = Sprite.Create((Texture2D)textureToUse, new Rect(0.0f, 0.0f, textureToUse.width,
            textureToUse.height), new Vector2(0.5f, 0.5f), 100.0f);
    
        //Change the Button Image
        buttons[buttonIndex].image.sprite = spriteToUse;
    
        //Flip Image
        visited[buttonIndex] = !visited[buttonIndex];
    }
    

    That's the output:

    enter image description here