Last active
May 17, 2016 22:46
-
-
Save tsaodown/1b51b6bd1936208bfe2076deb3a160a2 to your computer and use it in GitHub Desktop.
DerpCraft - Building a MineCraft Clone in Unity - Chunks | Full code available at https://git.io/vrlT3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Utilities; | |
public class AirBlock : Block { | |
static Block instance; | |
public static Block Instance { | |
get { | |
if (instance == null) { | |
instance = new AirBlock(); | |
} | |
return instance; | |
} | |
} | |
AirBlock() { | |
} | |
protected override bool IsSolid() { | |
return false; | |
} | |
public override MeshData GetBlockData(Chunk chunk, Vector3Int position, | |
MeshData collectedMeshData) { | |
return collectedMeshData; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using Utilities; | |
public class Block { | |
// Enumerator representing the face of the block. | |
public enum FaceDirection { | |
North, | |
// +z | |
South, | |
// -z | |
East, | |
// +x | |
West, | |
// -x | |
Top, | |
// +y | |
Bottom | |
// -y | |
} | |
// Target texture is 16x16 of 16x16 textures. | |
static readonly float tileSize = 0.0625f; | |
protected virtual Vector2Int TextureTilePosition(Chunk chunk, | |
FaceDirection direction) { | |
// Default is a hot pink box. | |
return new Vector2Int(0, 1); | |
} | |
protected virtual bool IsSolid() { | |
return true; | |
} | |
// Calculates the UVs for a given direction on the block. | |
protected virtual Vector2[] FaceUVs(Chunk chunk, FaceDirection direction) { | |
Vector2Int texTile = TextureTilePosition(chunk, direction); | |
var uvs = new Vector2[4]; | |
// top-left, top-right, bottom-right, bottom-left | |
uvs[0] = texTile * tileSize + Vector2.up * tileSize; | |
uvs[1] = texTile * tileSize + Vector2.one * tileSize; | |
uvs[2] = texTile * tileSize + Vector2.right * tileSize; | |
uvs[3] = texTile * tileSize; | |
return uvs; | |
} | |
public virtual MeshData GetBlockData(Chunk chunk, Vector3Int position, | |
MeshData collectedMeshData) { | |
// Go through each face and get the vertices, indices, normals, and UVs. | |
if (!chunk[position + Vector3Int.up].IsSolid()) | |
collectedMeshData = FaceDataTop(chunk, position, collectedMeshData); | |
if (!chunk[position + Vector3Int.down].IsSolid()) | |
collectedMeshData = FaceDataBottom(chunk, position, collectedMeshData); | |
if (!chunk[position + Vector3Int.north].IsSolid()) | |
collectedMeshData = FaceDataNorth(chunk, position, collectedMeshData); | |
if (!chunk[position + Vector3Int.south].IsSolid()) | |
collectedMeshData = FaceDataSouth(chunk, position, collectedMeshData); | |
if (!chunk[position + Vector3Int.east].IsSolid()) | |
collectedMeshData = FaceDataEast(chunk, position, collectedMeshData); | |
if (!chunk[position + Vector3Int.west].IsSolid()) | |
collectedMeshData = FaceDataWest(chunk, position, collectedMeshData); | |
return collectedMeshData; | |
} | |
protected virtual MeshData FaceDataTop(Chunk chunk, Vector3Int position, | |
MeshData collectedMeshData) { | |
// top-left, top-right, bottom-right, bottom-left | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y + 0.5f, position.z + 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y + 0.5f, position.z + 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y + 0.5f, position.z - 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y + 0.5f, position.z - 0.5f)); | |
// Add tris from verts. | |
collectedMeshData.AddQuadTriangles(); | |
// Add UVs for face. | |
collectedMeshData.uvs.AddRange(FaceUVs(chunk, FaceDirection.Top)); | |
return collectedMeshData; | |
} | |
protected virtual MeshData FaceDataBottom(Chunk chunk, Vector3Int position, | |
MeshData collectedMeshData) { | |
// top-left, top-right, bottom-right, bottom-left | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y - 0.5f, position.z - 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y - 0.5f, position.z - 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y - 0.5f, position.z + 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y - 0.5f, position.z + 0.5f)); | |
// Add tris from verts. | |
collectedMeshData.AddQuadTriangles(); | |
// Add UVs for face. | |
collectedMeshData.uvs.AddRange(FaceUVs(chunk, FaceDirection.Bottom)); | |
return collectedMeshData; | |
} | |
protected virtual MeshData FaceDataNorth(Chunk chunk, Vector3Int position, | |
MeshData collectedMeshData) { | |
// top-left, top-right, bottom-right, bottom-left | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y + 0.5f, position.z + 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y + 0.5f, position.z + 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y - 0.5f, position.z + 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y - 0.5f, position.z + 0.5f)); | |
// Add tris from verts. | |
collectedMeshData.AddQuadTriangles(); | |
// Add UVs for face. | |
collectedMeshData.uvs.AddRange(FaceUVs(chunk, FaceDirection.North)); | |
return collectedMeshData; | |
} | |
protected virtual MeshData FaceDataSouth(Chunk chunk, Vector3Int position, | |
MeshData collectedMeshData) { | |
// top-left, top-right, bottom-right, bottom-left | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y + 0.5f, position.z - 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y + 0.5f, position.z - 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y - 0.5f, position.z - 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y - 0.5f, position.z - 0.5f)); | |
// Add tris from verts. | |
collectedMeshData.AddQuadTriangles(); | |
// Add UVs for face. | |
collectedMeshData.uvs.AddRange(FaceUVs(chunk, FaceDirection.South)); | |
return collectedMeshData; | |
} | |
protected virtual MeshData FaceDataEast(Chunk chunk, Vector3Int position, | |
MeshData collectedMeshData) { | |
// top-left, top-right, bottom-right, bottom-left | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y + 0.5f, position.z - 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y + 0.5f, position.z + 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y - 0.5f, position.z + 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x + 0.5f, position.y - 0.5f, position.z - 0.5f)); | |
// Add tris from verts. | |
collectedMeshData.AddQuadTriangles(); | |
// Add UVs for face. | |
collectedMeshData.uvs.AddRange(FaceUVs(chunk, FaceDirection.East)); | |
return collectedMeshData; | |
} | |
protected virtual MeshData FaceDataWest(Chunk chunk, Vector3Int position, | |
MeshData collectedMeshData) { | |
// top-left, top-right, bottom-right, bottom-left | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y + 0.5f, position.z + 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y + 0.5f, position.z - 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y - 0.5f, position.z - 0.5f)); | |
collectedMeshData.AddVertex(new Vector3( | |
position.x - 0.5f, position.y - 0.5f, position.z + 0.5f)); | |
// Add tris from verts. | |
collectedMeshData.AddQuadTriangles(); | |
// Add UVs for face. | |
collectedMeshData.uvs.AddRange(FaceUVs(chunk, FaceDirection.West)); | |
return collectedMeshData; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using Utilities; | |
[RequireComponent(typeof(MeshFilter))] | |
[RequireComponent(typeof(MeshRenderer))] | |
[RequireComponent(typeof(MeshCollider))] | |
public class Chunk : MonoBehaviour { | |
public static int Size = 16; | |
public static int Height = 32; | |
Block[,,] blocks = new Block[Size, Height, Size]; | |
public Block this[int x, int y, int z] { | |
get { | |
if (x < 0 || x >= Size || y < 0 || y >= Height || z < 0 || z >= Size) { | |
return AirBlock.Instance; | |
} | |
return blocks[x, y, z]; | |
} | |
set { | |
if (x < 0 || x >= Size || y < 0 || y >= Height || z < 0 || z >= Size) { | |
return; | |
} | |
blocks[x, y, z] = value; | |
} | |
} | |
public Block this[Vector3Int v] { | |
get { | |
return this[v.x, v.y, v.z]; | |
} | |
set { | |
this[v.x, v.y, v.z] = value; | |
} | |
} | |
void Start() { | |
var meshData = new MeshData(); | |
for (int x = 0; x < Size; x++) { | |
for (int y = 0; y < Height; y++) { | |
for (int z = 0; z < Size; z++) { | |
float rand = Random.value; | |
blocks[x, y, z] = rand > 0.5 ? AirBlock.Instance : new GrassBlock(); | |
} | |
} | |
} | |
for (int x = 0; x < Size; x++) { | |
for (int y = 0; y < Height; y++) { | |
for (int z = 0; z < Size; z++) { | |
meshData = blocks[x, y, z].GetBlockData( | |
this, new Vector3Int(x, y, z), meshData); | |
} | |
} | |
} | |
meshData.RecalculateNormals(); | |
// Set the mesh in the MeshFilter for display. | |
var filter = GetComponent<MeshFilter>(); | |
filter.mesh.vertices = meshData.verts.ToArray(); | |
filter.mesh.triangles = meshData.tris.ToArray(); | |
filter.mesh.normals = meshData.normals.ToArray(); | |
filter.mesh.uv = meshData.uvs.ToArray(); | |
// Set the mesh in the MeshCollider for collision. | |
var coll = GetComponent<MeshCollider>(); | |
var collMesh = new Mesh(); | |
collMesh.vertices = meshData.colliderVerts.ToArray(); | |
collMesh.triangles = meshData.colliderTris.ToArray(); | |
collMesh.normals = meshData.colliderNormals.ToArray(); | |
coll.sharedMesh = collMesh; | |
transform.position = transform.position + | |
Vector3.one * 0.5f - new Vector3(Size / 2, 0, Size / 2); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using Utilities; | |
[RequireComponent(typeof(MeshFilter))] | |
[RequireComponent(typeof(MeshRenderer))] | |
[RequireComponent(typeof(MeshCollider))] | |
public class Chunk : MonoBehaviour { | |
public static int Size = 16; | |
public static int Height = 32; | |
Block[,,] blocks = new Block[Size, Height, Size]; | |
class NullBlock : Block { | |
static Block instance; | |
public static Block Instance { | |
get { | |
if (instance == null) { | |
instance = new NullBlock(); | |
} | |
return instance; | |
} | |
} | |
protected override bool IsSolid() { | |
return false; | |
} | |
} | |
public Block this[int x, int y, int z] { | |
get { | |
if (x < 0 || x >= Size || y < 0 || y >= Height || z < 0 || z >= Size) { | |
return NullBlock.Instance; | |
} | |
return blocks[x, y, z]; | |
} | |
set { | |
if (x < 0 || x >= Size || y < 0 || y >= Height || z < 0 || z >= Size) { | |
return; | |
} | |
blocks[x, y, z] = value; | |
} | |
} | |
public Block this[Vector3Int v] { | |
get { | |
return this[v.x, v.y, v.z]; | |
} | |
set { | |
this[v.x, v.y, v.z] = value; | |
} | |
} | |
void Start() { | |
var meshData = new MeshData(); | |
for (int x = 0; x < Size; x++) { | |
for (int y = 0; y < Height; y++) { | |
for (int z = 0; z < Size; z++) { | |
blocks[x, y, z] = new GrassBlock(); | |
} | |
} | |
} | |
for (int x = 0; x < Size; x++) { | |
for (int y = 0; y < Height; y++) { | |
for (int z = 0; z < Size; z++) { | |
meshData = blocks[x, y, z].GetBlockData( | |
this, new Vector3Int(x, y, z), meshData); | |
} | |
} | |
} | |
meshData.RecalculateNormals(); | |
// Set the mesh in the MeshFilter for display. | |
var filter = GetComponent<MeshFilter>(); | |
filter.mesh.vertices = meshData.verts.ToArray(); | |
filter.mesh.triangles = meshData.tris.ToArray(); | |
filter.mesh.normals = meshData.normals.ToArray(); | |
filter.mesh.uv = meshData.uvs.ToArray(); | |
// Set the mesh in the MeshCollider for collision. | |
var coll = GetComponent<MeshCollider>(); | |
var collMesh = new Mesh(); | |
collMesh.vertices = meshData.colliderVerts.ToArray(); | |
collMesh.triangles = meshData.colliderTris.ToArray(); | |
collMesh.normals = meshData.colliderNormals.ToArray(); | |
coll.sharedMesh = collMesh; | |
transform.position = transform.position + | |
Vector3.one * 0.5f - new Vector3(Size / 2, 0, Size / 2); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment