どういうこと?
例えばギャラリー画面で、N×Mのレイアウトでゲームオブジェクトの生成→配置を行いたい場合、同期処理じゃイけてないから、コルーチンで処理したい。
わけあって、以下のような処理のイメージ。
イメージ
private void Start{ StartCoroutine(Initialize()); }
private IEnumerator Initialize() {
for (int j = 0; j < 2; j++) {
for (int i = 0; i < 3; i++) {
hoge.registInstantiate((obj) => {
GameObject go = obj as GameObject;
go.transform.localPosition = new Vector3(i*10f-300f, 100-j*140f, 0f);
...
});
}
}
yield return 0;
hoge.StartInstantiate(); //registInstantiateで登録したアクションを一気に動かす
}
ただこれだと、実際にアクションを動かすタイミングだとiとかjが最後に更新された値(i=3, j=2)として処理されてしまう……困った。
対応策
- iを一時変数に代入し、その値を使用する
- メソッドをかませる
具体的に
前提:Unity5.4.0p3
ケース1:iを一時変数に代入し、その値を使用する
テストコード
private void Start{ StartCoroutine(testFor()); }
private IEnumerator testFor() {
System.Action[] actions = new System.Action[6];
for (int j = 0; j < 2; j++) {
for (int i = 0; i < 3; i++) {
int tmp_i = i;
actions[j*3 + i] = () =>
{
Debug.Log("i = " + i + ", tmp_i = " + tmp_i);
};
}
}
yield return 0;
for(int k=0; k<actions.Length; k++) { actions[k](); }
yield break;
}
結果[NG]
i = 3, tmp_i = 2
i = 3, tmp_i = 2
i = 3, tmp_i = 2
i = 3, tmp_i = 2
i = 3, tmp_i = 2
i = 3, tmp_i = 2
ケース2:iを一時変数に代入し、その値を使用する+メソッドをかませる
テストコード
private void Start{ StartCoroutine(testFor()); }
private IEnumerator testFor() {
System.Action[] actions = new System.Action[6];
for (int j = 0; j < 2; j++) {
for (int i = 0; i < 3; i++) {
int tmp_i = i;
actions[j*3 + i] = log(i, tmp_i);
}
}
yield return 0;
for(int k=0; k<actions.Length; k++) { actions[k](); }
yield break;
}
private System.Action log(int i, int tmp_i) {
System.Action action = () =>
{
Debug.Log("i = " + i + ", tmp_i = " + tmp_i);
};
return action;
}
結果[OK]
i = 0, tmp_i = 0
i = 1, tmp_i = 1
i = 2, tmp_i = 2
i = 0, tmp_i = 0
i = 1, tmp_i = 1
i = 2, tmp_i = 2
ただ、参考記事にあるように、Unity5.5系からだとケース1で解決できることを確認済。
ケース1をUnity5.5.2p4で動かした結果[OK]
i = 3, tmp_i = 0
i = 3, tmp_i = 1
i = 3, tmp_i = 2
i = 3, tmp_i = 0
i = 3, tmp_i = 1
i = 3, tmp_i = 2
参考にさせていただきました記事
-以上-