오늘은 이미 이전 포스팅에서 많이 보였겠지만,
스크립트를 작성할 때 쓰이는 함수의 수학, 물리의 기본 요소를 다루어보도록 하겠다.
기초적인 내용이며,
이미 알고 있는 사람들은 복습의 개념으로!
아니면 이미 써왔지만 개념을 정확히 알고 가는 느낌으로!
시작을 해본다.
유니티 게임 수학 & 물리
1. 게임 오브젝트 위치를 결정하는 기본 요소
오브젝트 위치 : Position
유니티 x,y,z 좌표 : Vector3
플레이어의 transform.position 가져와서 Vector3의 (0,5,0)로 변경하는 함수
//플레이어 (0, 5, 0) 위치로 이동
transform.position = new Vector3(0,5,0);
개인적으로 궁금증이 생겼던 건데, 왜 new Vector3일까?
그냥 Vector3으로 하면 안 되는 것인가? 라는 생각이 들었었다.
이건 노베이스라서 코드 하나 하나가 왜 붙여진지 궁금증이 생겨 이런 생각을 하게 된 건데..
이것은 새로운 Vector3 객체를 생성해서 position 값을 설정하는 것이다.
new Vector3를 생성해서 기존에 있던 vector3의 transform.position을 new Vector3로 덮어씌운다는 것이다.
그렇기 때문에 Vector3이 아니라 new Vector3이 되는 것이다.
그냥 개인적인 궁금증에 대한 해결을 적어본 것이다..
2. 캐릭터와 카메라의 움직임을 구현할 때 필수
플레이어가 이동하거나 카메라가 캐릭터를 따라갈 때, 벡터 연산을 사용해야 한다.
벡터 덧셈을 이용해서 캐릭터가 움직이도록 만들 수 있다.
카메라가 부드럽게 따라오게 만들려면 벡터 보간(Lerp)을 사용해야 한다.
//W키를 누르면 앞쪽으로 이동
void Update() {
if(Input.GetKey(KeyCode.W)) {
transform.position += new Vector3(0, 0, 1) * Time.deltaTime * 5f;
}
transform.position += new Vector3(0, 0, 1)
여기에서 += 가 벡터 연산을 이용한 것이다. (벡터를 벡터끼리 연산하자!는 의미이다.)
3. 충돌 감지와 거리 계산
적과 플레이어와 가까워지면 공격하도록 만들려면 두 오브젝트 간의 거리를 계산해야 한다.
아래는 적과 플레이어의 거리 계산 코드이다.
//적이 플레이어를 감지하는 코드
float distance = Vector3.Distance(enemy.position, player.position);
if (distance < 5f) {
Debug.Log("플레이어 감지!");
}
여기에서 쓰이는 Vector3.Distance(a, b) 코드의 계산은
a와 b 사이의 직선 거리를 계산해서 float 값으로 반환하는 것인데,
내부적으로 계산하는 것이 아래 설명이다.
적이 (0,0,0), 플레이어가 (3,0,4)에 있다면 → 거리 = √(3² + 4²) = 5
이런 계산 방식을
a = enemy.position (적의 위치값)
b = player.position (플레이어의 위치값)
이렇게 대입해 계산하는 것이다.
그런 후에 조건식을 넣어 거리가 5f 보다 작으면
플레이어를 감지하는 것이다.
4. 물리 엔진과 방향 계산
물리적인 힘을 적용하거나, 총알이 날아가는 방향을 계산할 때 벡터 연산은 필수!
방향을 구할 때 Vector3.Normalize() 많이 사용한다.
플레이어가 적을 바라보는 방향! (A - B)
A = enemy.position
B = player.position
normalized는 위에서 계산 된 방향 벡터를 정규화한다.
정규화를 왜 하는 걸까?
방향만 계산하기 위해서이다!
정규화가 없다면 거리까지 반영된 벡터가 되어서,
총알을 쏜다면 속도가 거리마다 달라지게 된다.
일정한 총알 속도를 유지하기 위해서 사용하는 것이다.
//플레이어가 적을 향해 총을 쏠 때 방향 계산
Vector3 direction = (enemy.position - player.position).normalized;
bullet.velocity = direction * bulletSpeed;
5. 회전과 방향 전환
2D보다 3D에서 많이 쓰이는 것이다. 각도 계산하기 위해서이다.
Dot Product (내적) : 두 벡터의 유사도를 구할 때 사용
Cross Product (외적) : 두 벡터가 이루는 수직 방향을 구할 때 사용
//적이 플레이어를 보고 있는지 체크
Vector3 toPlayer = (player.position - enemy.position).normalized;
float dot = Vector3.Dot(enemy.forward, toPlayer);
if(dot > 0.5f) {
Debug.Log("적이 나를 보고 있다!)
}
기초 수학 개념
1. 좌표계와 벡터 개념
x축 : 왼쪽(-) 오른쪽(+)
y축 : 아래(-) 위(+)
z축 : 뒤(-) 앞(+)
2. 행렬과 변환
이동, 회전, 확대에 관한 기본 예제 코드이다.
transform.position += new Vector3(1, 0, 0); //X축으로 1만큼 이동
transform.rotation = Quaternion.Euler(0, 90, 0); //Y축을 기준으로 90도 회전
transform.localScale = new Vector3(2, 2, 2); //2배 확대
3. 삼각 함수와 회전
Sin, Cos, Tan 같은 삼각 함수를 활용해 움직임 구현
//펜들럼 움직임 (sin 함수)
void Update() {
float y = Mathf.Sin(Time.time) * 2.0f // -2 ~ 2 범위에서 반복한다.
transform.position = new Vector3(0, y, 0);
}
유니티에서의 수학 활용
1. 유니티 좌표계 이해
World 좌표 : 전역 위치
Local 좌표 : 부모 객체 기준 위치
Screen 좌표: 픽셀 단위 위치
Vector3 worldPos = transform.position; //월드 좌표
Vector3 localPos = transform.localPosition; //로컬 좌표
Vector3 screenPos = Camera.main.WorldToScreenPoint(transform.position); //스크린 좌표
2. Quaternion과 오일러 회전 비교
유니티에서 회전할 때 Quaternion을 쓴다.
부드럽게 회전하기 위해서는 Lerp보다 Slerp을 사용하는 편이다.
Slerp | 두 회전 사이를 부드럽게 이어주는 함수 |
Quaternion.Euler | 우리가 원하는 목표 회전값 |
Time.deltaTime | 한 프레임마다 조금씩 → 부드럽게 움직임 |
//두 회전 사이 부드러운 보간
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0, 90, 0), Time.deltaTime);
기존에 알고 있었지만, 다시 한번 복습하는 개념으로
유니티 기본 수학 물리에 대해서 다시 짚어보는 시간이었다.
기본적이면서도 많이 쓰이는 중요한 함수들이니 헷갈린다면
이 포스팅을 통해 다시 알고 가자!!!
(나에게 하는 말)
'Development > 멋쟁이사자처럼 게임개발 부트캠프' 카테고리의 다른 글
[멋쟁이사자처럼 Unity 게임 부트캠프 4기] 25일차 - 게임디자인패턴 : 싱글톤, 옵저버, 팩토리 (6) | 2025.04.13 |
---|---|
[멋쟁이사자처럼 Unity 게임 부트캠프 4기] 24일차 - URP 2D Light (0) | 2025.04.12 |
[멋쟁이사자처럼 Unity 게임 부트캠프 4기] 23일차 - Katana ZERO (4) (0) | 2025.04.08 |
[멋쟁이사자처럼 Unity 게임 부트캠프 4기] 22일차 - Katana ZERO (3) (4) | 2025.04.07 |
[멋쟁이사자처럼 Unity 게임 부트캠프 4기] 21일차 - Katana ZERO (2) (0) | 2025.04.03 |