Unity开发—— C#中存在的异步执行情况的方法和数据结构

25 篇文章 1 订阅
18 篇文章 0 订阅
1、相关关键词

涉及数据结构、方法:Dictionary,List,Destory,Foreach,While,For

2、示例

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

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

    /// <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;
    }
 3、输出

4、详解说明
(1)不能在foreach中对List以及Dictionary等进行元素的添加和删除操作,会报错;

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

Collection was modified; enumeration operation may not execute
(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发现,

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

        2)直接进行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);
    }

         输出

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值