게임프로그래밍/MMORPG 게임 개발(C#, 유니티)

[MMORPG 게임 개발(C#, Unity)] Part 3. Transform(트랜스폼)

shine94 2025. 4. 18. 18:24

* 해당 글은 게임 프로그래머 입문 올인원 강의를 보고 정리한 글입니다

   https://www.inflearn.com/roadmaps/355#introduce

 

MMORPG 게임 개발, 켠김에 끝판왕까지! (유니티 + C#) 로드맵 - 인프런

C#, Unity 스킬을 학습할 수 있는 게임 개발 로드맵을 인프런에서 만나보세요.

www.inflearn.com

 

 

 

 

* ScriptTemplates 위치

   C:\Program Files\Unity Editor Versions\6000.0.46f1\Editor\Data\Resources\ScriptTemplates

 

* public 필드와 [SerializeField] private 필드는 모두 인스펙터에서 값 설정 가능

 

* serialize(직렬화)

   메모리 데이터전송 가능한 형태변환하는 것

 

* deserialize(역직렬화, unserialize)

   전송 가능한 형태의 데이터를 다시 메모리 객체복원하는 것

 

* 유니티는 좌표계를 "Left-Handed, 왼손 좌표계" 기준으로 3D 공간을 설정한다

ㄴ 왼손 좌표계?

     X는 옆, Y는 위, Z는 앞(캐릭터가 정면을 보고 서 있을 때 기준)

의미
X축 좌 우
Y축 위 아래
Z축 앞 뒤

 

* 모델링

   게임 속 보이는 3D 요소를 만드는 아트 작업 전체

 

* 이동

   Local → World : transform.TransformDirection

   World Local : transform.InverseTransformDirection

 

   (1 - 1) 월드좌표 기준 이동 : transform.position

transform.position += new Vector3(0.0f, 0.0f, 1.0f) * (Time.deltaTime * _speed);

 

   (1 - 2) 월드좌표 기준 이동 : transform.position, 미리 정의된 상수인 Vector3.forward  사용

transform.position += Vector3.forward * (Time.deltaTime * _speed);

 

   (2) 로컬좌표를 월드좌표로 변환 이동 : transform.TransformDirection

transform.position += transform.TransformDirection(Vector3.forward * (Time.deltaTime * _speed));

 

   (3) 로컬좌표 이동 : transform.Translate

transform.Translate(Vector3.forward * (Time.deltaTime * _speed));

 

* 백터 정의

   거리와 방향을 좌표로 표현한 것

 

* 백터 사용하는 2가지 방법

   1. 위치 백터

       - 특정 지점의 좌표를 의미

       - Vector3(3, 2, 0) → (3, 2, 0) 위치에 있다는 뜻

       - 위치 간 연산 가능

Vector3 p1 = new Vector3(3, 2, 0);
Vector3 p2 = new Vector3(5, 4, 0);
Vector3 offset = p2 - p1;			// p1에서 p2까지의 방향

 

   2. 방향 백터

       - 두 지점의 차로 만들어지는 "어느 쪽을 향하고 있는가?"

Vector3 direction = target - current;

       - 위의 direction은 방향 + 거리 정보를 동시에 가짐

 

* 백터 관련 메서드

   1. magnitude :  거리(크기)

       - 피타고라스의 정리

float dist = direction.magnitude;		// 얼마나 떨어져 있는가

   2. normalized : 순수한 방향

       -  방향은 유지하고 길이를 1로 만든 백터 단위

transform.position += dir * speed * Time.deltaTime;

       -  이 방향으로, 내가 원하는 속도만큼 이동해라

       -  길이가 1 방향을 이용, 스피드와 델타 타임을 이용하여 그 방향으로 이동할 수 있다

 

* 유니티에서..?

   - normalized : 길이가 1인 방향 백터

   - 속도 = 거리 / 시간(초)

   - Time.deltaTime : 한 프레임당 경과 시간(초)

transform.position += 방향 * 속도 * Time.deltaTime;

 

   [정리하자면]  

   - 단위 백터는 방향만 나타냄(방향만 나타내는 화살표 역할)

   - 원하는 거리만 곱하면, 정확한 그 방향으로 이동할 수 있음

   - 프레임당 이동 거리 = 속도 * Time.deltaTime

   - 이 프레임당 이동 거리에 방향을 곱하면 → 그 방향으로 이동하는 이동 벡터가 됨

 

* 단위 벡터 × 거리 = 원하는 방향으로 정확히 이동하는 벡터

 

* 오일러 각(eulerAngles)

   오브젝트의 회전을 X, Y, Z 세 축으로 나눠서 각각 몇 도 회전했는지 나타내는 값

 

   (1) 절대 회전값(오일러 각 직접 지정)

private float _angle = 0.0f;

void Update()
{
    _angle += Time.deltaTime * 100.0f;
    transform.eulerAngles = new Vector3(0.0f, _angle, 0.0f);
}

   - 짐벌락(Gimbal Lock) 위험 있음

      ㄴ 짐벌락이란?

           3개의 회전축 중 두 개가 같은 방향으로 겹쳐져서 회전이 제대로 작동하지 않거나, 축 하나가 먹통되는 현상

 

   (2) 상대 회전값(기존 회전에 더하기)

private float _angle = 0.0f;

void Update()
{
    _angle += Time.deltaTime * 100.0f;
    transform.Rotate(new Vector3(0.0f, _angle, 0.0f));
}

 

   (3) 쿼터니언(Quaternion) 기반 회전

private float _angle = 0.0f;

void Update()
{
    _angle += Time.deltaTime * 100.0f;
    transform.rotation = Quaternion.Euler(new Vector3(0.0f, _angle, 0.0f));
}

   - 쿼터니언의 x, y, z는 회전 축을 나타내고, w는 회전 각도의 절반에 대한 코사인 값으로, 회전량을 수학적으로 표현한 값

   - 짐벌락 없이 회전을 안정적으로 처리할 수 있음

 

* 유니티는 내부적으로 회전을 쿼터니언으로 처리하기 때문에, rotation을 직접 다루면 더 안정적이라고 함