Unity Увеличивает размер списка во время выполнения - PullRequest
0 голосов
/ 13 июля 2020

Это сводит меня с ума. Я пытаюсь просто увеличить размер списка с помощью скрипта.

Я попытался установить размер списка, прежде чем ссылаться на него, сказав

List<int> listName = new List<int>(20);

, но это не работает . Ничего не произошло. Даже в Awake или Start.

Я попытался увеличить размер, сделав это в al oop:

foreach(var line in table)
{
    int tempInt = new int();
    intList.Add(tempInt);
}

это работает, и размер моего списка увеличивается.

Но моя проблема в том, что ПОСЛЕ увеличения размера этого списка я не могу ссылаться ни на один из элементов, созданных во время выполнения. Например, я не могу сослаться на intList [2].

Я пробовал делать это в обычном void и IEnumerator, но ни один из них не работает.

Все, что я хочу здесь сделать, это увеличить свой список размер по мере необходимости, а затем ссылка на эти элементы списка по мере необходимости ....

Как бы просто эта проблема не звучала, это, честно говоря, самая раздражающая проблема кодирования, с которой я когда-либо сталкивался в Unity.

ПОЖАЛУЙСТА, помогите.

РЕДАКТИРОВАТЬ: Вот код, который я использую ...

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

public class DataExtraction : MonoBehaviour
{
    [Header("Tables")]
    public List<DataItem> tables; // The main table that needs to be populated
    
    [Header("Extraction Variables")]
    public string webAddress = "https://old.winningform.co.za/ECP/2F200717_1.htm"; // URL that the data will be extracted from 
    //(note this URL will be deleted after 17 July 2020 
    
    public List<string> rawDataSplit; // Place to store each line of the raw data
    public int currentTable = 0;
    
    void Awake()
    {
        DataItem newDataItem = new DataItem();
        tables.Add(newDataItem);
    }
    
    void Start()
    {
        if(webAddress != "")
        {
            StartCoroutine(GetRequest(webAddress));
        }
    }
    
    IEnumerator GetRequest(string uri)
    {
        using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
        {
            yield return webRequest.SendWebRequest();

            string[] pages = uri.Split('/');
            int page = pages.Length - 1;

            if (webRequest.isNetworkError)
            {
                Debug.Log(pages[page] + ": Error: " + webRequest.error);
            }
            else
            {
                string rawData = webRequest.downloadHandler.text;
                
                // Splitting the data into lines and assigning it to rawDataSplit list
                var linesInText = rawData.Split('\n'); 
                
                foreach(var line in linesInText)
                {
                    if(line != "")
                    {
                        rawDataSplit.Add(line);
                    }
                }
                //
                
                // Data has been split and assigned to the rawDataSplit list
                AssignTableData();
                //
            }
        }
    }
    
    void AssignTableData()
    {
        foreach(var line in rawDataSplit)
        {
            // When the script finds this line it indicates that a new Table has been found in the text
            // This will create a new table in the list and increase the currentTable number by 1 (to be used as an index number)
            // The following lines of data after that will then be added to THAT table until the next table is found...
            // A new table will again be created and the information will be added there instead.
            if(line.Contains("<table border"))
            {
                currentTable++;
                
                DataItem newDataItem = new DataItem();
                tables.Add(newDataItem);
                
                tables[currentTable].rawTableData.Add(line);
            }
            else // If not found automatically add information into Table index 0 (created at Awake)
            {
                print(tables.Count.ToString());
                tables[currentTable].rawTableData.Add(line);
            }
        }
    }
}

[System.Serializable]
public class DataItem
{
    public List<string> rawTableData;
}

ОШИБКА:

NullReferenceException: Object reference not set to an instance of an object
DataExtraction.AssignTableData () (at Assets/DataExtraction.cs:89)
DataExtraction+<GetRequest>d__6.MoveNext () (at Assets/DataExtraction.cs:63)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)

Ответы [ 3 ]

0 голосов
/ 13 июля 2020

Параметр конструктора - это начальная емкость внутреннего массива, используемого списком. Начальный элемент Count всегда равен 0. Вы можете получить доступ только к индексам в диапазоне [0 .. Count - 1] (включая Count - 1). Первоначальная емкость не меняет этого.

Вы можете изменить видимый размер, заданный как Count, только добавляя или удаляя элементы с помощью Add, AddRange, Clear, Insert, InsertRange и один из 4 Remove вариантов.

Хорошая начальная емкость способствует минимизации количества требуемых операций изменения размера внутреннего массива, но в противном случае не оказывает видимого эффекта.

Следовательно, если у вас есть индекс, который может превышать Count - 1, вы должны получить элементы с

if (i < list.Count) {
    int item = list[i];
    Process(item);
}

Если вам нужен фиксированный размер коллекции, используйте вместо него массив:

const int N = 20;
int[] arrayName = new int[N];

Теперь вы можете получить доступ ко всем индексам в диапазоне [0 .. N - 1] (включая N - 1).

Если все это не работает, возможно, список, к которому вы пытаетесь получить доступ, не тот, который вы инициализировали. Если это поле класса, возможно, оно находится в другом объекте того же типа класса. Если это локальная переменная (переменная, объявленная внутри метода), то она будет существовать только во время одного вызова этого метода. (Я не говорю здесь о счетчиках и async / await.)

См .: Класс списка (Microsoft Docs)

0 голосов
/ 13 июля 2020

Ваш вопрос вообще не имеет ничего общего с подсчетом или индексами списка!

Фактическая проблема : вы никогда не инициализируете список rawTableData, поэтому он равен null, когда пытаясь добавить к нему элементы в

tables[currentTable].rawTableData.Add(line);

Вы должны просто объявить его как

[System.Serializable]
public class DataItem
{
    public List<string> rawTableData = new List<string>();
}
0 голосов
/ 13 июля 2020

Списки должны автоматически увеличиваться в размере. Массивов нет. Вы не должны требовать для установки размера списка, но идея состоит в том, что это поможет с производительностью.

Код, который вы упомянули:

foreach(var line in table)
{
    int tempInt = new int();
    intList.Add(tempInt);
}

должен эффективно добавить в список 20 int по умолчанию. Значит, все они должны быть установлены на 0. Вы как-то переопределяете свои значения? Как вы устанавливаете свои фактические ценности? Можете ли вы предоставить более подробную информацию о том, как вы добавляете значения в список, а затем как вы их используете?

Если вы устанавливаете значения в редакторе, в инспекторе, тогда вы следует быть осторожным, чтобы не повторно инициализировать список, так как это уничтожит все, что исходит из редактора. Как вы храните этот список? Неясно, используете ли вы publi c или частное поле, или свойство, или что-то, что создается внутри метода.

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