首页 > 解决方案 > 尝试学习如何使用 Theadpool 生成网格数据

问题描述

我想在一个线程上生成网格图块数据并将其存储在某种数组或列表中,这些数组或列表以可预测的方式排序。需要稍后访问它们以进行放置。在下面的脚本中,我想在线程池上执行“void CreatingTile”,然后将其分配给列表或数组中的某个索引。

但是,如果我能看到一个简单的例子,它将线程池上的值添加到线程安全数组或列表中,那么我可以自己解决它。我是 C# 新手,我想学习如何使用线程。已阅读线程池文档,但斐波那契数是我不熟悉的东西,所以我有点难以理解。

编辑:所以我的问题是我如何实现线程并将生成的网格数据存储在数组或列表中?

当前脚本(工作代码)

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;


public class TerrainGenerator : MonoBehaviour
{



    public int xVertices = 20;
    public int zVertices = 20;




    void Start()
    {

        TileData tileData = new TileData(xVertices, zVertices);

        Vector3 positionV3 = new Vector3(0, 0, 0);

        GameObject terrain;
        terrain = new GameObject("Empty");


        MeshRenderer meshRenderer = terrain.AddComponent<MeshRenderer>();
        meshRenderer.sharedMaterial = new Material(Shader.Find("Standard"));
        MeshFilter meshFilter = terrain.AddComponent<MeshFilter>();

        CreatingTile(tileData);

        terrain.transform.position = positionV3;


        meshFilter.mesh = tileData.CreateMesh();

    }


    void CreatingTile(TileData tileData)
    {


        for (int i = 0, z = 0; z <= zVertices; z++)
        {
            for (int x = 0; x <= xVertices; x++)
            {
                float y = Mathf.PerlinNoise(x * .3f, z * .3f) * 2f;
                tileData.vertices[i] = new Vector3(x, y, z);
                i++;

            }

        }


        int vert = 0;
        int tris = 0;
        for (int z = 0; z < zVertices; z++)
        {
            for (int x = 0; x < xVertices; x++)
            {


                tileData.triangles[tris + 0] = vert + 0;
                tileData.triangles[tris + 1] = vert + xVertices + 1;
                tileData.triangles[tris + 2] = vert + 1;
                tileData.triangles[tris + 3] = vert + 1;
                tileData.triangles[tris + 4] = vert + xVertices + 1;
                tileData.triangles[tris + 5] = vert + xVertices + 2;

                vert++;
                tris = tris + 6;


            }
            vert++;
        }


        for (int i = 0, z = 0; z <= zVertices; z++)
        {
            for (int x = 0; x <= xVertices; x++)
            {
                tileData.uvs[i] = new Vector2((float)x / xVertices, (float)z / zVertices);
                i++;
            }
        }

    }

    public class TileData
    {

        public Vector3[] vertices;
        public int[] triangles;
        public Vector2[] uvs;

        public TileData(int xVertices, int zVertices)
        {
            vertices = new Vector3[(xVertices + 1) * (zVertices + 1)];
            uvs = new Vector2[vertices.Length];
            triangles = new int[xVertices * zVertices * 6];

        }

        public Mesh CreateMesh()
        {
            Mesh mesh = new Mesh();
            mesh.vertices = vertices;
            mesh.triangles = triangles;
            mesh.uv = uvs;
            mesh.RecalculateNormals();
            return mesh;
        }


    }


}

将感谢您在此问题上的任何帮助。

标签: c#multithreadingunity3dthreadpool

解决方案


这是一个相当幼稚的解决方案,我能够通过一些阅读和一些帮助来创建它。但它的工作和使用多个线程。

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System.Threading.Tasks;


public class TerrainGenerator : MonoBehaviour
{


    //the max tileMeshSize is close to 250
    public int tileMeshSize = 250;
    public int tileCountX = 10;
    public int tileCountY = 10;
    public int tileSizeScaleModifier = 1;
    public int perlinNoiseScale = 1;
    public int perlinNoiseheigh = 1;
    //Add Biomes 
    //Terrain characteristics for diffrent areas examples hills ,canyon, plains, sanddunes.
    ConcurrentQueue<TileData> tileCQ = new ConcurrentQueue<TileData>();


    void Start()
    {
        

        Task[] tasks = new Task[tileCountX * tileCountY];
        TileData[] tileArrayData = new TileData[tileCountX * tileCountY];
        GameObject[] terrainTiles = new GameObject[tileCountX * tileCountY];

        for (int i = 0,y = 0; y < tileCountY; y++)
        { 
            for (int x = 0; x < tileCountX; x++)
            {
                // Tile mesh size, int index, int X start position, int Z start position 
                tileArrayData[i] = new TileData(tileMeshSize, i, (tileMeshSize * x), (tileMeshSize * y));
                i++;
            }
        }
        for (int i = 0; i < (tileCountX * tileCountY); i++)
        {
            var x = i;
            tasks[x] = Task.Run(() => CreatingTile(tileArrayData[x]));
        }

    }

    void Update()
    {
        if (tileCQ.Count == (tileCountX * tileCountY))
        {
            CreatingMeshFromTileData();
            enabled = false;
        }
     
    }


    //Creates multiple meshes
    void CreatingMeshFromTileData()
    {
        TileData[] sortingArray = new TileData[tileCountX * tileCountY];
        TileData[] tileArrayDataReady = new TileData[tileCountX * tileCountY];
        GameObject[] terrainCollection = new GameObject[tileCountX * tileCountY];
        MeshRenderer[] meshRenderers = new MeshRenderer[tileCountX * tileCountY];
        MeshFilter[] meshFilters = new MeshFilter[tileCountX * tileCountY];
        Vector3[] tilePos = new Vector3[tileCountX * tileCountY];
        for (int i = 0; i < (tileCountX * tileCountY); i++)
        {
            tileCQ.TryDequeue(out tileArrayDataReady[i]);

        }

        Array.Sort(tileArrayDataReady,
        delegate (TileData x, TileData y) { return x.tileIndex.CompareTo(y.tileIndex); });


        for (int y = 0, i = 0; y < tileCountY; y++)
        {
            for (int x = 0; x < tileCountX; x++)
            {

                tilePos[i] = new Vector3((x * tileMeshSize * tileSizeScaleModifier), 0, (y * tileMeshSize * tileSizeScaleModifier));
                terrainCollection[i] = new GameObject("Empty");
                meshRenderers[i] = terrainCollection[i].AddComponent<MeshRenderer>();
                meshFilters[i] = terrainCollection[i].AddComponent<MeshFilter>();
                terrainCollection[i].transform.position = tilePos[i];

                meshFilters[i].mesh = tileArrayDataReady[i].CreateMesh();
                meshRenderers[i].sharedMaterial = new Material(Shader.Find("Standard"));
                i++;
            }
        }        

    }
    //Creating mesh on thread
    void CreatingTile(TileData tileData)
    {
        

        for (int i = 0, z = 0; z <= tileMeshSize; z++)
        {
            for (int x = 0; x <= tileMeshSize; x++)
            {
                float y = Mathf.PerlinNoise((x + tileData.xStartPos) * .3f, (z + tileData.zStartPos) * .3f) * perlinNoiseScale;
                tileData.vertices[i] = new Vector3((x* tileSizeScaleModifier), y, (z* tileSizeScaleModifier));
                i++;
            }
        }


        int vert = 0;
        int tris = 0;
        for (int z = 0; z < tileMeshSize; z++)
        {
            for (int x = 0; x < tileMeshSize; x++)
            {


                tileData.triangles[tris + 0] = vert + 0;
                tileData.triangles[tris + 1] = vert + tileMeshSize + 1;
                tileData.triangles[tris + 2] = vert + 1;
                tileData.triangles[tris + 3] = vert + 1;
                tileData.triangles[tris + 4] = vert + tileMeshSize + 1;
                tileData.triangles[tris + 5] = vert + tileMeshSize + 2;

                vert++;
                tris = tris + 6;

            }
            vert++;
        }


        for (int i = 0, z = 0; z <= tileMeshSize; z++)
        {
            for (int x = 0; x <= tileMeshSize; x++)
            {
                tileData.uvs[i] = new Vector2((float)x / tileMeshSize, (float)z / tileMeshSize);
                i++;
            }
        }
        tileCQ.Enqueue(tileData);
    }

    public class TileData
    {
        public int tileIndex;
        public Vector3[] vertices;
        public int[] triangles;
        public Vector2[] uvs;

        public int xStartPos;
        public int zStartPos;

        public int xEndPos;
        public int zEndPos;

        public TileData(int tileMeshSize, int index, int xSPos, int zSPos)
        {

            xStartPos = xSPos;
            zStartPos = zSPos;

            xEndPos = xSPos + tileMeshSize;
            zEndPos = zSPos + tileMeshSize;


            tileIndex = index;
            vertices = new Vector3[(tileMeshSize + 1) * (tileMeshSize + 1)];
            uvs = new Vector2[vertices.Length];
            triangles = new int[tileMeshSize * tileMeshSize * 6];

        }

        public Mesh CreateMesh()
        {
            Mesh mesh = new Mesh();
            mesh.vertices = vertices;
            mesh.triangles = triangles;
            mesh.uv = uvs;
            mesh.RecalculateNormals();
            return mesh;
        }


    }

}



推荐阅读