Почему добавление списка <T>также добавляется в другой список <T>? - PullRequest
0 голосов
/ 08 февраля 2019

Я создаю меши для отправки в Unity для применения к игровым объектам, которые будут отображаться.У меня есть метод, который передает экземпляр моего класса MeshData, содержащий (Vertices, список индексов вершин для создания треугольников и UV-координат), и объединяет его с текущим экземпляром MeshData для создания окончательного объединенного MeshData, содержащего Vertices, TriangleИндексы и UVs обоих объединенных наборов для передачи в качестве объекта Mesh в Unity.

Исходя из этого, я делаю игру типа вокселей и создаю сетку для каждого отдельного блока, а затем объединяю все сетки блоков в 16x16 "кусочек" блоков.Эта более крупная сетка преобразуется в объект Unity Mesh и применяется к GameObject для чанка.

Когда этот метод запущен, он в настоящее время застревает в бесконечном цикле, который, похоже, обновляет this._tris и данные._tris в то же время, так как он проходит через data._tris, он никогда не достигает конца, потому что каждый раз, когда this._tris добавляется, он также обновляет data._tris.Это непреднамеренное поведение, и я не уверен, что заставляет его так себя вести.

Этот конкретный фрагмент кода ранее работал нормально и не был изменен вообще.Но когда я изменил код в другом классе, он начал застрять в бесконечном цикле, пока не достигнет исключения Out of Memory.Независимо от того, что передается в Merge (), оно никогда не должно так застрять.

// Class for creating MeshData
public class MeshData
{
    // MeshData objects
    private List<Vector3> _verts = new List<Vector3>();
    private List<int> _tris = new List<int>();
    private List<Vector2> _uvs = new List<Vector2>();

    // MeshData constructor with parameters
    public MeshData(List<Vector3> v, List<int> i, Vector2[] u)
    {
        this._verts = v;
        this._tris = i;
        this._uvs = new List<Vector2>(u);
    }

    // MeshData default constructor
    public MeshData()
    {

    }

    // Merge Mesh Data
    public void Merge(MeshData data)
    {
        // if data is empty, don't do anything
        if(data._verts.Count <= 0)
        {
            return;
        }
        // if current meshdata is empty, just set it to be the new data set
        if(this._verts.Count <= 0)
        {
            this._verts = data._verts;
            this._tris = data._tris;
            this._uvs = data._uvs;
            return;
        }
        // if neither case above is true, merge the two data sets
        int count = this._verts.Count;
        this._verts.AddRange(data._verts);
        for(int i = 0; i < data._tris.Count; i++)
        {
            this._tris.Add(data._tris[i] + count);
        }
        this._uvs.AddRange(data._uvs);
    }
}

Метод Merge должен объединять текущие MeshData (this) с заданными MeshData (data) так, чтобытекущая MeshData (this) содержит элементы обоих.

В методе Merge в цикле for "for (int i = 0; i Любая помощь в том, почему он так себя ведет и как избежать такого поведения?

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Всякий раз, когда вы устанавливаете List<T> равным другому List<T> с помощью оператора =, вы устанавливаете ссылку на список, а не копируете значения через:


В вашемНапример, вы сначала создаете новый List<int>:

private List<int> _tris = new List<int>();

Но затем в конструкторе вы устанавливаете _tris для ссылки на другой список:

this._tris = i;

Старый new List<int>() на вас больше не ссылаются, и она будет собираться мусором (в конце концов).Эта перезапись может также произойти в вашем методе Merge со строкой:

this._tris = data._tris;

Если вы хотите, чтобы this._tris - ссылались на другой список (и, следовательно, добавляли кодин добавляет к другому), вы используете =.Если вместо этого вы хотите скопировать все значения в , вы используете AddRange, как вы делаете с _verts:

this._tris.AddRange(data._tris);
0 голосов
/ 08 февраля 2019

На первый взгляд, я бы сказал, что ваша проблема this._tris = data._tris;, вы указываете this._tris на data._tris.Возможно, вместо этого нужно добавить содержимое data._tris в this._tris.

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