Pou*_*nte 5 c# multithreading procedural-generation unity-game-engine minecraft
我正在研究体素地形生成器。一切都很好,我有生物群落,街区等。
让我感到震惊的是我团结一致的项目速度。如果我在主线程上运行所有程序,则只能加载并渲染1到2个块,而不会降至70fps以下。这主要是因为块中的每个块都必须检查其邻居以定义其块侧可见性。一个块有6个邻居,一个块有16个块。这很快就进行了很多检查。
我读过《我的世界》是单线程的,但我很难相信,因为它的块加载速度非常快并且没有fps下降。
我的解决方案是在另一个线程上运行块的块邻居的检查。这将大大提高我的fps和我的块加载速度。这是正确的方法吗?我不想使用线程,因为我的代码未优化。这就像将灰尘推到地毯下面。
谢谢阅读
编辑:检查邻居的代码
//Block provides its mesh information
//Check for solidity of adjacent blocks
public virtual MeshData CreateBlockData(Chunk chunk, int x, int y, int z, MeshData meshData)
{
//Set this to true to turn on collider creation shaped like the chunks
meshData.useRenderDataForCol = true;
if (!chunk.GetBlock(x, y + 1, z).IsSolid(Direction.down))
{
meshData = FaceDataUp(chunk, x, y, z, meshData);
}
if (!chunk.GetBlock(x, y - 1, z).IsSolid(Direction.up))
{
meshData = FaceDataDown(chunk, x, y, z, meshData);
}
if (!chunk.GetBlock(x, y, z + 1).IsSolid(Direction.south))
{
meshData = FaceDataNorth(chunk, x, y, z, meshData);
}
if (!chunk.GetBlock(x, y, z - 1).IsSolid(Direction.north))
{
meshData = FaceDataSouth(chunk, x, y, z, meshData);
}
if (!chunk.GetBlock(x + 1, y, z).IsSolid(Direction.west))
{
meshData = FaceDataEast(chunk, x, y, z, meshData);
}
if (!chunk.GetBlock(x - 1, y, z).IsSolid(Direction.east))
{
meshData = FaceDataWest(chunk, x, y, z, meshData);
}
return meshData;
}
//The center of block is the origin
protected virtual MeshData FaceDataUp(Chunk chunk, int x, int y, int z, MeshData meshData)
{
meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z + 0.5f));
meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f));
meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z - 0.5f));
meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z - 0.5f));
meshData.AddQuadTriangles();
//Adds UVs range (0 to 3) to uv list
meshData.uv.AddRange(FaceUVs(Direction.up));
return meshData;
}
Run Code Online (Sandbox Code Playgroud)
因此,每个16x16x16块的块都有4096个块来运行此功能。
创建块的代码只是包含以下内容的三元组for循环:
static void GeneratePlainBiome(Chunk chunk, int x, int y, int z, FastNoise noise)
{
int stoneHeight = GetNoise2D(noise, x, z, 0, 50);
int chunkX = (int)chunk.transform.position.x;
int chunkY = (int)chunk.transform.position.y;
int chunkZ = (int)chunk.transform.position.z;
if(y == 0)
{
chunk.SetBlock(x - chunkX, y - chunkY, z - chunkZ, new BlockSnow());
}
else if(stoneHeight > y)
{
chunk.SetBlock(x - chunkX, y - chunkY, z - chunkZ, new BlockEarth());
}
else if(stoneHeight == y)
{
chunk.SetBlock(x - chunkX, y - chunkY, z - chunkZ, new BlockGrass());
}
else
{
chunk.SetBlock(x - chunkX, y - chunkY, z - chunkZ, new BlockAir());
}
}
Run Code Online (Sandbox Code Playgroud)
填充大块后,我使用以下函数渲染网格:
//Sends the calculated mesh information to the mesh and collision components
void RenderMesh(MeshData meshData)
{
//Mesh construction
filter.mesh.Clear();
filter.mesh.vertices = meshData.vertices.ToArray();
filter.mesh.triangles = meshData.triangles.ToArray();
//Uv mapping
filter.mesh.uv = meshData.uv.ToArray();
filter.mesh.RecalculateNormals();
//Collision component creation
coll.sharedMesh = null;
Mesh meshColl = new Mesh();
meshColl.vertices = meshData.colVertices.ToArray();
meshColl.triangles = meshData.colTriangles.ToArray();
meshColl.RecalculateNormals();
coll.sharedMesh = meshColl;
}
Run Code Online (Sandbox Code Playgroud)
因此,为了恢复,我正在检查块的16x16x16块,以了解如何基于邻居渲染块网格。完成该功能后,我可以选择渲染块。我这样做是为了让播放器周围有16x16x16的块。(即使我在一个帧上做一个大块,我也会得到非常差的fps下降。)
编辑2:
对于来自块脚本的chunk.SetBlock()和chunk.GetBlock():
public void SetBlock(int x, int y, int z, Block block)
{
if (InRange(x) && InRange(y) && InRange(z))
{
blocks[x, y, z] = block;
}
else
{
LoadBiomes.SetBlock((int)transform.position.x + x, (int)transform.position.y + y, (int)transform.position.z + z, block);
}
}
public Block GetBlock(int x, int y, int z)
{
if(InRange(x) && InRange(y) && InRange(z))
{
Block block = blocks[x, y, z];
return block;
}
else
{
//return new BlockAir();
int xPos = (int)transform.position.x + x;
int yPos = (int)transform.position.y + y;
int zPos = (int)transform.position.z + z;
Block blockToReturn = LoadBiomes.GetBlock(xPos,yPos,zPos);
return blockToReturn;
}
}
//This work since the values passed to the function are block position - chunk position
public static bool InRange(int index)
{
if (index < 0 || index >= CHUNK_SIZE)
return false;
return true;
}
Run Code Online (Sandbox Code Playgroud)
块脚本中的isSolid(如果游戏仅包含多维数据集,则不是很重要
//Every face is solid for a cube
public virtual bool IsSolid(Direction direction)
{
switch (direction)
{
case Direction.north:
return true;
case Direction.east:
return true;
case Direction.south:
return true;
case Direction.west:
return true;
case Direction.up:
return true;
case Direction.down:
return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
以及来自探查器的图像(不确定是否是所要求的)
我不是专家,但据我所知,unity 3d 使用多边形,而不是体素引擎。体素引擎是不同的。
这种差异的直接后果是,多边形可以有效地表示具有大量空白或均匀填充空间的简单 3D 结构,而体素则擅长表示非均匀填充的规则采样空间。
https://en.wikipedia.org/wiki/Voxel
技术细节请参见:
一些体素引擎所做的是使用大数组,然后使用它们来确定视野中的内容和视野之外的内容。这与从 Quake 开始的经典 3D 多边形处理方式非常不同。著名的体素游戏包括《科曼奇》系列、《Outcast》……以及现在的《我的世界》。
归档时间: |
|
查看次数: |
189 次 |
最近记录: |