变量

时间:2016-05-26 12:06:32

标签: c# unity3d custom-controls

在我用于更改按钮设置的一个循环中,我还使用AddListener函数而不是Inspector中的函数。我有5个项目,从0-4给出一系列“i”,但是当我通过它应该调用的函数打印“i”时,它总是记录5,无论我按什么按钮,这都是奇怪的,因为“我”从来没有达到5.任何想法?

P.S。我使用CustomEditor在检查器中显示2个按钮“预览布局”和“删除预览”。

代码:

using UnityEngine;
using System.Collections;
using UnityEditor;
using UnityEngine.UI;

public class RateMeManager : MonoBehaviour {

    public GameObject rateMeCanvas;
    public Sprite emptyStar, fullStar, button;
    public float spriteWidth, spriteHeight, spritePadding;

    [HideInInspector]
    public GameObject currentCanvas, tempButton;

    void Start () {
        RemovePreview();
        GenerateStars();
    }

    // Update is called once per frame
    public void GenerateStars () {
        RectTransform myRectTransform;
        if (currentCanvas != null)
        {
            GameObject temp;
            temp = currentCanvas;
            DestroyImmediate(temp);
        }
        currentCanvas = Instantiate(rateMeCanvas, Vector3.zero, Quaternion.identity) as GameObject;
        GameObject subCanvas = currentCanvas.transform.FindChild("subCanvas").gameObject;
        myRectTransform = subCanvas.GetComponent<RectTransform>();
        myRectTransform.sizeDelta = new Vector2((5*spriteWidth) + (4*spritePadding), spriteHeight);
        myRectTransform.anchoredPosition = Vector2.zero;
        Button[] buttons = subCanvas.GetComponentsInChildren<Button>();
        float[] positions = new float[] {((2*spriteWidth)+(2*spritePadding))*-1, ((1 * spriteWidth) + (1 * spritePadding)) * -1 , 0, ((1 * spriteWidth) + (1 * spritePadding)), ((2 * spriteWidth) + (2 * spritePadding))};
        for (int i = 0; i < buttons.Length; i++)
        {
            Debug.Log(i);
            tempButton = buttons[i].gameObject;
            tempButton.GetComponent<Button>().image.sprite = emptyStar;
            myRectTransform = buttons[i].GetComponent<RectTransform>();
            myRectTransform.sizeDelta = new Vector2(spriteWidth, spriteHeight);
            myRectTransform.anchoredPosition = new Vector2(positions[i], 0);
            tempButton.GetComponent<Button>().onClick.AddListener(() => OnGivenRate(i));
        }
    }

    public void RemovePreview()
    {
        DestroyImmediate(currentCanvas);
    }

    private void OnGivenRate(int stars)
    {
        Debug.Log("pressed star: " + stars);
    }

    public class RateMeEditor
    {
        [CustomEditor(typeof(RateMeManager))]
        public class button : Editor
        {
            public override void OnInspectorGUI()
            {
                base.OnInspectorGUI();

                RateMeManager myScript = (RateMeManager)target;
                if (GUILayout.Button("Preview Layout"))
                {
                    myScript.GenerateStars();
                }
                if (GUILayout.Button("Delete Preview"))
                {
                    myScript.RemovePreview();
                }
            }
        }
    }
}

4 个答案:

答案 0 :(得分:5)

您的错误在这里:

tempButton.GetComponent<Button>().onClick.AddListener(() => OnGivenRate(i));

在将变量传递给OnGivenRate或使用闭包之前,必须将i存储在变量中。 因为在循环结束时i等于5.这就是为什么当您点击按钮时i显示5。

所以:

var rate = i;
tempButton.GetComponent<Button>().onClick.AddListener(() => OnGivenRate(rate));

Action<int> OnGivenRateClosure(int rate)
{
    return () => OnGivenRate(rate);
}

tempButton.GetComponent<Button>().onClick.AddListener(OnGivenRateClosure(i));

答案 1 :(得分:1)

你正在访问一个闭包,所以for循环中的被调用函数只在一段时间后得到i值,当循环处于另一个循环时i已被修改。

另一件事。当你写:

for(int i = 0; i < 5; i++)

代码执行for循环内的语句,其中i值为 0,1,2,3,4,,但i的最后一个值是 5 。事实上,当 4 的周期结束时,i会递增,检查&#34; i < 5&#34;如果是,则结果为假,因此循环退出。

答案 2 :(得分:1)

您在i循环中引用for

tempButton.GetComponent()。onClick.AddListener(()=&gt; OnGivenRate(i));

您使用匿名方法呼叫OnGivenRate(i)。这段代码将超出for - 循环的范围,但它可以访问i变量。当() => OnGivenRate(i)匿名方法引用该变量时,该变量很可能具有i=5(退出for - 循环时)。

答案 3 :(得分:0)

您的代码是多余的。你已经在for循环之前将按钮作为数组,然后你将它转换为gameObject(tempButton)然后再转换为一个按钮....这看起来像一个参考问题。只需用下面的代码替换你的for循环。

显示0到4:

for (int i = 0; i < buttons.Length; i++)
{
    buttons[i].image.sprite = emptyStar;
    myRectTransform = buttons[i].GetComponent<RectTransform>();
    myRectTransform.sizeDelta = new Vector2(spriteWidth, spriteHeight);
    myRectTransform.anchoredPosition = new Vector2(positions[i], 0);
    buttons[i].onClick.AddListener(() => OnGivenRate(i));
}

显示1到5:

for (int i = 0; i < buttons.Length; i++)
{
    buttons[i].image.sprite = emptyStar;
    myRectTransform = buttons[i].GetComponent<RectTransform>();
    myRectTransform.sizeDelta = new Vector2(spriteWidth, spriteHeight);
    myRectTransform.anchoredPosition = new Vector2(positions[i], 0);
    buttons[i].onClick.AddListener(() => OnGivenRate(i+1));
}

注意差异:buttons [i] .onClick.AddListener(()=&gt; OnGivenRate( i + 1 ));