Skip to content

Instantly share code, notes, and snippets.

@tsaodown
Last active May 18, 2016 06:30
Show Gist options
  • Save tsaodown/74751c0b291dcd7a3c71fddac7a5ba45 to your computer and use it in GitHub Desktop.
Save tsaodown/74751c0b291dcd7a3c71fddac7a5ba45 to your computer and use it in GitHub Desktop.
DerpCraft - Building a MineCraft Clone in Unity - Voxel Terrain Chunks | Full code available at https://git.io/vrlNO
using UnityEditor;
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;
public Texture2D textureAtlas;
public int seed;
public float noiseScale = 100;
[Range(1, 10)]
public int octaves = 3;
public float lacunarity = 2.5f;
[Range(0, 1)]
public float persistence = 0.5f;
public Vector2 position;
public bool autoUpdate = true;
float[,] heightMap;
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() {
Noise2DGenerator.Noise2DGeneratorFactory.CreatePerlinNoise2DGenerator(
seed, noiseScale, octaves, lacunarity, persistence);
GenerateNoiseMap();
var rend = GetComponent<MeshRenderer>();
rend.material.mainTexture = textureAtlas;
rend.material.shader = Shader.Find("Mobile/Diffuse");
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] =
y > heightMap[x, z] * Height ?
AirBlock.Instance : new GrassBlock();
}
}
}
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++) {
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);
}
void OnValidate() {
if (noiseScale < 1)
noiseScale = 1;
if (octaves < 1)
octaves = 1;
if (lacunarity < 1)
lacunarity = 1;
if (!EditorApplication.isPlayingOrWillChangePlaymode && autoUpdate)
GenerateNoiseMap();
}
void GenerateNoiseMap() {
if (!EditorApplication.isPlayingOrWillChangePlaymode) {
var meshData = new MeshData(false);
meshData.AddVertex(new Vector3(-Size / 2, 0, Size / 2));
meshData.AddVertex(new Vector3(Size / 2, 0, Size / 2));
meshData.AddVertex(new Vector3(Size / 2, 0, -Size / 2));
meshData.AddVertex(new Vector3(-Size / 2, 0, -Size / 2));
meshData.AddQuadTriangles();
meshData.uvs.Add(Vector2Int.up);
meshData.uvs.Add(Vector2Int.one);
meshData.uvs.Add(Vector2Int.right);
meshData.uvs.Add(Vector2Int.zero);
var filter = GetComponent<MeshFilter>();
GetComponent<MeshFilter>().sharedMesh = new Mesh();
filter.sharedMesh.vertices = meshData.verts.ToArray();
filter.sharedMesh.triangles = meshData.tris.ToArray();
filter.sharedMesh.uv = meshData.uvs.ToArray();
Noise2DGenerator.Noise2DGeneratorFactory.CreatePerlinNoise2DGenerator(
seed, noiseScale, octaves, lacunarity, persistence);
}
heightMap = Noise2DGenerator.Instance.GenerateNoise(position,
Vector2Int.one * Size);
if (!EditorApplication.isPlayingOrWillChangePlaymode) {
var pixels = new Color[Size * Size];
for (int y = 0; y < Size; y++) {
for (int x = 0; x < Size; x++) {
pixels[y * Size + x] = Color.Lerp(Color.black,
Color.white, heightMap[x, y]);
}
}
var tex = new Texture2D(Size, Size);
tex.wrapMode = TextureWrapMode.Clamp;
tex.filterMode = FilterMode.Point;
tex.SetPixels(pixels);
tex.Apply();
GetComponent<MeshRenderer>().sharedMaterial =
new Material(Shader.Find("Mobile/Diffuse"));
GetComponent<MeshRenderer>().sharedMaterial.mainTexture = tex;
}
}
}
using UnityEditor;
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;
public Texture2D textureAtlas;
public int seed;
public float noiseScale = 100;
[Range(1, 10)]
public int octaves = 3;
public float lacunarity = 2.5f;
[Range(0, 1)]
public float persistence = 0.5f;
public Vector2 position;
public bool autoUpdate = true;
float[,] heightMap;
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() {
Noise2DGenerator.Noise2DGeneratorFactory.CreatePerlinNoise2DGenerator(
seed, noiseScale, octaves, lacunarity, persistence);
heightMap = Noise2DGenerator.Instance.GenerateNoise(position,
Vector2Int.one * Size);
var rend = GetComponent<MeshRenderer>();
rend.material.mainTexture = textureAtlas;
rend.material.shader = Shader.Find("Mobile/Diffuse");
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] =
y > heightMap[x, z] * Height ?
AirBlock.Instance : new GrassBlock();
}
}
}
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++) {
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