创建可编辑体素环境的最佳方法
本文关键字:最佳 方法 环境 编辑 创建 | 更新日期: 2023-09-27 17:56:33
我希望为类似于Minecraft的游戏创建一个动态体素环境。我的主要语言是Java,但是因为我不想完全从头开始编写游戏,所以我决定使用Unity3D。我在这里按照本教程了解了这个主题:http://alexstv.com/index.php/category/voxels
我已经启动了环境并正常工作,并合并了我自己的 FPS 控制器预制件。然而,现在我的下一个目标是缩小块的大小。基本上,我想将每个立方体拆分为另一个 8x8x8 可编辑表面。这将为世界带来更大的灵活性。在 Block 类中,我能够使用 Block.blockSize 让各个块看起来更小。但是,当我这样做时,块之间和块之间都有空格。所以显然我错过了一些东西,但我不确定是什么。我想我会寻找决定此代码中块和块间距的原因。
我也想到也许只是将角色升级为巨人......再次不确定这是否是最好的课程。
这是我的 Block 类:
using UnityEngine;
using System.Collections;
using System;
[Serializable]
public class Block
{
public enum Direction { north, east, south, west, up, down };
public struct Tile { public int x; public int y;}
const float tileSize = 0.25f;
const float blockSize = 0.5f;
const int blockSpace = 1;
public bool changed = true;
//Base block constructor
public Block()
{
}
public virtual MeshData Blockdata
(Chunk chunk, int x, int y, int z, MeshData meshData)
{
meshData.useRenderDataForCol = true;
if (!chunk.GetBlock(x, y + blockSpace, z).IsSolid(Direction.down))
{
meshData = FaceDataUp(chunk, x, y, z, meshData);
}
if (!chunk.GetBlock(x, y - blockSpace, z).IsSolid(Direction.up))
{
meshData = FaceDataDown(chunk, x, y, z, meshData);
}
if (!chunk.GetBlock(x, y, z +blockSpace).IsSolid(Direction.south))
{
meshData = FaceDataNorth(chunk, x, y, z, meshData);
}
if (!chunk.GetBlock(x, y, z - blockSpace).IsSolid(Direction.north))
{
meshData = FaceDataSouth(chunk, x, y, z, meshData);
}
if (!chunk.GetBlock(x + blockSpace, y, z).IsSolid(Direction.west))
{
meshData = FaceDataEast(chunk, x, y, z, meshData);
}
if (!chunk.GetBlock(x - blockSpace, y, z).IsSolid(Direction.east))
{
meshData = FaceDataWest(chunk, x, y, z, meshData);
}
return meshData;
}
protected virtual MeshData FaceDataUp
(Chunk chunk, int x, int y, int z, MeshData meshData)
{
meshData.AddVertex(new Vector3(x - blockSize, y + blockSize, z + blockSize));
meshData.AddVertex(new Vector3(x + blockSize, y + blockSize, z + blockSize));
meshData.AddVertex(new Vector3(x + blockSize, y + blockSize, z - blockSize));
meshData.AddVertex(new Vector3(x - blockSize, y + blockSize, z - blockSize));
meshData.AddQuadTriangles();
meshData.uv.AddRange(FaceUVs(Direction.up));
return meshData;
}
protected virtual MeshData FaceDataDown
(Chunk chunk, int x, int y, int z, MeshData meshData)
{
meshData.AddVertex(new Vector3(x - blockSize, y - blockSize, z - blockSize));
meshData.AddVertex(new Vector3(x + blockSize, y - blockSize, z - blockSize));
meshData.AddVertex(new Vector3(x + blockSize, y - blockSize, z + blockSize));
meshData.AddVertex(new Vector3(x - blockSize, y - blockSize, z + blockSize));
meshData.AddQuadTriangles();
meshData.uv.AddRange(FaceUVs(Direction.down));
return meshData;
}
protected virtual MeshData FaceDataNorth
(Chunk chunk, int x, int y, int z, MeshData meshData)
{
meshData.AddVertex(new Vector3(x + blockSize, y - blockSize, z + blockSize));
meshData.AddVertex(new Vector3(x + blockSize, y + blockSize, z + blockSize));
meshData.AddVertex(new Vector3(x - blockSize, y + blockSize, z + blockSize));
meshData.AddVertex(new Vector3(x - blockSize, y - blockSize, z + blockSize));
meshData.AddQuadTriangles();
meshData.uv.AddRange(FaceUVs(Direction.north));
return meshData;
}
protected virtual MeshData FaceDataEast
(Chunk chunk, int x, int y, int z, MeshData meshData)
{
meshData.AddVertex(new Vector3(x + blockSize, y - blockSize, z - blockSize));
meshData.AddVertex(new Vector3(x + blockSize, y + blockSize, z - blockSize));
meshData.AddVertex(new Vector3(x + blockSize, y + blockSize, z + blockSize));
meshData.AddVertex(new Vector3(x + blockSize, y - blockSize, z + blockSize));
meshData.AddQuadTriangles();
meshData.uv.AddRange(FaceUVs(Direction.east));
return meshData;
}
protected virtual MeshData FaceDataSouth
(Chunk chunk, int x, int y, int z, MeshData meshData)
{
meshData.AddVertex(new Vector3(x - blockSize, y - blockSize, z - blockSize));
meshData.AddVertex(new Vector3(x - blockSize, y + blockSize, z - blockSize));
meshData.AddVertex(new Vector3(x + blockSize, y + blockSize, z - blockSize));
meshData.AddVertex(new Vector3(x + blockSize, y - blockSize, z - blockSize));
meshData.AddQuadTriangles();
meshData.uv.AddRange(FaceUVs(Direction.south));
return meshData;
}
protected virtual MeshData FaceDataWest
(Chunk chunk, int x, int y, int z, MeshData meshData)
{
meshData.AddVertex(new Vector3(x - blockSize, y - blockSize, z + blockSize));
meshData.AddVertex(new Vector3(x - blockSize, y + blockSize, z + blockSize));
meshData.AddVertex(new Vector3(x - blockSize, y + blockSize, z - blockSize));
meshData.AddVertex(new Vector3(x - blockSize, y - blockSize, z - blockSize));
meshData.AddQuadTriangles();
meshData.uv.AddRange(FaceUVs(Direction.west));
return meshData;
}
public virtual Tile TexturePosition(Direction direction)
{
Tile tile = new Tile();
tile.x = 0;
tile.y = 0;
return tile;
}
public virtual Vector2[] FaceUVs(Direction direction)
{
Vector2[] UVs = new Vector2[4];
Tile tilePos = TexturePosition(direction);
UVs[0] = new Vector2(tileSize * tilePos.x + tileSize,
tileSize * tilePos.y);
UVs[1] = new Vector2(tileSize * tilePos.x + tileSize,
tileSize * tilePos.y + tileSize);
UVs[2] = new Vector2(tileSize * tilePos.x,
tileSize * tilePos.y + tileSize);
UVs[3] = new Vector2(tileSize * tilePos.x,
tileSize * tilePos.y);
return UVs;
}
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;
}
}
世界级:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class World : MonoBehaviour {
public Dictionary<WorldPos, Chunk> chunks = new Dictionary<WorldPos, Chunk>();
public GameObject chunkPrefab;
public string worldName = "world";
public void CreateChunk(int x, int y, int z)
{
WorldPos worldPos = new WorldPos(x, y, z);
//Instantiate the chunk at the coordinates using the chunk prefab
GameObject newChunkObject = Instantiate(
chunkPrefab, new Vector3(x, y, z),
Quaternion.Euler(Vector3.zero)
) as GameObject;
Chunk newChunk = newChunkObject.GetComponent<Chunk>();
newChunk.pos = worldPos;
newChunk.world = this;
//Add it to the chunks dictionary with the position as the key
chunks.Add(worldPos, newChunk);
var terrainGen = new TerrainGen();
newChunk = terrainGen.ChunkGen(newChunk);
newChunk.SetBlocksUnmodified();
Serialization.Load(newChunk);
}
public void DestroyChunk(int x, int y, int z)
{
Chunk chunk = null;
if (chunks.TryGetValue(new WorldPos(x, y, z), out chunk))
{
Serialization.SaveChunk(chunk);
Object.Destroy(chunk.gameObject);
chunks.Remove(new WorldPos(x, y, z));
}
}
public Chunk GetChunk(int x, int y, int z)
{
WorldPos pos = new WorldPos();
float multiple = Chunk.chunkSize;
pos.x = Mathf.FloorToInt(x / multiple) * Chunk.chunkSize;
pos.y = Mathf.FloorToInt(y / multiple) * Chunk.chunkSize;
pos.z = Mathf.FloorToInt(z / multiple) * Chunk.chunkSize;
Chunk containerChunk = null;
chunks.TryGetValue(pos, out containerChunk);
return containerChunk;
}
public Block GetBlock(int x, int y, int z)
{
Chunk containerChunk = GetChunk(x, y, z);
if (containerChunk != null)
{
Block block = containerChunk.GetBlock(
x - containerChunk.pos.x,
y - containerChunk.pos.y,
z - containerChunk.pos.z);
return block;
}
else
{
return new BlockAir();
}
}
public void SetBlock(int x, int y, int z, Block block)
{
Chunk chunk = GetChunk(x, y, z);
if (chunk != null)
{
chunk.SetBlock(x - chunk.pos.x, y - chunk.pos.y, z - chunk.pos.z, block);
chunk.update = true;
UpdateIfEqual(x - chunk.pos.x, 0, new WorldPos(x - 1, y, z));
UpdateIfEqual(x - chunk.pos.x, Chunk.chunkSize - 1, new WorldPos(x + 1, y, z));
UpdateIfEqual(y - chunk.pos.y, 0, new WorldPos(x, y - 1, z));
UpdateIfEqual(y - chunk.pos.y, Chunk.chunkSize - 1, new WorldPos(x, y + 1, z));
UpdateIfEqual(z - chunk.pos.z, 0, new WorldPos(x, y, z - 1));
UpdateIfEqual(z - chunk.pos.z, Chunk.chunkSize - 1, new WorldPos(x, y, z + 1));
}
}
void UpdateIfEqual(int value1, int value2, WorldPos pos)
{
if (value1 == value2)
{
Chunk chunk = GetChunk(pos.x, pos.y, pos.z);
if (chunk != null)
chunk.update = true;
}
}
}
如果您需要更多代码或信息,请告诉我!
我也愿意接受有关其他更好的引擎或方法的建议!
我认为您需要使用一些体素资产。例如:https://www.assetstore.unity3d.com/en/#!/content/12689