美文网首页
2021-01-17【tips】在循环中动态添加移除元素2

2021-01-17【tips】在循环中动态添加移除元素2

作者: 持刀的要迟到了 | 来源:发表于2021-01-17 02:11 被阅读0次

    之前写的方法,主要是为了在固定帧中,动态添加移除子弹。
    后面由于出了bug,因此做了修改。
    考虑的方面有如下几点:

    1.由于是频繁操作,因此使用数组,并且减少循环遍历
    2.添加元素,往数组的记录【最新】的位置后面依次添加
    这样,当循环执行更新元素的时候,动态添加在后面的元素也能在本帧执行到。
    3.移除元素,不能立即修改数组的元素。使用标记位,在本帧所有元素更新结束后才能移除。
    4.由于标记位的缘故,不需要每帧都移除,可以定时间隔x帧清理一次
    5.移除方式是把数组中某个元素移除,把后面的元素往前移填满数组。优化的方式,只需要遍历一次即可。

    虽然是简单的for循环,但是还是出了各种bug;被逼无奈列举出了所有情况。
    简单的东西,认真做也会有莫名的成就感;

    贴部分代码

        private int m_ActiveFrameBulletCount;
        public Bullet[] m_FrameBulletList;
        private int m_FrameToDeleteCount;
        private int[] m_FrameToDeleteList;
        private int m_MaxFrameBulletCount = 200;
    
        int cleanTurn = 0;
        int cleanFrequency = 10; //更新x轮子弹后销毁一次;要保证不能囤积数量超过数组最大数量
        private void FrameUpdate()
        {
            //Debug.LogError("【BulletManager】更新子弹:" + Client.Ins.NetFrameIndex);
    
            cleanTurn++;
            if (cleanTurn == cleanFrequency)
            {
                cleanTurn = 0;
                m_FrameToDeleteCount = 0;
            }
    
            var count = m_ActiveFrameBulletCount;
    
            for (int i = 0; i < count; ++i)
            {
                var bullet = m_FrameBulletList[i];
    
                if (bullet.Enabled)
                {
                    //Debug.LogError("【BulletManager】更新子弹:" + bullet.preid + "_" + bullet.addid + "_" + Client.Ins.NetFrameIndex);
                    bullet.Update();
                }
    
                if (cleanTurn == 0 && bullet.toDelete)
                {
                    m_FrameToDeleteList[m_FrameToDeleteCount] = i;
                    m_FrameToDeleteCount++;
                }
            }
    
            if (cleanTurn == 0)
            {
                CleanFrameBullets();
            }
        }
    
        private void CleanFrameBullets()
        {
            for (int i = 0; i < m_FrameToDeleteCount; i++)
            {
                int toDeleteIndex = m_FrameToDeleteList[i];             //获得在子弹表中要删除的index
    
                int moveLastIndex = -1;                                 //获得需要往前移 i+1 位的最后一项index
                if (i != (m_FrameToDeleteCount - 1))
                {
                    //当前删除项不是要删除的最后一项
                    //获取下一个要删除的项index,得到它前一个index
                    moveLastIndex = m_FrameToDeleteList[i + 1] - 1;
    
                    //目标:把两个要删除项之间的项,都前移 i+1 个格子
                    //如果两个项之间没有项,即:toDeleteIndex + 1 > moveLastIndex,那跳过本次移动
                    //否则遍历前移 i+1 位
                    int j = toDeleteIndex + 1;
                    if (j > moveLastIndex)
                    {
                        continue;
                    }
                    else
                    {
                        for (; j <= moveLastIndex; j++)
                        {
                            m_FrameBulletList[j - i - 1] = m_FrameBulletList[j];
                        }
                    }
                }
                else
                {
                    //当前删除项就是要删除的最后一项
                    //获取最后一发子弹的index
                    moveLastIndex = m_ActiveFrameBulletCount - 1;
    
                    //目标:把后面所有的项,都前移 i+1 个格子
                    //如果小丑就是我自己,即:toDeleteIndex == moveLastIndex,那么跳过本次移动
                    //否则遍历前移 i+1 位
                    if (toDeleteIndex == moveLastIndex)
                    {
                        continue;
                    }
                    else
                    {
                        for (int j = toDeleteIndex + 1; j <= moveLastIndex; j++)
                        {
                            m_FrameBulletList[j - i - 1] = m_FrameBulletList[j];
                        }
                    }
                }
            }
        }
    

    相关文章

      网友评论

          本文标题:2021-01-17【tips】在循环中动态添加移除元素2

          本文链接:https://www.haomeiwen.com/subject/gmtaaktx.html