/**
*Copyright(C) 2019 by #COMPANY#
*All rights reserved.
*FileName: #SCRIPTFULLNAME#
*Author: #AUTHOR#
*Version: #VERSION#
*UnityVersion:#UNITYVERSION#
*Date: #DATE#
*Description:
*History:
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Text1 : MonoBehaviour
{
public Transform btn;
List<int> list = new List<int> {
1,2,3,4,5
};
// Use this for initialization
void Start()
{
for (int i = 0; i < list.Count; i++)
{
Transform go = Instantiate(btn);
go.transform.position = btn.transform.position + Vector3.down * i*30;
go.gameObject.SetActive(true);
go.GetComponent<Button>().onClick.AddListener(() => {
go.Find("Text").GetComponent<Text>().text = i.ToString();
});
go.SetParent(transform);
}
}
}
这个脚本挂在画布上 创建一个Btn拖到屏幕上方的位置失活
然后我们点击会把I传递给Text
点一轮都是5
因为他一开始帮你注册了事件 但是Btn里面点击激活并没有,在你点的时候循环已经完毕,一直是最大值,在点击的时候就所有Btn只会被传递最大值的i,但是不是从0开始最后不应该是4停止吗,因为for循环底层是
public void For(ref int i,int maxCount,Action func)
{
while (i<maxCount)
{
func();
i++;
}
}
int j = 0;
For(ref j, 4, () => { Debug.Log(j); });
他的i++是最后执行的也就是说最后i++还是执行了。
至于i++和++i for循环结果是没区别的 详细的可以看
https://blog.csdn.net/tsvico/article/details/74943281
/**
*Copyright(C) 2019 by #COMPANY#
*All rights reserved.
*FileName: #SCRIPTFULLNAME#
*Author: #AUTHOR#
*Version: #VERSION#
*UnityVersion:#UNITYVERSION#
*Date: #DATE#
*Description:
*History:
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Text1 : MonoBehaviour
{
public Transform btn;
List<int> list = new List<int> {
1,2,3,4,5
};
// Use this for initialization
void Start()
{
for (int i = 0; i < list.Count; i++)
{
Transform go = Instantiate(btn);
go.transform.position = btn.transform.position + Vector3.down * i*30;
go.gameObject.SetActive(true);
var iCache = i;
go.GetComponent<Button>().onClick.AddListener(() => {
go.Find("Text").GetComponent<Text>().text = iCache.ToString();
});
go.SetParent(transform);
}
}
}
然后如果用临时变量在注册Btn之前存一下呢
正常了,原因可能是每次循环都会New出一个新的iCache,而注册Btn里面的iCache是指向外面每次for循环产生的与他们同一次循环产生的iCache
/**
*Copyright(C) 2019 by #COMPANY#
*All rights reserved.
*FileName: #SCRIPTFULLNAME#
*Author: #AUTHOR#
*Version: #VERSION#
*UnityVersion:#UNITYVERSION#
*Date: #DATE#
*Description:
*History:
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Text1 : MonoBehaviour
{
public Transform btn;
List<int> list = new List<int> {
1,2,3,4,5
};
// Use this for initialization
void Start()
{
int iCache;
for (int i = 0; i < list.Count; i++)
{
Transform go = Instantiate(btn);
go.transform.position = btn.transform.position + Vector3.down * i*30;
go.gameObject.SetActive(true);
iCache = i;
go.GetComponent<Button>().onClick.AddListener(() => {
go.Find("Text").GetComponent<Text>().text = iCache.ToString();
});
go.SetParent(transform);
}
}
}
然后把iCache提取到外部一直覆盖为什么现在都成四了,因为结束时i++执行后就没有再进入循环所以iCache是不会多增加一次
然后用类传入i呢,结果正常应该是传入的时候自动帮你新建了一个临时变量储存起来,类似于之前的 var iCache=i;的操作
using System;
/**
*Copyright(C) 2019 by #COMPANY#
*All rights reserved.
*FileName: #SCRIPTFULLNAME#
*Author: #AUTHOR#
*Version: #VERSION#
*UnityVersion:#UNITYVERSION#
*Date: #DATE#
*Description:
*History:
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Text1 : MonoBehaviour
{
public Transform btn;
List<int> list = new List<int> {
1,2,3,4,5
};
// Use this for initialization
void Start()
{
for (int i = 0; i < list.Count; i++)
{
CreatBtn(i);
}
//for (int k = 0; k < 4; ++k)
//{
// Debug.Log(k);
//}
//int j = 0;
//For(ref j, 4, () => { Debug.Log(j); });
}
public void CreatBtn(int i)
{
Transform go = Instantiate(btn);
go.transform.position = btn.transform.position + Vector3.down * i * 30;
go.gameObject.SetActive(true);
go.GetComponent<Button>().onClick.AddListener(() =>
{
go.Find("Text").GetComponent<Text>().text = i.ToString();
});
go.SetParent(transform);
}
public void For(ref int i, int maxCount, Action func)
{
while (i < maxCount)
{
func();
i++;
}
}
}
因为这个坑让我很多靠顺序生成读表的东西都迷之错误,然后在这里探究下以防以后出现再傻掉了
之后无意间看到其实这个叫闭包陷阱
这个是概念
内层的函数可以引用包含在它外层的函数的变量,即使外层函数的执行已经终止。但该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值。
用临时变量接收相当于每次new出来这个对象
详细的
https://www.cnblogs.com/jiejie_peng/p/3701070.html