Carrot
본문 바로가기
Unity/멋쟁이사자처럼 부트캠프

[멋쟁이사자처럼부트캠프] 유니티 게임 개발 5기(53일차) - 3D 편집도구 실습 및 C# 중급 (1)

by 독기품은토끼 2025. 8. 1.
✅ 오늘의 학습 목표
1. Probuilder 실습
2. Terrain 실습
3. Polybrush 실습
4. C# 중급 (1)

 

1. Probuilder

 

ProBuilder는 정교한 형태의 오브젝트를 직접 만들어서 배치하거나, 맵 프로토타입을 만들 때 유용한 툴이다.

 

First Vertex로 만들면 피벗이 꼭짓점으로 잡히고, ctrl을 누른 채로 만들면 사이즈가 딱 맞게 생성된다.

오브젝트를 Shift 누르고 드래그하면 복사가 된다.

 

 

ProBuilder 오브젝트를 수정하려면 좌측 툴바 제일 위에 있는 셀렉션 툴을 선택한 뒤,

점(Vertex), 선(Edge), 면(Face) 중에서 선택해서 편집하면 된다.

 

영역을 자를 때에는 Cut tool을 사용하면 되고

면을 선택하고 마우스 우클릭 Subdivide Faces를 선택하면 좀 더 세분화된 형태로 나눌 수 있다.

 

 

2. Terrain

 

Terrain은 지형을 만들 때 사용하는 툴이다.

ProBuilder는 직접 구조물을 만드는 용도라면, Terrain은 말 그대로 넓은 땅이나 언덕, 산 같은 걸 만들 때 쓴다.

 

ProBuilder는 보통 모델러나 레벨 디자이너가 쓰기도 하지만 Terrain은 개발자 쪽에서도 기본적인 사용법 정도는 익혀두는 게 좋다.

 

1. Terrain Settings

 

Terrain은 지형을 만들 때 사용하는 툴이라서 처음 생성하면 사이즈가 꽤 크다.
기본 Plane의 100배 크기로 만들어지는데 사이즈를 조절하려면 Terrain Settings > Mesh Resolution 쪽에서 수치를 조정하면 된다.

 

2. Paint Terrain

 

지형을 직접 그리려면 Paint Terrain 창을 사용하면 된다.
그 안에서 Raise or Lower Terrain을 선택한 뒤 브러쉬 종류를 고르고, 브러쉬 크기나 강도를 조절해 가면서 원하는 형태로 지형을 다듬을 수 있다.

 

항목 설명
Raise or Lower Terrain 클릭한 위치의 지형을 올리거나 깎음
Set Height 지형을 지정한 높이로 평평하게 맞춤
Smooth Height 날카롭거나 들쭉날쭉한 지형을 부드럽게 다듬는 용도
Stamp Terrain 준비된 지형 스탬프(산, 언덕 등)를 찍어내서 빠르게 형태를 잡을 수 있음
Paint Holes 지형에 구멍을 뚫음. (예: 동굴 입구나 낙하 구간 만들 때 사용)
Transform 지형 전체를 이동, 회전, 스케일 조절할 수 있는 기능
Effects 지형에 침식(Erosion)이나 노이즈 같은 시각 효과 적용
Sculpt 여러 브러쉬 기능을 조합해 세밀하게 조형하는 커스텀 브러쉬 툴
Erosion 지형 침식 효과를 시뮬레이션해 자연스러운 지형 형태를 생성
Paint Texture 지형에 텍스처(흙, 풀, 바위 등)를 칠할 수 있는 기능. 레이어 기반으로 적용

 


 

 

Paint Texture 툴을 선택하면 바로 브러쉬가 뜨는 게 아니라 먼저 레이어를 만들어줘야 한다.

 

  • Terrain을 선택한 상태에서 Paint Terrain > Paint Texture 탭으로 이동
  • Create Layer 또는 Add Layer 선택
    • Create Layer: 새로운 텍스처를 추가해서 생성
    • Add Layer: 기존에 만들어둔 텍스처 레이어가 있다면 그걸 불러오기

 

 

3. Paint Trees

지형에 나무를 배치할 때 사용하는 기능이다.
일일이 프리팹을 드래그해서 놓지 않고 브러쉬처럼 쓱쓱 그리듯 나무를 심을 수 있다.

🥕 예행 작업
1. Asset 다운로드
 

Unity Terrain - URP Demo Scene | 3D 주변환경 | Unity Asset Store

Elevate your workflow with the Unity Terrain - URP Demo Scene asset from Unity Technologies. Find this & other 주변환경 options on the Unity Asset Store.

assetstore.unity.com

 

다운받은 나무나 바위 프리팹을 Trees 탭에 넣어주고 Terrain 위에 클릭하거나 드래그하는 방식으로 나무를 배치할 수 있다.

 

 

3. Polybrush

 

Polybrush는 메시(Mesh)의 표면을 직접 브러시처럼 수정할 수 있는 Unity 전용 툴이다.

Terrain을 쓰지 않고도 자연스러운 지형 느낌을 주고 싶을 때 사용하면 좋은 툴이다.

 

1. Sculpt

 

메시 표면의 버텍스를 위아래로 직접 이동시켜 굴곡이나 입체감을 표현할 수 있다.
Terrain 없이 간단한 지형이나 암벽을 만들 때 유용하며, Smooth와 함께 사용하면 자연스러운 결과를 얻을 수 있다.

 

2. Smooth

 

Vertex 위치, Vertex Color, 텍스처 블렌딩 등의 결과를 자연스럽게 정리해 주는 브러시
굴곡이 심하거나 경계가 뚜렷한 부분을 부드럽게 연결할 때 사용한다.

 

3. Color

 

메시 표면에 버텍스 단위로 색상을 칠할 수 있는 기능.
Vertex Color를 사용하는 셰이더와 함께 사용할 때만 반영됨.

 

 

4. Object

 

메시 표면 위에 오브젝트(프리팹)를 브러시처럼 배치할 수 있다.
나무, 풀, 돌 등 다양한 환경 프랍을 자연스럽게 뿌릴 때 사용하며, 랜덤 회전/스케일 등의 설정으로 반복 티를 줄일 수 있음.

 

5. Texture

 

메시 하나에 여러 텍스처를 섞어 칠할 수 있는 기능.
예를 들어 바위에 흙, 이끼, 눈 텍스처를 자연스럽게 섞을 수 있다.
텍스처 블렌딩을 지원하는 셰이더가 필요함.

 

 

4. C# 중급

1. 매개변수 활용

1.1. 일반 매개변수 (Call by Value)

public int number = 1;

void Start()
{
    NormalParameter(number);
    Debug.Log($"Call by Value : {number}"); // 1
}

private void NormalParameter(int num)
{
    num = 10;
}

 

  • NormalParameter(number)를 호출하면, number의 값이 복사되어 전달된다.
  • 즉, 메서드 안에서 값을 바꿔도 원래 변수에는 영향을 주지 않는다.

 

1.2. 참조 매개변수 (ref)

public int number = 1;

void Start()
{
    ReferenceParameter(ref number);
    Debug.Log($"Call by Reference : {number}"); // 20
}

private void ReferenceParameter(ref int num)
{
    num = 20;
}

 

  • ref 키워드를 사용하면 원래 변수 자체를 참조해서 값을 바꾼다.
  • 메서드 안에서 값을 수정하면, 호출한 쪽 변수도 같이 바뀐다.

 

1.3. 반환 전용 매개변수 (out)

public int number = 1;
public int number2;

void Start()
{
    OutParameter(out number, out number2);
    Debug.Log($"Call by Out : {number}, {number2}"); // 30, 50
}
    
    private void OutParameter(out int num, out int num2)
{
    num = 30;
    num2 = 50;
}

 

  • out은 값을 메서드 내부에서 설정하고, 외부로 전달하기 위한 키워드.
  • 초기화하지 않고 넘겨도 되고, 무조건 메서드 안에서 값을 할당해야 한다.

 

 

1.4. 선택적 매개변수 (Default)

void Start()
{
    DefaultParameter(); // 값이 없어도 되고
    DefaultParameter(5); // 있으면 해당 값으로 초기화 됨 number = 5
}

// 선택적 매개변수 (Default 매개변수) -> 매개변수에 값을 넣어둔 것
private void DefaultParameter(int num = 3)
{
    number = num;
}

 

  • 매개변수에 기본값을 지정해두면, 인자를 생략해도 호출 가능하다.

 

1.5. 배열 매개변수 (Array)

void Start()
{
    int[] inArray = new int[3] { 10, 20, 30 }; // 크기가 정해져 있어서 값 추가 안됨
    ArrayParameter(inArray);
}

private void ArrayParameter(int[] numbers)
{
    foreach (var n in numbers)
    {
        Debug.Log(n);
    }
}

 

  • 배열(int[])을 매개변수로 넘겨서 여러 값을 한꺼번에 전달할 수 있다.
  • 배열은 크기가 고정되어 있기 때문에, 동적으로 요소를 추가하거나 뺄 수는 없다.
  • 배열 내부 값은 순회하며 접근 가능하다.

 

1.6. 가변 인자 매개변수 (Params)

void Start()
{
    ParamsParameter(10, 20, 30);
}

private void ParamsParameter(params int[] numbers)
{
    foreach (var n in numbers)
    {
        Debug.Log(n);
    }
}

 

  • params 키워드를 사용하면 배열처럼 값을 나열해서 전달할 수 있는 가변 매개변수가 된다.
  • 배열을 따로 만들 필요 없이, 콤마(,)로 구분된 값들만 넘겨주면 자동으로 배열처럼 처리된다.

 

1.7. GameObject 매개변수

public GameObject player;
public GameObject enemy;
public GameObject item;

void Start()
{
    GameObjectActivate2(false, player, enemy, item);
}

private void GameObjectActivate2(bool isActive, params GameObject[] objs)
{
    foreach (var o in objs)
    {
        o.SetActive(isActive);
    }
}

 

  • params를 활용해서 여러 개의 GameObject를 한 번에 넘기고 반복문을 통해 모든 오브젝트의 SetActive() 상태를 일괄적으로 바꿀 수 있다.
  • 리스트나 배열을 따로 만들지 않아도 간단하게 일괄 처리할 수 있는 방식이다.
  • = GameObject들을 배열 형태로 받아 처리할 수 있어, 리스트를 미리 만들 필요 없이 간단하게 다수의 오브젝트를 제어할 수 있다.

 

1.8. 오버로딩 (Overloading)

void Start()
{
    OverloadingMethod();
    OverloadingMethod(1);
    OverloadingMethod(1f);
    OverloadingMethod(true);
    OverloadingMethod(1, 2);
}

private void OverloadingMethod() { Debug.Log("기능 A"); }
private void OverloadingMethod(int num) { Debug.Log("기능 B"); }
private void OverloadingMethod(float num) { Debug.Log("기능 C"); }
private void OverloadingMethod(bool isNum) { Debug.Log("기능 D"); }
private void OverloadingMethod(int num1, int num2) { Debug.Log("기능 E"); }

 

  • 메서드 이름은 같지만 매개변수의 타입이나 개수가 다르면 서로 다른 메서드로 인식된다.
  • 이처럼 동일한 이름으로 여러 기능을 정의할 수 있는 것을 오버로딩(Overloading) 이라고 한다.

 

2. Static

C#에서 static 키워드는 정적(static) 멤버를 선언할 때 사용된다.

정적 멤버는 특정 인스턴스에 속하는 것이 아니라, 클래스 자체에 속하게 되는데

이 말은 즉, 클래스의 인스턴스를 만들지 않아도 바로 접근할 수 있다는 것을 의미한다.

using UnityEngine;

public class StudyStatic : MonoBehaviour
{
    void Start()
    {
        Debug.Log($"정적 변수에 접근 : {StaticClass.number}");
    }

    public class StaticClass
    {
        public static StaticClass instance = new StaticClass();
        public static int number = 10;

        public StaticClass()
        {
            Debug.Log($"생성자 실행 : {number}");
        }
    }
}

 

  • StudyStatic 클래스의 Start() 메서드에서 new StaticClass()를 하지 않고도 StaticClass.number처럼 클래스 이름만으로 변수에 접근할 수 있다.

 

3. Partial

partial class는 부분 클래스란 뜻이고,

같은 이름의 클래스를 여러 파일이나 코드 블록에서 나눠서 정의할 수 있게 해준다.

public partial class StudyPartial : MonoBehaviour
{
    private int nuber;

    public void Start()
    {
        MethodA();
        MethodB();
    }

    private void MethodA()
    {
        Debug.Log("MethodA");
    }
}

 

  • StudyPartial이라는 클래스가 두 개로 나뉘어 정의되어 있음.
  • 둘 다 partial 키워드를 사용했기 때문에 컴파일할 때 하나의 StudyPartial 클래스로 합쳐짐.
  • 그래서 MethodA와 MethodB는 결국 하나의 클래스 안에 있는 두 개의 메서드가 됨.
  • Start() 메서드에서 MethodA()와 MethodB()를 호출하고 있어서, Unity 실행 시 두 메서드 모두 로그를 출력함.
  • 동일한 멤버(변수, 메서드) 이름은 중복 선언하면 안 됨
  • 모든 partial 블록은 접근 제어자(public/private 등), 상속 관계(MonoBehaviour 상속 여부) 등에서 일관성 있어야 함.