【问题标题】:Changing texture of pressed button in array - Unity c#更改数组中按下按钮的纹理 - Unity c#
【发布时间】:2017-03-05 00:12:48
【问题描述】:

我创建了一组按钮,我想创建它,所以当我单击按钮时,按钮的纹理会发生变化。当我单击任何按钮时,我拥有的代码会更改所有按钮的纹理。

有没有办法对其进行编码,以便如果我单击一个按钮,那么该按钮的纹理会从 texA 变为 texB,而其余按钮保持为 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;
        }
    }
}

【问题讨论】:

    标签: c# arrays button unity3d textures


    【解决方案1】:

    有很多方法可以做到这一点。您可以使用数据结构来存储有关单击的按钮的信息。最简单的方法是使用数组。

    只需将visited 变量制作成一​​个数组,然后用visited[i] 替换您使用它的所有位置。就是这样。

    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];
            }
        }
    }
    

    这解决了您的问题,但您需要放弃当前代码并使用 Unity 的新 UI 系统和 Button 组件及其事件系统。您可以了解有关新 UI 事件的更多信息here


    新用户界面

    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];
    }
    

    这是输出:

    【讨论】:

    • 第一段代码非常适合我的需要。谢谢你帮助我。
    • 不客气。请考虑我的第二个解决方案,因为它应该用于性能原因。
    【解决方案2】:

    您应该避免使用 OnGUI,正如 Unity 团队自己所说的那样,而应该依赖新的 UI。

    要解决您的问题,您应该这样做:

    • 创建一个画布,并在其上附加脚本CreateButtons
    • 在 Canvas 中创建一个 Button,将脚本 ChangeButtonSprite 附加到它,并在检查器字段中为其提供适当的 A 和 B 精灵。
    • 在 Button 上创建 OnClick 事件,将脚本 ChangeButtonSprite 传递给它,选择 ChangeSprite() 方法,并选择按钮本身的 Image 组件作为参数
    • 将此按钮设为预制件,然后将其从层次结构中删除;
    • 在 Canvas 的 Button Prefab 字段中,放置 Button 预制件
    • 就是这样,您可能想要更改/扩展位置的生成方式、按钮的起始图像等,因为这只是有关如何使用 Unity UI OnClick 嵌入式事件的示例(您甚至可以通过使用onClick.AddListener) 直接从脚本 ofc 中拦截 OnClick 事件

    CreateButtons.cs

    using UnityEngine;
    
    public class CreateButtons : MonoBehaviour {
    
        public GameObject ButtonPrefab;
        public int NumberOfButtons;
    
        void Start () {
            for (int i=0; i<NumberOfButtons; i++) {
                Vector3 buttonPos = new Vector3 (Random.Range(0f, Screen.width), Random.Range(0f, Screen.height), 0);
                GameObject buttonSpawned = Instantiate(ButtonPrefab, buttonPos, Quaternion.identity, gameObject.transform) as GameObject;
            }
        }
    }
    

    ChangeButtonSprite

    using UnityEngine;
    using UnityEngine.UI;
    
    public class ChangeButtonSprite : MonoBehaviour {
    
        public Sprite TexA,TexB;
    
        void Start(){
            GetComponent<Image>().sprite = TexA;
        }
    
        public void ChangeSprite(Image image){
            if (image.sprite == TexA) {
                image.sprite = TexB;
                return;
            }
            image.sprite = TexA;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-09
      • 1970-01-01
      • 2015-06-23
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多