C# 为什么传递给多线程作业结构的数组充当引用类型?

C# 为什么传递给多线程作业结构的数组充当引用类型?,c#,multithreading,unity3d,jobs,unity3d-terrain,C#,Multithreading,Unity3d,Jobs,Unity3d Terrain,我正在做一个unity项目,涉及基于行进立方体的可变形地形。它的工作原理是在地形块的三维坐标上生成密度地图,并使用该数据创建表示地形表面的网格。它一直在工作,但过程非常缓慢。我试图引入多线程来提高性能,但我遇到了一个让我挠头的问题 当我运行CreateMeshData()并尝试将密度贴图terrainMap传递到MarchCubeJob结构时,它会将其识别为引用类型,而不是值类型。我似乎已经减少了这个错误,但我试图以我知道的每一种方式介绍数据,我被难倒了。我认为传递这样的引用应该创建一个与引用断

我正在做一个unity项目,涉及基于行进立方体的可变形地形。它的工作原理是在地形块的三维坐标上生成密度地图,并使用该数据创建表示地形表面的网格。它一直在工作,但过程非常缓慢。我试图引入多线程来提高性能,但我遇到了一个让我挠头的问题

当我运行CreateMeshData()并尝试将密度贴图terrainMap传递到MarchCubeJob结构时,它会将其识别为引用类型,而不是值类型。我似乎已经减少了这个错误,但我试图以我知道的每一种方式介绍数据,我被难倒了。我认为传递这样的引用应该创建一个与引用断开连接的数据副本,但我的理解肯定有缺陷。我的目标是将每个marchingcube多维数据集传递到一个作业中,并让它们同时运行

我是多线程的新手,所以我可能在这里犯了一些新手错误,如果有人能帮我再看一眼,我将不胜感激。干杯

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst;

public class Chunk
{

    List<Vector3> vertices = new List<Vector3>();
    List<int> triangles = new List<int>();

    public GameObject chunkObject;
    MeshFilter meshFilter;
    MeshCollider meshCollider;
    MeshRenderer meshRenderer;

    Vector3Int chunkPosition;

    public float[,,] terrainMap;
    
    // Job system
    NativeList<Vector3> marchVerts;
    NativeList<Vector3> marchTris;
    MarchCubeJob instanceMarchCube;
    JobHandle instanceJobHandle;


    int width { get { return Terrain_Data.chunkWidth;}}
    int height { get { return Terrain_Data.chunkHeight;}}
    static float terrainSurface { get { return Terrain_Data.terrainSurface;}}

    public Chunk (Vector3Int _position){ // Constructor

        chunkObject = new GameObject();
        chunkObject.name = string.Format("Chunk x{0}, y{1}, z{2}", _position.x, _position.y, _position.z);
        chunkPosition = _position;
        chunkObject.transform.position = chunkPosition;
        meshRenderer = chunkObject.AddComponent<MeshRenderer>();
        meshFilter = chunkObject.AddComponent<MeshFilter>();
        meshCollider = chunkObject.AddComponent<MeshCollider>();
        chunkObject.transform.tag = "Terrain";
        terrainMap = new float[width + 1, height + 1, width + 1]; // Weight of each point
        meshRenderer.material = Resources.Load<Material>("Materials/Terrain");
        
        // Generate chunk
        PopulateTerrainMap();
        CreateMeshData();
    }

    void PopulateTerrainMap(){
        ...
    }

    void CreateMeshData(){

        ClearMeshData();

        vertices = new List<Vector3>();

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                for (int z = 0; z < width; z++) {

                    Debug.Log(x + ", " + y + ", " + z + ", begin");

                    Vector3Int position = new Vector3Int(x, y, z);

                    // Set up memory pointers
                    NativeList<Vector3> marchVerts = new NativeList<Vector3>(Allocator.TempJob);
                    NativeList<int> marchTris = new NativeList<int>(Allocator.TempJob);
                    NativeList<float> mapSample = new NativeList<float>(Allocator.TempJob);

                    // Split marchcube into jobs by cube
                    instanceMarchCube = new MarchCubeJob(){
                        position = position,
                        marchVerts = marchVerts,
                        marchTris = marchTris,
                        mapSample = terrainMap
                    };

                    // Run job for each cube in a chunk
                    instanceJobHandle = instanceMarchCube.Schedule();
                    instanceJobHandle.Complete();

                    // Copy data from job to mesh data
                    //instanceMarchCube.marchVerts.CopyTo(vertices);
                    vertices.AddRange(marchVerts);
                    triangles.AddRange(marchTris);

                    // Dispose of memory pointers
                    marchVerts.Dispose();
                    marchTris.Dispose();
                    mapSample.Dispose();

                    Debug.Log(x + ", " + y + ", " + z + ", end");
                }
            }
        }

        BuildMesh();

    }

    public void PlaceTerrain (Vector3 pos, int radius, float speed){

        ...

        CreateMeshData();

    }

    public void RemoveTerrain (Vector3 pos, int radius, float speed){

        ...

        CreateMeshData();

    }

    void ClearMeshData(){

        vertices.Clear();
        triangles.Clear();

    }

    void BuildMesh(){

        Mesh mesh = new Mesh();
        mesh.vertices = vertices.ToArray();
        mesh.triangles = triangles.ToArray();
        mesh.RecalculateNormals();
        meshFilter.mesh = mesh;
        meshCollider.sharedMesh = mesh;

    }

    private void OnDestroy(){
        marchVerts.Dispose();
        marchTris.Dispose();
    }

}

// Build a cube as a job
[BurstCompile]
public struct MarchCubeJob: IJob{

    static float terrainSurface { get { return Terrain_Data.terrainSurface;}}

    public Vector3Int position;

    public NativeList<Vector3> marchVerts;
    public NativeList<int> marchTris;
    public float[,,] mapSample;

    public void Execute(){

        //Sample terrain values at each corner of cube
        float[] cube = new float[8];
        for (int i = 0; i < 8; i++){

            cube[i] = SampleTerrain(position + Terrain_Data.CornerTable[i]);

        }

        int configIndex = GetCubeConfiguration(cube);

        // If done (-1 means there are no more vertices)
        if (configIndex == 0 || configIndex == 255){
            return;
        }

        int edgeIndex = 0;
        for (int i = 0; i < 5; i++){ // Triangles
            for (int p = 0; p < 3; p++){ // Tri Vertices

                int indice = Terrain_Data.TriangleTable[configIndex, edgeIndex];

                if (indice == -1){
                    return;
                }

                // Get 2 points of edge
                Vector3 vert1 = position + Terrain_Data.CornerTable[Terrain_Data.EdgeIndexes[indice, 0]];
                Vector3 vert2 = position + Terrain_Data.CornerTable[Terrain_Data.EdgeIndexes[indice, 1]];

                Vector3 vertPosition;

                
                // Smooth terrain
                // Sample terrain values at either end of current edge
                float vert1Sample = cube[Terrain_Data.EdgeIndexes[indice, 0]];
                float vert2Sample = cube[Terrain_Data.EdgeIndexes[indice, 1]];

                // Calculate difference between terrain values
                float difference = vert2Sample - vert1Sample;


                if (difference == 0){
                    difference = terrainSurface;
                }
                else{
                    difference = (terrainSurface - vert1Sample) / difference;
                }

                vertPosition = vert1 + ((vert2 - vert1) * difference);



                marchVerts.Add(vertPosition);
                marchTris.Add(marchVerts.Length - 1);
                edgeIndex++;
            }
        }
    }

    static int GetCubeConfiguration(float[] cube){

        int configurationIndex = 0;
        for (int i = 0; i < 8; i++){

            if (cube[i] > terrainSurface){
                configurationIndex |= 1 << i;
            }

        }

        return configurationIndex;

    }

    public float SampleTerrain(Vector3Int point){

        return mapSample[point.x, point.y, point.z];

    }

}
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
使用团结。工作;
使用统一。集合;
使用统一。爆破;
公共类块
{
列表顶点=新列表();
列表三角形=新列表();
公共游戏对象;
网状过滤器;
网格对撞机;
网格渲染器;
向量3int位置;
公共浮动[,]地形图;
//职务制度
民族主义者马尔切维茨;
民族主义者马尔希特里斯;
MarchCubeJob instanceMarchCube;
JobHandle实例JobHandle;
int width{get{return Terrain_Data.chunkWidth;}
int height{get{return Terrain_Data.chunkHeight;}
静态浮点TerraInsureFace{get{return Terrain_Data.TerraInsureFace;}}
公共块(向量3int_位置){//Constructor
chunkObject=新游戏对象();
chunkObject.name=string.Format(“Chunk x{0},y{1},z{2}”,_position.x,_position.y,_position.z);
chunkPosition=_位置;
chunkObject.transform.position=chunkPosition;
meshRenderer=chunkObject.AddComponent();
meshFilter=chunkObject.AddComponent();
meshCollider=chunkObject.AddComponent();
chunkObject.transform.tag=“地形”;
terrainMap=new float[width+1,height+1,width+1];//每个点的权重
meshRenderer.material=Resources.Load(“材质/地形”);
//生成块
PopulateTerrainMap();
CreateMeshData();
}
void PopulateTerrainMap(){
...
}
void CreateMeshData(){
ClearMeshData();
顶点=新列表();
对于(int x=0;x