Note: To convert this to HTML Safe text sometimes code gets modified, for example quotes ( " ) are sometimes changed to /"/ for some reason. If there's an error check this first.
PolygonGenerator.cs: Generates the terrain, placed on a gameobject with a mesh filter, a mesh renderer, a mesh collider and the tilesheet as the material.
ColliderExample: Placed on a gameobject, destroys blocks in an area around itself.
RaycastExample: GameObject shoots ray towards a target gameobject and creates a block on every face it hits or destroys every block it hits.
PolygonGenerator.cs: Generates the terrain, placed on a gameobject with a mesh filter, a mesh renderer, a mesh collider and the tilesheet as the material.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PolygonGenerator : MonoBehaviour {
public List<Vector3> newVertices = new List<Vector3>();
public List<int> newTriangles = new List<int>();
public List<Vector2> newUV = new List<Vector2>();
public List<Vector3> colVertices = new List<Vector3>();
public List<int> colTriangles = new List<int>();
private int colCount;
private Mesh mesh;
private MeshCollider col;
private float tUnit = 0.25f;
private Vector2 tStone = new Vector2 (1, 0);
private Vector2 tGrass = new Vector2 (0, 1);
public byte[,] blocks;
private int squareCount;
public bool update=false;
// Use this for initialization
void Start () {
mesh = GetComponent<MeshFilter> ().mesh;
col = GetComponent<MeshCollider> ();
GenTerrain();
BuildMesh();
UpdateMesh();
}
void Update(){
if(update){
BuildMesh();
UpdateMesh();
update=false;
}
}
int NoiseInt (int x, int y, float scale, float mag, float exp){
return (int) (Mathf.Pow ((Mathf.PerlinNoise(x/scale,y/scale)*mag),(exp) ));
}
void GenTerrain(){
blocks=new byte[96,128];
for(int px=0;px<blocks.GetLength(0);px++){
int stone= NoiseInt(px,0, 80,15,1);
stone+= NoiseInt(px,0, 50,30,1);
stone+= NoiseInt(px,0, 10,10,1);
stone+=75;
int dirt = NoiseInt(px,0, 100f,35,1);
dirt+= NoiseInt(px,100, 50,30,1);
dirt+=75;
for(int py=0;py<blocks.GetLength(1);py++){
if(py<stone){
blocks[px, py]=1;
if(NoiseInt(px,py,12,16,1)>10){ //dirt spots
blocks[px,py]=2;
}
if(NoiseInt(px,py*2,16,14,1)>10){ //Caves
blocks[px,py]=0;
}
} else if(py<dirt) {
blocks[px,py]=2;
}
}
}
}
void BuildMesh(){
for(int px=0;px<blocks.GetLength(0);px++){
for(int py=0;py<blocks.GetLength(1);py++){
if(blocks[px,py]!=0){
GenCollider(px,py);
if(blocks[px,py]==1){
GenSquare(px,py,tStone);
} else if(blocks[px,py]==2){
GenSquare(px,py,tGrass);
}
}
}
}
}
byte Block (int x, int y){
if(x==-1 || x==blocks.GetLength(0) || y==-1 || y==blocks.GetLength(1)){
return (byte)1;
}
return blocks[x,y];
}
void GenCollider(int x, int y){
//Top
if(Block(x,y+1)==0){
colVertices.Add( new Vector3 (x , y , 1));
colVertices.Add( new Vector3 (x + 1 , y , 1));
colVertices.Add( new Vector3 (x + 1 , y , 0 ));
colVertices.Add( new Vector3 (x , y , 0 ));
ColliderTriangles();
colCount++;
}
//bot
if(Block(x,y-1)==0){
colVertices.Add( new Vector3 (x , y -1 , 0));
colVertices.Add( new Vector3 (x + 1 , y -1 , 0));
colVertices.Add( new Vector3 (x + 1 , y -1 , 1 ));
colVertices.Add( new Vector3 (x , y -1 , 1 ));
ColliderTriangles();
colCount++;
}
//left
if(Block(x-1,y)==0){
colVertices.Add( new Vector3 (x , y -1 , 1));
colVertices.Add( new Vector3 (x , y , 1));
colVertices.Add( new Vector3 (x , y , 0 ));
colVertices.Add( new Vector3 (x , y -1 , 0 ));
ColliderTriangles();
colCount++;
}
//right
if(Block(x+1,y)==0){
colVertices.Add( new Vector3 (x +1 , y , 1));
colVertices.Add( new Vector3 (x +1 , y -1 , 1));
colVertices.Add( new Vector3 (x +1 , y -1 , 0 ));
colVertices.Add( new Vector3 (x +1 , y , 0 ));
ColliderTriangles();
colCount++;
}
}
void ColliderTriangles(){
colTriangles.Add(colCount*4);
colTriangles.Add((colCount*4)+1);
colTriangles.Add((colCount*4)+3);
colTriangles.Add((colCount*4)+1);
colTriangles.Add((colCount*4)+2);
colTriangles.Add((colCount*4)+3);
}
void GenSquare(int x, int y, Vector2 texture){
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x + 1 , y , 0 ));
newVertices.Add( new Vector3 (x + 1 , y-1 , 0 ));
newVertices.Add( new Vector3 (x , y-1 , 0 ));
newTriangles.Add(squareCount*4);
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+3);
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+2);
newTriangles.Add((squareCount*4)+3);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
squareCount++;
}
void UpdateMesh () {
mesh.Clear ();
mesh.vertices = newVertices.ToArray();
mesh.triangles = newTriangles.ToArray();
mesh.uv = newUV.ToArray();
mesh.Optimize ();
mesh.RecalculateNormals ();
newVertices.Clear();
newTriangles.Clear();
newUV.Clear();
squareCount=0;
Mesh newMesh = new Mesh();
newMesh.vertices = colVertices.ToArray();
newMesh.triangles = colTriangles.ToArray();
col.sharedMesh= newMesh;
colVertices.Clear();
colTriangles.Clear();
colCount=0;
}
}
ColliderExample: Placed on a gameobject, destroys blocks in an area around itself.
using UnityEngine;
using System.Collections;
public class ColliderExample : MonoBehaviour {
public GameObject terrain;
private PolygonGenerator tScript;
public int size=4;
public bool circular=false;
// Use this for initialization
void Start () {
tScript=terrain.GetComponent(\"PolygonGenerator\") as PolygonGenerator;
}
// Update is called once per frame
void Update () {
bool collision=false;
for(int x=0;x<size;x++){
for(int y=0;y<size;y++){
if(circular){
if(Vector2.Distance(new Vector2(x-(size/2),y-(size/2)),Vector2.zero)<=(size/3)){
if(RemoveBlock(x-(size/2),y-(size/2))){
collision=true;
}
}
} else {
if(RemoveBlock(x-(size/2),y-(size/2))){
collision=true;
}
}
}
}
if( collision){
tScript.update=true;
}
}
bool RemoveBlock(float offsetX, float offsetY){
int x =Mathf.RoundToInt(transform.position.x+offsetX);
int y=Mathf.RoundToInt(transform.position.y+1f+offsetY);
if(x<tScript.blocks.GetLength(0) && y<tScript.blocks.GetLength(1) && x>=0 && y>=0){
if(tScript.blocks[x,y]!=0){
tScript.blocks[x,y]=0;
return true;
}
}
return false;
}
}
RaycastExample: GameObject shoots ray towards a target gameobject and creates a block on every face it hits or destroys every block it hits.
using UnityEngine;
using System.Collections;
public class RaycastExample : MonoBehaviour {
public GameObject terrain;
private PolygonGenerator tScript;
public GameObject target;
private LayerMask layerMask = (1 << 0);
// Use this for initialization
void Start () {
tScript=terrain.GetComponent(\"PolygonGenerator\") as PolygonGenerator;
}
// Update is called once per frame
void Update () {
RaycastHit hit;
float distance=Vector3.Distance(transform.position,target.transform.position);
if( Physics.Raycast(transform.position, (target.transform.position - transform.position).normalized, out hit, distance , layerMask)){
Debug.DrawLine(transform.position,hit.point,Color.red);
Vector2 point= new Vector2(hit.point.x, hit.point.y);
point+=(new Vector2(hit.normal.x,hit.normal.y))*0.5f;
Debug.DrawLine(hit.point,new Vector3(point.x,point.y,hit.point.z),Color.magenta);
tScript.blocks[Mathf.RoundToInt(point.x-.5f),Mathf.RoundToInt(point.y+.5f)]=1;
tScript.update=true;
} else {
Debug.DrawLine(transform.position,target.transform.position,Color.blue);
}
}
}
Thanks a lot!
ReplyDeletein the raycast exemple tScript=terrain.GetComponent(\"PolygonGenerator\") as PolygonGenerator;
ReplyDeleteshould the \ around polygongenerator be removed