반응형
절차적 메시로 N x M 크기의 평면에서 y 값을 적절히 주면 아래와 같이 간단한 지형을 만들 수 있다.
(x, z) 좌표에 대해 y가 적절히 지형스러운 값이 되도록 값을 넣어주면 된다.
이때 사용되는 y값이 noise가 되고 PerlinNoise를 사용하면 간단하다.
이전 코드에서 ny를 추가하고 Mathf.PerlineNoise를 이용하면 된다.
float sx = offset.x - width / 2.0f * cellSize;
float sy = offset.y;
float sz = offset.z + height / 2.0f * cellSize;
int vIdx = 0;
for(int z = 0; z <= height; z++)
{
for(int x = 0; x <= width; x++)
{
float nx, ny, nz;
nx = sx + x * cellSize;
ny = sy + Mathf.PerlinNoise(x * xNoise, z * zNoise) * noiseHeight;
nz = sz - z * cellSize;
vertices[vIdx++] = new Vector3(nx, ny, nz);
}
}
PerlineNoise는 0 ~ 1 사이의 float을 return하므로, 지형의 높이를 변경하기 위해 noiseHeight 만큼 곱한다.
전체 코드는 다음과 같다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class ProceduralPlane : MonoBehaviour
{
Mesh mesh;
Vector3[] vertices;
int[] triangles;
public float cellSize = 1;
public Vector3 offset;
public int width, height;
public float xNoise = 0.5f;
public float zNoise = 0.5f;
public float noiseHeight = 1.0f;
void OnValidate()
{
if (mesh == null) return;
if(offset != Vector3.zero || width > 0 || height > 0 || cellSize > 0)
{
setMeshData();
createProceduralMesh();
}
}
void Start()
{
mesh = GetComponent<MeshFilter>().mesh;
setMeshData();
createProceduralMesh();
}
void setMeshData()
{
vertices = new Vector3[(width + 1) * (height + 1)];
triangles = new int[width * height * 6];
float sx = offset.x - width / 2.0f * cellSize;
float sy = offset.y;
float sz = offset.z + height / 2.0f * cellSize;
int vIdx = 0;
for(int z = 0; z <= height; z++)
{
for(int x = 0; x <= width; x++)
{
float nx, ny, nz;
nx = sx + x * cellSize;
ny = sy + Mathf.PerlinNoise(x * xNoise, z * zNoise) * noiseHeight;
nz = sz - z * cellSize;
vertices[vIdx++] = new Vector3(nx, ny, nz);
}
}
vIdx = 0;
int tIdx = 0;
for (int z = 0; z < height; z++)
{
for (int x = 0; x < width; x++)
{
triangles[tIdx++] = vIdx;
triangles[tIdx++] = vIdx + 1;
triangles[tIdx++] = vIdx + (width + 1);
triangles[tIdx++] = vIdx + (width + 1);
triangles[tIdx++] = vIdx + 1;
triangles[tIdx++] = vIdx + (width + 1) + 1;
vIdx++;
}
vIdx++;
}
}
void createProceduralMesh()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
Destroy(this.GetComponent<MeshCollider>());
this.gameObject.AddComponent<MeshCollider>();
}
}
Unity Plus:
Unity Pro:
Unity 프리미엄 학습:
반응형
댓글