【问题标题】:Why does Destroy(GameObject) not work on the second item of a List of Tuples of GameObjects?为什么 Destroy(GameObject) 不适用于 GameObjects 元组列表的第二项?
【发布时间】:2021-12-30 09:42:16
【问题描述】:

在我的应用程序中,用户可以将对象放入场景中。每个对象都有一个背景网格,将由程序计算和添加。因此放置的对象被存储为一个元组列表:

public List<Tuple<GameObject, GameObject>> PlacedObjects;

用户还可以得到一个“清除”按钮来删除对象,如下所示:

foreach (var placedObject in PlacedObjects)
{
    Destroy(placedObject.Item1);
    Destroy(placedObject.Item2);
}
PlacedObjects.Clear();

由于某种原因,Item1 被删除,但 Item2 在场景中仍然可见。我想,一定有一些泄漏或引用阻止了数据被破坏?

无论如何要获得全貌,以下是数据的生成方式。首先,用户可以放置一个项目(从下拉选择中克隆),操作如下:

public void OnPlaceHereButtonPressed()
{
    var clone = Instantiate(currentlySelectedObject);

    clone.GetComponentInChildren<MeshFilter>().mesh = Instantiate(currentlySelectedObject.GetComponentInChildren<MeshFilter>().mesh);
    // Clone the material for each item
    Material cloneMat = new Material(currentlySelectedObject.GetComponentInChildren<Renderer>().material);

    if (currentlySelectedObject.tag.Equals(paramSphere)) // Spheres get random colors after placing
        cloneMat.SetColor("_BaseColor", Random.ColorHSV());
    clone.GetComponentInChildren<Renderer>().material = cloneMat;

    PlacedObjects.Add(new Tuple<GameObject, GameObject>(clone, null));
    SendVirtualObjectsToServer(clone);

    SetCameraBackgroundShader(true);
}

Item2 有点复杂,因为它来自服务器的结果数据。其中大部分只是将传入的数据流转换为网格数据:

// this is done for each of the placed objects after getting the result
if (hasReconstrucedData)
{
    var reconstructed = new GameObject("Reconstructed Mesh " + i.ToString(), typeof(MeshFilter), typeof(MeshRenderer));
    reconstructed.transform.position = new Vector3(0, 0, 0);
    reconstructed.transform.localScale = new Vector3(1, -1, 1);
    reconstructed.isStatic = true;
    Mesh mesh = new Mesh();

    // vertices
    int vertexBufferSize = BitConverter.ToInt32(data, bufferOffset);
    bufferOffset += sizeof(int);
    mesh.vertices = nativeBuffer.GetSubArray(bufferOffset, vertexBufferSize).Reinterpret<Vector3>(vertexBufferSize / 12).ToArray();
    bufferOffset += vertexBufferSize;

    // normals
    int vertexNormalsBufferSize = BitConverter.ToInt32(data, bufferOffset);
    bufferOffset += sizeof(int);
    mesh.normals = nativeBuffer.GetSubArray(bufferOffset, vertexNormalsBufferSize).Reinterpret<Vector3>(vertexNormalsBufferSize / 12).ToArray();
    bufferOffset += vertexNormalsBufferSize;

    // colors
    int vertexColorsBufferSize = BitConverter.ToInt32(data, bufferOffset);
    bufferOffset += sizeof(int);
    mesh.colors = nativeBuffer.GetSubArray(bufferOffset, vertexColorsBufferSize).Reinterpret<Color>(vertexNormalsBufferSize / 16).ToArray();
    bufferOffset += vertexColorsBufferSize;

    // triangles
    int trianglesBufferSize = BitConverter.ToInt32(data, bufferOffset);
    bufferOffset += sizeof(int);
    mesh.triangles = nativeBuffer.GetSubArray(bufferOffset, trianglesBufferSize).Reinterpret<int>(trianglesBufferSize / 4).ToArray();
    bufferOffset += trianglesBufferSize;

    // sh probes
    int reconstructedProbeBufferSize = BitConverter.ToInt32(data, bufferOffset);
    bufferOffset += sizeof(int);

    // set material and probe texture for reconstructed mesh
    Material reconstructedMat = new Material(Shader.Find("Custom/Differential"));

    rows = (int)Math.Ceiling((float)reconstructedProbeBufferSize / (float)cols);
    recbuffer = new NativeArray<float>(cols * rows, Allocator.TempJob);
    // only needed to fill up the complete texture
    recbuffer.CopyFrom(nativeBuffer.GetSubArray(bufferOffset, reconstructedProbeBufferSize).Reinterpret<float>(reconstructedProbeBufferSize / 4));
    bufferOffset += reconstructedProbeBufferSize;
    Texture2D shEnvTexture = new Texture2D(cols, rows, TextureFormat.RFloat, false);
    shEnvTexture.LoadRawTextureData(recbuffer);
    shEnvTexture.filterMode = FilterMode.Point;
    shEnvTexture.wrapMode = TextureWrapMode.Clamp;
    shEnvTexture.Apply(updateMipmaps: false);
    reconstructedMat.SetTexture("_SHTexture", shEnvTexture);


    float[] objectPos = new float[3]
    {
        PlacedObjects[i].Item1.transform.position.x,
        PlacedObjects[i].Item1.transform.position.y,
        PlacedObjects[i].Item1.transform.position.z
    };
    reconstructedMat.SetFloatArray("_ObjectPosition", objectPos);
    reconstructedMat.SetFloat("_ObjectScale",
        (PlacedObjects[i].Item1.transform.localScale * differentialShaderScaleFactor).magnitude);

    reconstructed.GetComponentInChildren<Renderer>().material = reconstructedMat;
    reconstructed.GetComponent<MeshFilter>().mesh = mesh;
    PlacedObjects[i] = Tuple.Create(PlacedObjects[i].Item1, reconstructed);
}

这些是在列表中添加或删除数据的所有位置。为什么Destroy() 函数对第二项不起作用?

【问题讨论】:

  • @rustyBucketBay 描述中说,强烈建议使用Destroy() 而不是DestroyImmediat()。我会测试一下,但是正常的Destroy()不工作的原因我猜可能会导致一些未来的问题?
  • 尽管如此,我还是测试了DestroyImmediat(),但也没有用。也没有将这两个项目分开List&lt;GameObjects&gt;

标签: c# unity3d destroy


【解决方案1】:

终于找到了问题,隐藏的很好。问题不在于destroy函数不起作用,而是每次服务器发送新结果时Item2的创建都会创建一个新Object,而没有清理现有对象。

将相应代码更改为以下内容后:

if (hasReconstrucedData)
{
    if(PlacedObjects[i].Item2 == null)
        PlacedObjects[i] = Tuple.Create(PlacedObjects[i].Item1, new GameObject("Reconstructed Mesh " + i.ToString(), typeof(MeshFilter), typeof(MeshRenderer)));

    PlacedObjects[i].Item2.transform.position = new Vector3(0, 0, 0);
    PlacedObjects[i].Item2.transform.localScale = new Vector3(1, -1, 1);
    PlacedObjects[i].Item2.isStatic = true;
    Mesh mesh = new Mesh();

    // vertices
    int vertexBufferSize = BitConverter.ToInt32(data, bufferOffset);
    bufferOffset += sizeof(int);
    mesh.vertices = nativeBuffer.GetSubArray(bufferOffset, vertexBufferSize).Reinterpret<Vector3>(vertexBufferSize / 12).ToArray();
    bufferOffset += vertexBufferSize;

    // normals
    int vertexNormalsBufferSize = BitConverter.ToInt32(data, bufferOffset);
    bufferOffset += sizeof(int);
    mesh.normals = nativeBuffer.GetSubArray(bufferOffset, vertexNormalsBufferSize).Reinterpret<Vector3>(vertexNormalsBufferSize / 12).ToArray();
    bufferOffset += vertexNormalsBufferSize;

    // colors
    int vertexColorsBufferSize = BitConverter.ToInt32(data, bufferOffset);
    bufferOffset += sizeof(int);
    mesh.colors = nativeBuffer.GetSubArray(bufferOffset, vertexColorsBufferSize).Reinterpret<Color>(vertexNormalsBufferSize / 16).ToArray();
    bufferOffset += vertexColorsBufferSize;

    // triangles
    int trianglesBufferSize = BitConverter.ToInt32(data, bufferOffset);
    bufferOffset += sizeof(int);
    mesh.triangles = nativeBuffer.GetSubArray(bufferOffset, trianglesBufferSize).Reinterpret<int>(trianglesBufferSize / 4).ToArray();
    bufferOffset += trianglesBufferSize;

    // sh probes
    int reconstructedProbeBufferSize = BitConverter.ToInt32(data, bufferOffset);
    bufferOffset += sizeof(int);

    // set material and probe texture for reconstructed mesh
    Material reconstructedMat = new Material(Shader.Find("Custom/Differential"));

    rows = (int)Math.Ceiling((float)reconstructedProbeBufferSize / (float)cols);
    recbuffer = new NativeArray<float>(cols * rows, Allocator.TempJob);
    // only needed to fill up the complete texture
    recbuffer.CopyFrom(nativeBuffer.GetSubArray(bufferOffset, reconstructedProbeBufferSize).Reinterpret<float>(reconstructedProbeBufferSize / 4));
    bufferOffset += reconstructedProbeBufferSize;
    Texture2D shEnvTexture = new Texture2D(cols, rows, TextureFormat.RFloat, false);
    shEnvTexture.LoadRawTextureData(recbuffer);
    shEnvTexture.filterMode = FilterMode.Point;
    shEnvTexture.wrapMode = TextureWrapMode.Clamp;
    shEnvTexture.Apply(updateMipmaps: false);
    reconstructedMat.SetTexture("_SHTexture", shEnvTexture);
    reconstructedMat.SetFloatArray("_SHEnvironmentProbe", lightProbeValues);

    float[] objectPos = new float[3]
    {
        PlacedObjects[i].Item1.transform.position.x,
        PlacedObjects[i].Item1.transform.position.y,
        PlacedObjects[i].Item1.transform.position.z
    };
    reconstructedMat.SetFloatArray("_ObjectPosition", objectPos);
    reconstructedMat.SetFloat("_ObjectScale",
        (PlacedObjects[i].Item1.transform.localScale * differentialShaderScaleFactor).magnitude);

    PlacedObjects[i].Item2.GetComponentInChildren<Renderer>().material = reconstructedMat;
    PlacedObjects[i].Item2.GetComponent<MeshFilter>().mesh = mesh;
}

我猜,在正常情况下,人们会很容易看到多个对象,因为我猜会发生 z-fighting。但是,这里这些对象用于 AR 系统的差分渲染(即将虚拟对象的阴影渲染到现实世界的风景上),因此它们大多是透明的,为了调试,我只是在着色器中将输出颜色更改为红色。

【讨论】:

    猜你喜欢
    • 2021-02-23
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    相关资源
    最近更新 更多