Перемещается ли массив c # List при извлечении элемента? - PullRequest
0 голосов
/ 01 ноября 2018

Я реализовал универсальную систему пула для любого GameObject в Unity. Когда я удаляю GameObject из List <>, я всегда беру последний, чтобы избежать смещения массива, используемого в реализации List. Не нашел ничего полезного в интернете, поэтому попытался понять это сам. Это полезно или я просто делаю бесполезный код?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PoolSystem : MonoBehaviour
{

    public static Dictionary<string, List<GameObject>> pool = new Dictionary<string, List<GameObject>>();

    #region cached
    private static GameObject lastReturned;
    #endregion

    public static GameObject GetElementFromPool(GameObject g)
    {
        if (!pool.ContainsKey(g.name))
        {
            lastReturned = Instantiate(g) as GameObject;
            pool.Add(g.name, new List<GameObject>());
            lastReturned.name = g.name;
            return lastReturned;
        }


        if (pool[g.name].Count == 0)
        {
            lastReturned = Instantiate(g) as GameObject;
            lastReturned.name = g.name;
        }
        else
        {
            lastReturned = pool[g.name][pool[g.name].Count - 1];
            pool[g.name].RemoveAt(pool[g.name].Count - 1);
        }

        return lastReturned;
    }

    public static void AddToPool(GameObject g)
    {

        if (!pool.ContainsKey(g.name))
        {
            pool.Add(g.name, new List<GameObject>());
        }
        pool[g.name].Add(g);

    }

}

Я добавил все предложения в ответах и ​​комментариях, спасибо всем за помощь . Добавив измененный код ниже, возможно, кто-то найдет его полезным

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PoolSystem : MonoBehaviour
{
    public static Dictionary<string, Stack<GameObject>> pool = new Dictionary<string, Stack<GameObject>>();

    #region cached
    private static GameObject lastReturned;
    private static Stack<GameObject> lastUsedStack;
    #endregion

    public static GameObject GetElementFromPool(GameObject g)
    {
        if (pool.TryGetValue(g.name, out lastUsedStack))
        {
            if (pool[g.name].Count == 0)
            {
                lastReturned = Instantiate(g) as GameObject;
                lastReturned.name = g.name;
            }
            else
            {
                lastReturned = pool[g.name].Pop();
            }
        }
        else
        {
            lastReturned = Instantiate(g) as GameObject;
            pool.Add(g.name, new Stack<GameObject>());
            lastReturned.name = g.name;
            return lastReturned;
        }

        return lastReturned;
    }

    public static void AddToPool(GameObject g)
    {
        if (!pool.ContainsKey(g.name))
        {
            pool.Add(g.name, new Stack<GameObject>());
        }
        pool[g.name].Push(g);
    }

}

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Все проиндексированные коллекции имеют это свойство. Если вы удаляете элемент в любой точке, все последующие перемещаются вверх. Это одна из главных причин, почему вы не найдете ConcurrentList[T]. Создание одного просто бросило бы вас головой в условия Индекса. Невозможно, чтобы список был параллельным без учета использования кода.

Коллекции Кейда (Dictionary[int, GameObject]) не имеют этого недостатка. Обратите внимание, что есть специальные коллекции для определенных операций. Очередь (первым пришел, первым вышел) и стек (первым пришел, последний вышел). Это может быть более подходящим для вашего сценария.

0 голосов
/ 01 ноября 2018

Чтение Документация

Когда вы вызываете RemoveAt для удаления элемента, оставшиеся элементы в списке перенумеровываются для замены удаленного элемента. Например, если вы удалите элемент с индексом 3, элемент с индексом 4 будет перемещен в позицию 3. Кроме того, количество элементов в списке (как представлено свойством Count) уменьшается на 1.

Этот метод является операцией O (n), где n равно (Count - index).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...