方法修改字段是在意外修改参数的同时创建了无限循环

时间:2019-02-07 22:45:15

标签: c# unity3d mesh

我正在创建网格以发送到Unity以应用于要渲染的游戏对象。我有一个方法传递给我的MeshData类实例,该实例包含(顶点,用于创建三角形的顶点索引列表和UV坐标),并将其与MeshData的当前实例合并以生成最终的合并的MeshData,其中包含顶点,三角形两个合并集的索引和UV将作为Mesh对象传递给Unity。

有一个理由,我正在制作一个体素型游戏,我为每个单独的块创建一个网格,然后将所有的块网格合并为一个16x16的“块”块。较大的网格将转换为Unity Mesh对象,并应用于块的GameObject。

运行此方法时,它当前陷入无限循环,似乎正在同时更新this._tris和data._tris,因此它遍历data._tris永远不会结束,因为每次this._tris被添加到它,它也更新data._tris。这是意想不到的行为,我不确定是什么原因导致了这种行为。

这段特定的代码之前运行良好,并且根本没有被修改。但是,当我在另一个类中修改代码时,它开始陷入无限循环,直到遇到内存不足异常。不管传递给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(此)与给定的MeshData(数据)合并,以便当前的MeshData(此)包含两者的元素。

在for循环的“合并(for(int i = 0; i

任何帮助说明其行为方式以及如何避免这种行为的方法?

2 个答案:

答案 0 :(得分:3)

乍一看,我想说您的问题是this._tris = data._tris;,您是在将this._tris指向data._tris。可能想将data._tris的内容添加到this._tris中。

答案 1 :(得分:1)

每当您将List<T>设置为等于另一个List<T>时,就是在建立对列表的引用,而不是将值复制到以下位置:

首先,您创建一个新列表:

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);