유니티/3D 맵 에디터

[Unity] 3D 맵 에디터 - 3. 지형 색칠

이름?없음 2024. 2. 29. 16:32
반응형

 

반응형

 

이번 글에서는 맵 에디터 지형 색칠을 구현해 보겠습니다

 

먼저 터레인 레이어 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);

    }


}

 

이제 실행해 보시면?

 

지형 편집과 지형 색칠이 아주 잘 작동하는 것을 확인하실 수 있습니다

 

이제 이것을 응용하여 여러 가지 에디터를 만들 수 있을 것입니다

 

마지막으로 지금까지 만든 에디터를 공유하고 맵 에디터는 여기까지 하도록 하겠습니다

BLOG.unitypackage
0.08MB

 

반응형

'유니티 > 3D 맵 에디터' 카테고리의 다른 글

[Unity] 3D 맵 에디터 - 2. 브러쉬  (0) 2024.02.29
[Unity] 3D 맵 에디터 - 1. 지형 편집  (0) 2024.02.28