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

2021-01-17  本文已影响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];
                    }
                }
            }
        }
    }
上一篇下一篇

猜你喜欢

热点阅读