Notice
Recent Posts
Recent Comments
Link
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

김산나

[멋쟁이사자처럼부트캠프 유니티 게임 개발 7기] 2026년 2월 25일 회고록 - 3D 입문 본문

Unity Engine

[멋쟁이사자처럼부트캠프 유니티 게임 개발 7기] 2026년 2월 25일 회고록 - 3D 입문

김산나 2026. 2. 25. 17:31

2026_02_25 강의 요약본

 

- 3D 입문 -

강사님께서는 그냥 z축 하나 추가된 거다 말씀하셨지만, 실제로는 그것보다 훨씬 복잡했다.

왜냐하면 3D의 지향점은 2D보다 " 실제 "에 가까워 사실적인 그래픽을 위한 기술들이 매우매우 많이 들어가 있었다.

일단 요구 사양부터 확 올라간다. 간단히 풀을 심었을 뿐이었는데도 크래쉬 오류가 뜨고 그랬다.

 

1. 복습

이전에 잠깐 진행했던 3D에서 사용한 코드에 대한 복습이다.

이동, 회전, 타겟 추적, 타겟 방향으로 회전, 충돌 처리, 오브젝트 클릭 순서로 다시 알아보자.

 

1) 이동

    void Update()
    {
        float speed = 5f;
        float h = Input.GetAxis("Horizontal");  // A/D 또는 ←/→
        float v = Input.GetAxis("Vertical");    // W/S 또는 ↑/↓

        // Space.Self (기본값): 오브젝트의 로컬 방향으로 이동 (앞이 forward)
        transform.Translate(Vector3.forward * v * speed * Time.deltaTime, Space.Self);
        transform.Translate(Vector3.right   * h * speed * Time.deltaTime, Space.Self);

        // Space.World: 월드 좌표 기준으로 이동
        transform.Translate(Vector3.forward * v * speed * Time.deltaTime, Space.World);
        transform.Translate(Vector3.right   * h * speed * Time.deltaTime, Space.World);
    }

 

가장 기본적인 이동. Self는 로컬 방향으로 이동, World는 월드 좌표 기준으로 이동한다.

Vector 2는 up, down right, left이런 식으로 있었다면(2차원), Vector3부터는 front가 추가되었다.

 

 

2) 회전

    void Update()
    {
        gameObject.transform.eulerAngles += new Vector3(0, 10,0);
    }

 

position도 그렇듯, 각도도 직접 수정이 안 된다. rotation이 아닌, 오일러 각을 수정해야 하고, 각을 Vector3로 입력한다.

 

 

3) 타겟 추적

    [SerializeField] private Transform target;
    [SerializeField] private float speed = 3f;

    void Update()
    {
        // MoveTowards: 일정 속도로 목표 지점 접근 (오버슛 없음)
        transform.position = Vector3.MoveTowards(
            transform.position,
            target.position,
            speed * Time.deltaTime
        );

        // Lerp (선형 보간): 부드럽게 점점 느려지며 접근 (t는 0~1)
        // 주의: t에 Time.deltaTime을 사용하면 매 프레임 비율이 달라지므로 아래는 근사치 사용법
        transform.position = Vector3.Lerp(
            transform.position,
            target.position,
            0.1f  // 매 프레임 나머지 거리의 10% 이동 → 점점 느려짐
        );

            float rotateSpeed = 90f; // 초당 90도

        // Y축 회전
        transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.World);

        // 로컬 X축 회전 (피칭)
        transform.Rotate(Vector3.right * rotateSpeed * Time.deltaTime, Space.Self);
    }

 

두 가지 방식이 있다. MoveTowards, trandform.position = Vector3.Lerp

전자는 이름 그대로 그쪽으로 가는 기능이고, Lerp는 목표 위치로 원하는 곡선대로 이동시키는 기능이다.

 

 

4) 타겟 방향으로 회전

    [SerializeField] private Transform target;
    void Update()
    {
        // 즉시 target을 바라봄
        transform.LookAt(target);

        // Y축만 회전하도록 (수직 회전 무시)
        Vector3 lookPos = target.position;
        lookPos.y = transform.position.y;
        transform.LookAt(lookPos);
    }

 

LookAt은 target 위치로 각도를 변경한다.

만약 특정 축만 이동하고 싶다면 Vector3 변수를 만들어 특정 축의 값만 받아서 넣으면 된다.

 

 

5) 충돌 처리

2D랑 동일하다. 사실 큰 차이 없다고 봐도 될듯.

다만 이름 뒤에 "2D"를 제외해야 한다.

 

    // 충돌이 시작될 때 (한 번만)
    void OnCollisionEnter(Collision collision)
    {
        Debug.Log("충돌 시작: " + collision.gameObject.name);

        // 충돌 지점 정보
        foreach (ContactPoint contact in collision.contacts)
        {
            Debug.DrawRay(contact.point, contact.normal, Color.red, 1f);
        }
    }

    // 충돌 중 (매 프레임)
    void OnCollisionStay(Collision collision)
    {
        // 지속적인 충돌 처리
    }

    // 충돌이 끝날 때 (한 번만)
    void OnCollisionExit(Collision collision)
    {
        Debug.Log("충돌 종료: " + collision.gameObject.name);
    }
    // 트리거 영역에 진입할 때
    void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            Debug.Log("플레이어가 트리거 영역에 진입!");
            // 아이템 획득, 체크포인트 등
        }
    }

    // 트리거 영역에서 나갈 때
    void OnTriggerExit(Collider other)
    {
        Debug.Log(other.name + "이 트리거 영역을 벗어남");
    }

 

비슷하다.

 

6) 오브젝트 클릭

카메라를 기준으로, 유저가 클릭한 위치에 레이저를 쏴 감지된 오브젝트를 클릭 대상으로 지정한다.

void Update()
    {
        // 마우스 클릭 위치의 오브젝트 감지
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit, 100f))
            {
                Debug.Log("클릭한 오브젝트: " + hit.collider.gameObject.name);
                Debug.Log("충돌 지점: " + hit.point);
                Debug.DrawRay(ray.origin, ray.direction * hit.distance, Color.green, 1f);

                hit.collider.GetComponent<MeshRenderer>().material.color = Color.red;
            }
        }
    }

 

 

2. Terrain

3D의 Plane이랑 비슷하게 생겼는데, 지형을 전문적으로 만드는 Plane이라고 보면 된다.

생성하면 도구가 여럿 있다.

Paint Terrain툴을 누른 후 선택지를 살펴보자.

Rate or Lower Terrain은 산이나 협곡을 그리는 툴이다.

이게 다 브러쉬. 하단에 있는 브러쉬 사이즈, 블투명도를 조절해서 그릴 수 있다.

클릭은 산 그리기, shift + 클릭은 모양대로 고도 낮추기(협곡 그리기)이다.

 

Paint Texture은 Terrain의 텍스쳐를 그리는 툴이다.

레이어를 분리하여 그릴 수 있다.

 

이건 잔디, 풀, 나무 등의 요소를 그려주는 툴이다. 하단의 Edit Details로 구조물을 추가, 편집할 수 있다.

최적화 안 되는 툴을 밀도 높게 그리면 게임이 터지니 주의한다....

 

물은 어떻게 만들까?

 

물은 Plane에 Material을 적용해서 만든다.

 

 

이런 식으로 사이즈를 조절하고, 머터리얼을 적용하면 잘 작동한다.

 

 

===========================================================

 

3D 입문 !

터레인을 사용할 수 있게 되었다 !