2016-05-26 5 views
2

私のボタンの設定を変更するために使用する私のループの1つでは、インスペクタではなくAddListener関数も使用します。私は0から4までの "i"の範囲を与える5つの項目を持っていますが、 "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(); 
       } 
      } 
     } 
    } 
} 
+0

デバッグし、 'buttons.Length'が5であるかどうか確認してください。 – SeM

+4

「増やす」という言葉が大好きです – Fattie

+0

@JoeBlowは、あなたが言うまで、それに気づいていませんでした。なぜか分かりませんが、これは面白いと思います – Programmer

答えて

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)); 
+0

ありがとう!私が他の提案にコメントしたように、それはJavaを使用してAndroidスタジオでこのように動作するので、ここでは動作しませんでした(おそらくAndroidスタジオに入れた小さなものでしょうか?) とにかく、これをループに追加すると、すべて動作します! 'int rate = i; – sdieters

+0

私はあなたを助けてくれてうれしいです:) –

+0

少し話題がありますが、空白の行を追加するにはどうすればいいですか?(訳注:このようなコメント? – sdieters

1

あなたが閉鎖にアクセスしているので、ループは別のサイクルにあるとiが既に変更されたときforループ内呼び出された関数は、唯一しばらくi値を取得します。

別のこと。あなたが書く場合:

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

コードはi0、1、2、3、4、の値が、iの最後の値があるとforループ内のステートメントを実行します。実際には、のサイクルが終了すると、iがインクリメントされ、チェック「i < 5」が作成され、結果が偽になり、ループが終了します。

+0

[こちらの記事](http://stackoverflow.com/questions/304258/access-to-modified-closure-2)もチェックしてください。 –

+0

ありがとう、これは理にかなっていますが、Android Studioではこのように機能するため、ここではうまくいきません。偉大な説明tho! – sdieters

1
あなた for -loop上 iから

あなたの参照:。

tempButton.GetComponent()onClick.AddListener(()=> OnGivenRate(I));

そして匿名メソッドを使用してOnGivenRate(i)を呼び出します。このコードはfor -loopの範囲外にありますが、変数iにアクセスできます。変数は、() => OnGivenRate(i)匿名メソッドによって参照されるとき、i=5for -loopが終了したとき)を持つ可能性が最も高いでしょう。

+0

感謝します、ありがとう! Android Studio(Javaを使用)で何らかの理由で、OPで好きなように動作します。毎日学んだ新しいこと=) – sdieters

+0

JavaはC#とは異なるクロージャを扱うかもしれません。興味深い質問になるでしょうか。 ;) –

0

コードは冗長です。あなたは既にforループの前に配列としてbuttonを持っていて、次にそれをgameObject(tempButton)に変換してボタンにもう一度....これは参照問題のようです。 forループを以下のコードに置き換えてください。

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

注意差:ボタン[I] .onClick.AddListenerを((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)); 
} 

:0~4を表示する

)=> OnGivenRate(i + 1));

関連する問題