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

[멋쟁이사자처럼부트캠프] 유니티 게임 개발 5기(10일차) - Transform과 Polygon 동작 확인 및 C# 기초(6)

by 독기품은토끼 2025. 5. 26.
✅ 오늘의 학습 목표
1. Transform 활용
2. Polygon 원리 확인
3. C# 기초 학습(6)

 

1. Transform 활용하기

1. Roulette

🥕 예행 작업
1. Scene 생성 (Roulette)
2. Script 생성 (RouletteController)

 

1.1. 에셋 Import

 

Cute GUI-Pack-Lite | 2D 아이콘 | Unity Asset Store

Elevate your workflow with the Cute GUI-Pack-Lite asset from NBROS. Browse more 2D GUI on the Unity Asset Store.

assetstore.unity.com

 

해당 에셋을 내 유니티 프로젝트에 추가해 준다.

 

1.2. 이미지 레이어 조정

 

룰렛판과 표시판을 넣으면 내가 원하는 이미지의 순서가 아닐 수 있다.

이럴 때에는 Layer를 설정해 주자. (숫자가 높을수록 가장 위에 이미지가 배치된다.)

 

1.3. 메인 카메라 조정

 

프로젝트를 실행시켰을 때, 카메라에 룰렛판이 너무 확대되어 나타나 있으니 이걸 좀 조정해 주자.

지금 2D 프로젝트를 진행하고 있으니 Projection을  Orthographic으로 바꿔준다.

(4일차에 씬 기즈모 배울 때 사용한 ISO와 동일한 옵션)

항목 Perspective Orthographic
투영 방식 원근 투영 (Perspective Projection) 직교 투영 (Orthographic Projection)
원근감 있음 (멀리 있는 객체는 작아 보임) 없음 (멀리 있어도 크기 동일)
크기 기준 화면에서의 위치와 거리 실제 객체의 크기
주 용도 3D 게임, 현실감 있는 장면 2D 게임, UI, 등거리 시점
설정 속성 Field of View (시야각) 조절 Size (카메라 높이 절반) 조절
사용 예시 FPS, TPS, 3D 액션 게임 등 2D 퍼즐 게임, 전략 게임, 미니맵 카메라 등

 

1.4. Z축 기준으로 회전시키기

 

룰렛판이 Z축 기준으로 회전되도록 코드를 작성해 주자.

public class RouletteController : MonoBehaviour
{
    public float rotSpeed = 5f;
    
    void Update()
    {
        transform.Rotate(Vector3.forward * rotSpeed);
    }
}

 

1.5. 클릭 이벤트 추가

마우스로 클릭했을 때 룰렛판이 돌아가도록 설정해 보자.

public class RouletteController : MonoBehaviour
{
    public float rotSpeed = 0f;
    private bool isStop, isRotating = false;
    
    void Update()
    {
        transform.Rotate(Vector3.forward * rotSpeed);
        
        if (Input.GetMouseButtonDown(0))
        {
            rotSpeed = 5f;
        }
    }
}

 

1.6. 룰렛이 서서히 멈추는 기능 추가

using UnityEngine;

public class RouletteController : MonoBehaviour
{
    public float rotSpeed;

    public bool isStop; // false

    void Start()
    {
        rotSpeed = 0f;
    }
    
    void Update()
    {
        transform.Rotate(Vector3.forward * rotSpeed); // Z축 기준으로 회전하는 기능
        
        // 마우스 왼쪽 버튼을 눌렀을 때 -> 1번 실행
        if (Input.GetMouseButtonDown(0))
        {
            rotSpeed = 5f;
        }

        // 키보드 스페이스 버튼을 눌렀을 때 -> 1번 실행
        if (Input.GetKeyDown(KeyCode.Space))
        {
            isStop = true;
        }

        if (isStop == true)
        {
            rotSpeed *= 0.98f; // 현재 속도에서 특정 값만큼 줄이는 기능

            if (rotSpeed < 0.01f)
            {
                rotSpeed = 0f;
                isStop = false;
            }
        }
    }
}

 

1.7. 최종 결과물

 

2. Transform 작동 방식

🥕 예행 작업
1. Scene 생성 (TransformMovement)
2. Script 생성 (StudyTransfrom)

 

2.1. 월드 기준과 로컬 기준의 차이

using UnityEngine;

public class StudyTransform : MonoBehaviour
{
    public float moveSpeed = 10f;
    public float rotateSpeed = 70f;

    void Update()
    {
        // 1. 월드 방향으로 이동
        // transform.position += Vector3.forward * moveSpeed * Time.deltaTime;

        // 2. 로컬 방향으로 이동
        // transform.localPosition += Vector3.forward * moveSpeed * Time.deltaTime;

        // 3. 로컬 방향으로 이동
        // transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);

        // float angle = transform.eulerAngles.y + rotateSpeed * Time.deltaTime;
        // float localX = transform.localEulerAngles.x;
        // float localZ = transform.localEulerAngles.z;

        // 4. 월드 방향으로 회전
        // transform.rotation = Quaternion.Euler(localX, angle, localZ);

        // 5. 로컬 방향으로 회전
        // transform.localRotation = Quaternion.Euler(localX, angle, localZ);

        // 6. 로컬 방향으로 회전
        // transform.Rotate(Vector3.up, rotateSpeed * Time.deltaTime); // Space.Self 생략

        // 7. 월드 방향으로 회전
        // transform.Rotate(Vector3.up, rotateSpeed * Time.deltaTime, Space.World);

        // 8. 특정 위치의 주변을 회전 (new Vector3(0f, 0f, 0f), new Vector3(0f, 1f, 0f) 줄여씀
        // transform.RotateAround(Vector3.zero, Vector3.up, rotateSpeed * Time.deltaTime);
    }
}

 

월드 기준과, 로컬 기준에서 각각 어떻게 적용되는지 주석을 코드별로 풀어서 확인해 보자

 

2.2. Transform 한눈에 보기...

 

이렇게 월드 기준과 로컬 기준에 따라서 움직임이 어떻게 다른지 확인할 수 있다.

실제 게임을 구현할 때 주의가 필요할 것 같다.

 

2. Polygon

5일차에 폴리곤에 대해 약간 학습했었다.

폴리곤의 작동 방식, 원리에 대해서도 한번 알아봐 보자.

 

 

[멋쟁이사자처럼부트캠프] 유니티 게임 개발 5기(5일차) - Unity 기본 사용법(2) 및 오브젝트 활용

✅ 오늘의 학습 목표1. 유니티 에디터 알아보기(2)2. 게임 오브젝트 활용🥕 예행 작업1. Project - Assets 아래 새로운 폴더 생성2. Scenes 폴더에 새로운 씬 생성 1. UI 버튼의 기능 및 윈도우 바1. 좌표계1

toxicbunny.tistory.com

 

🥕 예행 작업
1. 기존 Scene 열기 (Array)
2. Script 생성 (StudyPolygon)
3. GameObject 생성

 

1. 코드

using UnityEngine;

public class StudyPolygon : MonoBehaviour
{
    void Start()
    {
        // 데이터(점)가 들어갈 mesh 타입의 변수 생성
        Mesh mesh = new Mesh();

        // 점 4개 찍기
        Vector3[] vertices = new Vector3[]
        {
            new Vector3(0, 0, 0),
            new Vector3(1, 0, 0),
            new Vector3(0, 1, 0),
            new Vector3(1, 1, 0),
        };

        // 삼각형 순서
        int[] triangles = new int[]
        {
            0, 2, 1,
            2, 3, 1,
        };

        // uv = 면을 감싸는 표면
        Vector2[] uv = new Vector2[]
        {
            new Vector2(0, 0),
            new Vector2(1, 0),
            new Vector2(0, 1),
            new Vector2(1, 1)
        };

        // Mesh에 위에서 만든 점, 삼각형, uv 데이터를 적용
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.uv = uv;

        // MeshFilter에 Mesh 데이터를 적용
        MeshFilter meshFilter = this.gameObject.AddComponent<MeshFilter>();
        meshFilter.mesh = mesh;

        // MeshRenderer에 Material 적용
        MeshRenderer meshRenderer = this.gameObject.AddComponent<MeshRenderer>();
        meshRenderer.material = new Material(Shader.Find("Sprites/Default"));
    }
}

 

2. 결과

위 코드는 Mesh를 직접 생성하여 폴리곤을 그리는(?) 작업을 구현한 코드이다!
점 4개를 정의하고, 이 중 3개씩 묶어 삼각형 2개를 만들어 사각형 도형을 구성한다.
이후 각 점에 UV 좌표를 설정해 텍스처를 입힐 수 있도록 만들었다.
이렇게 만든 것을 MeshFilter와 MeshRenderer를 통해 화면에 출력할 수 있다.

 

2.1. UV란 무엇인가!

 

3D 모델링에서는 기초가 되는 것이라고 하는데...

우리가 직접 3D 모델링해서 오브젝트를 구현하는 것이 아니라고.. 깊게 알 필요는 없다 하셨다.

 

대충 정리하자면!

3D 모델은 여러 개의 폴리곤으로 이루어져 있는데,
이 모델에 2D 이미지를 입히기 위해서는, 이미지의 어느 부분이 폴리곤의 어떤 정점에 대응되는지를 알려주어야 한다.

그래서 uv라는 좌표라는 것이 생기게 된 거다!

 

3. C# 기초 학습(6)

1. Unity Callback 함수

아래 함수들은 Unity에서 기본 제공하는 콜백 함수로, 특정 시점에 자동으로 호출되도록 설계된 함수이다.

using System;
using UnityEngine;

public class StudyUnityEvent : MonoBehaviour
{
    void Awake()
    {
        Debug.Log("Awake");
    }

    void Start()
    {
        Debug.Log("Start");
    }

    // 켜질 때 마다 1번 실행
    void OnEnable()
    {
        Debug.Log("OnEnable");
    }

    // 꺼질 때 마다 1번 실행
    void OnDisable()
    {
        Debug.Log("OnDisable");
    }

    void Update()
    {

    }
}

 

1.1. 호출 시점

항목 호출 시점
Awake() 오브젝트가 생성될 때 (스크립트 활성화 여부 상관 없음)
Start() 첫 프레임 직전에 한 번 (스크립트가 활성 상태일 때만)
OnEnable() / OnDisable() 오브젝트가 활성/비활성화될 때
Update() 매 프레임마다 호출

 

 

1.2. OnEnable, OnDisable

 

오브젝트를 활성화/비활성화시킬 때마다 해당 콜백 함수들이 다시 호출되는 것을 확인할 수 있다.

 

2. 연산자

2.1. 대입 연산자

 

2.2. 산술 연산자

 

2.3. 비교 연산자

 

2.4. 논리 연산자

 

2.5. bool

bool은 비교 연산의 결과(true, false)를 반환한다.

using UnityEngine;

public class StudyOperator : MonoBehaviour
{
    public int currentLevel = 10;

    public int maxLevel = 99;

    void Start()
    {
        // 비교 연산에 의한 결과를 bool 값으로 받는 코드
        bool isMax = currentLevel >= maxLevel;

        Debug.Log($"현재 레벨은 만렙이 {isMax} 입니다.");
    }
}

 

따라서 위 코드 결과로는 false를 반환한다.

 

2.6. 삼항 연산자

삼항 연산자는 if문과 switch문 같은 조건문을 사용하지 않고 간단하게 참/거짓을 처리하는 짧은 문법이다.

using UnityEngine;

public class StudyOperator : MonoBehaviour
{
    public int currentLevel = 10;

    public int maxLevel = 99;

    void Start()
    {
        string msg = currentLevel >= maxLevel ? "현재 만렙입니다." : "현재 만렙이 아닙니다.";

        Debug.Log(msg);
    }

}

 

조건 ? 참 값 : 거짓 값 → 이 형식으로 입력하면 된다.

 

2.7. 비트 연산자

유니티에서 비트 연산자로 계산을 좀 간단하게 하는 작업이 있다.

 

레이어 같이 활성화/비활성화 부분이 보통 비트 연산자로 구현되어 있다고 하셨음

 


 

 

주말에 살짝 복습해 보면서 느낀 건데,

코드블록 넣어둘 때 내가 복붙 해서 복습할까 봐 일부로 코드를 좀 잘라서 넣었는데

와! 진짜 개불편ㅋ 과거의 나는 나를 너무 잘 알았던 건가.. 지금의 나로서는 과거의 내가 밉다!

 

아무튼 벌써 부캠 3주차 시작인데.. 시간이 참 빠른 거 같다..

시간의 흐름과 나의 집중력은 반비례되는 중..^^... 벌써 이러면 안되는데~~ 정신 체리자!! 🍒🍒🍒