유니티/3D 맵 에디터

[Unity] 3D 맵 에디터 - 2. 브러쉬

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

 

반응형

저번 글에서는 터레인 지형편집을 알아보았는데요

하지만 지형이 한 곳만 튀어나오는 문제점이 있었습니다

이번 글에서는 그 문제를 해결하기 위하여 브러쉬를 만들고 적용시켜 보겠습니다

 

먼저 브러쉬에 사용할 이미지를 만들어주어야 합니다

저는 GIMP로 간단하게 하나 만들어 주었습니다

 

그다음 텍스쳐 설정에서 Read/Write를 활성화시켜 주세요

 

이러면 텍스쳐 설정은 끝났습니다 이제 코드를 작성할 시간입니다

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 Color32[] curBrashArr;

    private TerrainData data => terrain.terrainData;

    private float[,] heightMap;

    private void Awake()
    {

        heightMap = data.GetHeights(0, 0, data.heightmapResolution, data.heightmapResolution);

        //브러쉬 텍스쳐의 정보를 가져와주기
        curBrashArr = brashTex.GetPixels32(0);

    }

    private void Update()
    {

        //시프트를 누르고 클릭하면 내려가게
        if (Input.GetKey(KeyCode.LeftShift) && Input.GetMouseButton(0))
        {

            var ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            if (Physics.Raycast(ray, out var hit, 1000, terrainMask))
            {

                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))
            {

                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++)
            {

                //인덱스를 범위를 넘어섰을때 continue
                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)
                        ] +=
                        //역보간으로 현제 브러시 데이터의 값을 0 ~ 1 로 변환
                        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);

    }


}

 

브러쉬 텍스쳐의 색 값을 읽어온 다음 

역보간을 이용하여 0 ~ 1로 고정해 주고 그 값을 기반으로 지형을 변경시키는 식으로 작성하였습니다

이제 코드에 텍스쳐를 할당해 주고

실행해 주시면?

지형편집이 잘 되는 것을 확인하실 수 있습니다

이뿐만이 아니라 흑백으로 이루어진 이미지라면 브러쉬로 사용할 수 있습니다

 

이런 네모모양 브러쉬를 사용해도 잘 동작하는 것을 확인할 수 있습니다

 

이렇게 이번 글에서는 브러쉬를 구현해 보았는데요

다음 글에서는 지형색칠에 관하여 알아보도록 하겠습니다

반응형