[Object pool] The problem caused by not judging whether two objects are the same

Recently, I dealt with a problem left over from a few versions ago. The code was written by a colleague who left the company. The test found this problem, but it could not be reproduced stably, so it has not been modified. Recently, some players reported that the chance of recurrence is relatively high, so I used the player's account to reproduce this problem.

Phenomenon: Occasional lack of some data during battle. The specific performance is that there are six generals when entering the battle, but it will be displayed that some generals are missing.

After many times of debugging, it was found that there is no problem with entering the combat data, but there is a problem with the display. The displayed place is to take the data in the View code and not modify it.

Code logic:

1. First check whether there is an idle View from the object pool, take it out and use it, if not, create a new one, put the used object in the queue and save it, after using it, put the object back into the object pool according to the queue.

2. Modify the object according to your own needs.

3. Put the used object back into the object pool.

There is no problem with the logic as a whole, but after adding a new battle mode, colleagues added a new queue to store objects in the first step, and in the third step, when putting them back into the object pool, put the same objects in the two queues Back to the object pool. In this way, when fetching data from the object pool next time, it is possible that when two objects are needed, two identical objects will be fetched. When modifying data, the second object will always overwrite the first data causing bugs.

The code logic is roughly as follows:

 public class TestData
    {
        public int TestNum;

        public void Dispose()
        {
            TestNum = 0;
        }
    }
    private List<TestData> m_testDataList1 = new List<TestData>();
    private List<TestData> m_testDataList2 = new List<TestData>();

    private Queue<TestData> m_testDataCacheList = new Queue<TestData>();

    public int TestA = 0;
    public int TestB = 0;

    private TestData ShowTestDataA;
    private TestData ShowTestDataB;
    private void OtherSystem()
    {
        EditorGUILayout.BeginVertical();
        if (GUILayout.Button("获取数据"))
        {
            ShowTestDataA = CreateData();
            //模拟取数据
            for (int i = 0; i < 2; i++)
            {
                ShowTestDataB = CreateData();
            }
             //模拟将数据加了两次
            m_testDataList1.Add(ShowTestDataA);
            m_testDataList1.Add(ShowTestDataB);

            m_testDataList2.Add(ShowTestDataA);
            m_testDataList2.Add(ShowTestDataB);
            if (ShowTestDataA == ShowTestDataB)
            {
                Log.Error("如果取出来两个对象地址相同+++++++++++++++");
            }
        }
        TestA = EditorGUILayout.IntField("TestA:", TestA);
        TestB = EditorGUILayout.IntField("TestB:", TestB);

        if (GUILayout.Button("修改数据"))
        {
            ChangeData(ShowTestDataA, TestA);
            ChangeData(ShowTestDataB,TestB);
        }
        if (GUILayout.Button("回收数据"))
        {
            //模拟将同一个对象添加到对象池。
            for (int i = 0; i < m_testDataList2.Count; i++)
            {
                DisposeData(m_testDataList2[i]);
            }
            for (int i = 0; i < m_testDataList1.Count; i++)
            {
                DisposeData(m_testDataList1[i]);
            }
            m_testDataList1.Clear();
            m_testDataList2.Clear();
        }
        if (GUILayout.Button("清除缓存"))
        {
            m_testDataList1.Clear();
            m_testDataList2.Clear();
            m_testDataCacheList.Clear();
        }
        if (ShowTestDataA != null)
        {
            GUILayout.Label("ShowTestDataA:" + ShowTestDataA.TestNum.ToString());
        }
        if (ShowTestDataB != null)
        {
            GUILayout.Label("ShowTestDataB:" + ShowTestDataB.TestNum.ToString());
        }
        EditorGUILayout.EndVertical();
    }
    private void ChangeData(TestData data,int num)
    {
        if (data == null)
        {
            return;
        }
        data.TestNum = num;
    }
    private void DisposeData(TestData data)
    {
        if (data ==null)
        {
            return;
        }
        data.Dispose();
        if (m_testDataCacheList.Contains(data))
        {
            Log.Error("存进来的对象相同");
        }
        m_testDataCacheList.Enqueue(data);
    }
    private TestData CreateData()
    {
        if (m_testDataCacheList.Count > 0)
        {
            TestData data = m_testDataCacheList.Dequeue();
            return data;
        }
        else
        {
            TestData data = new TestData();
            return data;
        }
    }

Because the object pool may store an object twice, the address of the same object may be assigned to two objects when it is taken out, and there will be problems when modifying the data.

Modification: When putting objects into the object pool, judge whether the objects are the same.

Guess you like

Origin blog.csdn.net/qq_33461689/article/details/124930520