IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 笔记记录:Unity C#里的异步执行 -> 正文阅读

[游戏开发]笔记记录:Unity C#里的异步执行

?举例:根据数据Datas,实例化生成每条数据对应的条目Item,以及对应的页码;

(6条Item为一页)(已略去不相关的代码)

相关关键词:Dictionary,List,Destory,Foreach,While,For

    /// <summary>
    /// key:同Datas的key,从0开始
    /// </summary>
    public Dictionary<int, Transform> itemDic = new Dictionary<int, Transform>();

    /// <summary>
    /// key:从0开始
    /// </summary>
    public Dictionary<int, Transform> pageDic = new Dictionary<int, Transform>();


public void Inited()
    {
        if (isInited == false)
        {
            ......

            InitInstantiate(itemDic, itemParent);
            InitInstantiate(pageDic, pageParent);

            ......

            isInited = true;
        }

        Debug.LogFormat("更新后{0}的子物体数:{1}", itemParent.name, itemParent.childCount);
        Debug.LogFormat("更新后{0}的子物体数:{1}", pageParent.name, pageParent.childCount);

    }

//清空字典和父物体下的子物体,然后重新生成指定个数的子物体
private void InitInstantiate(Dictionary<int, Transform> dic, Transform parent)
    {
        Debug.LogFormat("初始{0}子物体个数:{1}", parent.name, parent.childCount);

        //清空dic,parent
        dic.Clear();
        if (parent.childCount > 0)
        {
            for (int i = 0; i < parent.childCount; i++)
            {
                Destroy(parent.GetChild(i).gameObject);
            }
        }

        //更新parent
        switch (parent.name)
        {
            case "ItemContent":
                foreach (var itemData in Datas)
                {
                    AddProjectItem(itemData);
                }
                break;
            case "PageContent":
                int pageNum = (itemCount / 6) + (itemCount % 6 == 0 ? 0 : 1);
                for (int i = 0; i < pageNum; i++)
                {
                    int index = i;
                    AddPageNum(index);
                }
                break;
        }
    }

//生成Item
public void AddProjectItem(KeyValuePair<int, StartProjectData> itemData)
    {
        Transform item = Instantiate(itemPrefab, itemParent);

        ......

        item.gameObject.SetActive(false);
        itemDic.Add(itemData.Key, item);

        itemCount++;
        //Debug.LogFormat("key值为:{0},对应id为:{1}", itemData.Key, itemData.Value.id);
    }

//生成Page
    public void AddPageNum(int curPageNum)
    {
        Transform page = Instantiate(pagePrefab, pageParent);

        ......

        page.gameObject.SetActive(false);
        pageBtnDic.Add(curPageNum, page);
        pageBtnCount++;
    }

public void OnEnable()
    {
        StartCoroutine("OnOpenPanel");
    }

private IEnumerator OnOpenPanel()
    {
        yield return new WaitUntil(() => isInited);

        ......

        //itemIndex[0,itemCount-1],pageBtnIndex[0,pageBtnCount-1]

        ......        

        Debug.LogFormat("{0}的子物体数:{1}", itemParent.name, itemParent.childCount);
        Debug.LogFormat("{0}的子物体数:{1}", pageParent.name, pageParent.childCount);
        yield break;
    }

注:

1、不能在foreach中对List以及Dictionary等进行元素的添加和删除操作;

否则会报错:Collection was modified; enumeration operation may not execute

因为在foreach中删除元素时,每一次删除都会导致集合的大小和元素索引值发生变化,导致在foreach中删除元素会出现异常;

2、Unity里不能使用While循环执行删除,会导致Unity崩溃;

因为在移除的过程中,不会立刻改变childCount的数量,直接导致死循环;

3、可通过for循环,直接使用Destory进行删除子物体,不过记得删除gameObject,而不是transform;

正确:

Destroy(parent.GetChild(i).gameObject);

错误:

Destroy(parent.GetChild(i));

//清空字典和父物体下的子物体
private void DestoryDicChild(Dictionary<int, Transform> dic, Transform parent)
    {
        Debug.LogFormat("初始{0}子物体个数:{1}", parent.name, parent.childCount);

        //清空dic,parent
        dic.Clear();
        if (parent.childCount > 0)
        {
            for (int i = 0; i < parent.childCount; i++)
            {
                Destroy(parent.GetChild(i).gameObject);
            }
        }
    }

4、for循环也并不是同步执行,会存在异步执行的情况

如下,在遍历topBtns,给btn添加对应索引值的方法时,特意申明局部变量num来作为中间值进行赋值操作;

可通过Debug发现,

使用int num=j;ClickTopBtns(num);方法进行赋值索引值;索引值正确赋值;

直接进行ClickTopBtns(j);索引值全部为for循环遍历到最后的 j 值;

public List<Button> topBtns;
public List<Button> leftBtns;

   private void Awake()
    {
        //传的都是正确的Button,但对应的索引值一个有中转,一个直接赋值

        for (int j = 0; j < topBtns.Count; j++)
        {
            int num = j;
            topBtns[num].onClick.AddListener(delegate { ClickTopBtns(topBtns[num],num); });
        }

        for (int i = 0; i < leftBtns.Count; i++)
        {
            int index = i;
            leftBtns[i].onClick.AddListener(delegate { ClickLeftBtn(leftBtns[index],i); });
        }
    }

    private void ClickTopBtns(Button btn,int num)
    {
        Debug.LogFormat("Top:{0}的索引值:{1}", btn.name, num);
    }

    private void ClickLeftBtn(Button leftBtn, int index)
    {
        Debug.LogFormat("Left:{0}的索引值:{1}", leftBtn.name, index);
    }

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-01-01 14:17:32  更:2022-01-01 14:18:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 21:06:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码