c# - 尝试学习如何使用 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;
}
}
}
将感谢您在此问题上的任何帮助。
解决方案
这是一个相当幼稚的解决方案,我能够通过一些阅读和一些帮助来创建它。但它的工作和使用多个线程。
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;
}
}
}
推荐阅读
- node.js - 机器人一对一聊天
- go - 有没有其他方法可以在没有 sarama 的代理地址的情况下访问 kafka 集群?
- c++ - C++ 调试:VIsual Studio 中转储文件的堆内存状态
- serilog - 是否可以根据日志记录级别过滤掉 serilog 事件的属性
- excel - 基于段的 Excel 图表标题(无数据透视表)
- git - 我不小心点击了 vscode 中的初始化存储库。现在我不能回去
- r - Shiny 不显示表格
- c# - 冒泡排序问题 C#
- javascript - 如何处理地图函数中的多个参考
- python - 如何将 datetime 列中的 -99 值转换为我选择的日期?