반응형
반응형
이번 글에서는 맵 에디터 지형 색칠을 구현해 보겠습니다
먼저 터레인 레이어 2개를 추가해 주세요
터레인 레이어는 왼쪽부터 0, 1 이런 식으로 번호가 부여됩니다
그리고 터레인에 AlphaMap이라는 3차원 배열에서 가중치 조정이 가능합니다
이번 글에서는 이것을 사용하여 지형 색칠을 구현해 보겠습니다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TerrainEditor : MonoBehaviour
{
[SerializeField] private Terrain terrain;
[SerializeField] private LayerMask terrainMask;
[SerializeField] private float power = 3f;
[SerializeField] private Texture2D brashTex;
private bool paintMode;
private Color32[] curBrashArr;
private TerrainData data => terrain.terrainData;
private float[,] heightMap;
//알파맵 배열
private float[,,] alphaMap;
private void Awake()
{
heightMap = data.GetHeights(0, 0, data.heightmapResolution, data.heightmapResolution);
//알파맵 받아오기
alphaMap = data.GetAlphamaps(0, 0, data.alphamapResolution, data.alphamapResolution);
curBrashArr = brashTex.GetPixels32(0);
}
private void Update()
{
//Tab키로 모드 전환
if (Input.GetKeyDown(KeyCode.Tab))
{
paintMode = !paintMode;
}
if (Input.GetKey(KeyCode.LeftShift) && Input.GetMouseButton(0))
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit, 1000, terrainMask))
{
if (paintMode)
{
PaintTurrain(hit.point, false);
}
else
{
DrawTerrain(hit.point, false);
}
}
}
else if (Input.GetMouseButton(0))
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit, 1000, terrainMask))
{
if (paintMode)
{
PaintTurrain(hit.point, true);
}
else
{
DrawTerrain(hit.point, true);
}
}
}
}
private void DrawTerrain(Vector3 point, bool up)
{
int mousePosToTerrainX = (int)((point.x / data.size.x) * data.heightmapResolution);
int mousePosToTerrainZ = (int)((point.z / data.size.z) * data.heightmapResolution);
int size = (int)Mathf.Sqrt(curBrashArr.Length);
int cnt = 0;
for (int y = 0; y < size; y++)
{
for (int x = 0; x < size; x++)
{
if (mousePosToTerrainZ + (x - size / 2) < 0 ||
mousePosToTerrainZ + (x - size / 2) > data.heightmapResolution - 1 ||
mousePosToTerrainX + (y - size / 2) < 0 ||
mousePosToTerrainX + (y - size / 2) > data.heightmapResolution - 1)
{
cnt++;
continue;
}
if (up)
{
heightMap[mousePosToTerrainZ + (x - size / 2), mousePosToTerrainX + (y - size / 2)] +=
Mathf.InverseLerp(0, 255, curBrashArr[cnt].r) * Time.deltaTime / power;
}
else
{
heightMap[mousePosToTerrainZ + (x - size / 2), mousePosToTerrainX + (y - size / 2)] -=
Mathf.InverseLerp(0, 255, curBrashArr[cnt].r) * Time.deltaTime / power;
}
cnt++;
}
}
data.SetHeights(0, 0, heightMap);
}
private void PaintTurrain(Vector3 point, bool draw)
{
int mousePosToTerrainX = (int)((point.x / data.size.x) * data.alphamapResolution);
int mousePosToTerrainZ = (int)((point.z / data.size.z) * data.alphamapResolution);
int size = (int)Mathf.Sqrt(curBrashArr.Length);
int cnt = 0;
for (int y = 0; y < size; y++)
{
for (int x = 0; x < size; x++)
{
if (mousePosToTerrainZ + (x - size / 2) < 0 ||
mousePosToTerrainZ + (x - size / 2) > data.alphamapResolution - 1 ||
mousePosToTerrainX + (y - size / 2) < 0 ||
mousePosToTerrainX + (y - size / 2) > data.alphamapResolution - 1)
{
cnt++;
continue;
}
if (draw)
{
//터레인의 alphaMap을 조절
alphaMap[mousePosToTerrainZ + (x - size / 2), mousePosToTerrainX + (y - size / 2), 1] +=
Mathf.InverseLerp(0, 255, curBrashArr[cnt].r) * Time.deltaTime;
//타겟이 아닌 alphaMap의 비율을 낮춰주기
alphaMap[mousePosToTerrainZ + (x - size / 2), mousePosToTerrainX + (y - size / 2), 0] -=
Mathf.InverseLerp(0, 255, curBrashArr[cnt].r) * Time.deltaTime;
}
else
{
alphaMap[mousePosToTerrainZ + (x - size / 2), mousePosToTerrainX + (y - size / 2), 1] -=
Mathf.InverseLerp(0, 255, curBrashArr[cnt].r) * Time.deltaTime;
alphaMap[mousePosToTerrainZ + (x - size / 2), mousePosToTerrainX + (y - size / 2), 0] +=
Mathf.InverseLerp(0, 255, curBrashArr[cnt].r) * Time.deltaTime;
}
cnt++;
}
}
data.SetAlphamaps(0, 0, alphaMap);
}
}
이제 실행해 보시면?
지형 편집과 지형 색칠이 아주 잘 작동하는 것을 확인하실 수 있습니다
이제 이것을 응용하여 여러 가지 에디터를 만들 수 있을 것입니다
마지막으로 지금까지 만든 에디터를 공유하고 맵 에디터는 여기까지 하도록 하겠습니다
반응형
'유니티 > 3D 맵 에디터' 카테고리의 다른 글
[Unity] 3D 맵 에디터 - 2. 브러쉬 (0) | 2024.02.29 |
---|---|
[Unity] 3D 맵 에디터 - 1. 지형 편집 (0) | 2024.02.28 |