2026-04-23 게임수학 — 삼각함수 · 내적 · 외적 + Ch3 팀프로젝트 킥오프
목차
오늘 한 일 요약
- 게임수학 강의 — 삼각함수·내적·외적 개념 + 응용 문제 풀이
- 내적으로 시야각 판정, 외적으로 좌우 판정하는 RPG 문제 풀이
- Ch3 팀프로젝트 킥오프 회의 (17:00) — 컨셉 확정, 역할 분담, 에셋 현황 공유
- 팀 GitHub 레포 생성 (
NBC_Ch3_TeamProject)
삼각함수 — 각도를 방향 벡터로
각도 θ가 있을 때 이동 방향을 2D 벡터로 변환하는 공식:
단위원 위의 점이 곧 단위 방향 벡터다.
| 각도 | cos θ | sin θ | 벡터 |
|---|
| 0° | 1 | 0 | (1, 0) → 오른쪽 |
| 90° | 0 | 1 | (0, 1) → 위 |
| 180° | -1 | 0 | (-1, 0) → 왼쪽 |
| 270° | 0 | -1 | (0, -1) → 아래 |
1
2
| // UE5: 각도로 이동 방향 구하기
FVector dir = FVector(FMath::Cos(AngleRad), FMath::Sin(AngleRad), 0);
|
내적 — 얼마나 같은 방향?
핵심 질문: 두 벡터가 얼마나 같은 방향을 가리키는가?
단위벡터끼리라면 크기가 1이므로:
| 결과값 | 의미 |
|---|
| 1.0 | 완전히 같은 방향 (0°) |
| 0.5 | 60° 차이 |
| 0.0 | 수직 (90°) |
| -0.5 | 120° 차이 |
| -1.0 | 완전히 반대 방향 (180°) |
각도 역산:
1
| cos θ = 0.5 → θ = arccos(0.5) = 60°
|
계산 방법
성분곱으로 계산:
1
2
3
| a = (ax, ay), b = (bx, by)
a · b = ax×bx + ay×by
|
예시: a = (3, 4), b = (5, 0)
1
| a · b = (3×5) + (4×0) = 15 + 0 = 15
|
게임 활용: 시야각 판정
전방 벡터와 적 방향 벡터의 내적 → cos 값 → 각도 범위 판단
1
2
3
4
5
6
| // 시야각 90° (±45°) 내에 적이 있는지 판정
float dot = FVector::DotProduct(ForwardVec, ToEnemyVec); // 단위벡터 가정
if (dot > FMath::Cos(FMath::DegreesToRadians(45.f))) // cos45° ≈ 0.707
{
// 적이 시야 안에 있음
}
|
핵심: 시야각이 좁을수록 cos 임계값이 1에 가까워진다.
| 시야각 | cos 임계값 | 조건 |
|---|
| ±30° | cos30° ≈ 0.866 | dot > 0.866 |
| ±45° | cos45° ≈ 0.707 | dot > 0.707 |
| ±60° | cos60° = 0.5 | dot > 0.5 |
외적 — 어느 쪽?
핵심 질문: b는 a의 왼쪽에 있는가, 오른쪽에 있는가?
1
| |a × b| = |a||b| sin θ (크기 = 평행사변형 넓이)
|
2D에서는 스칼라 부호로 방향을 판단한다 (y-up 기준):
| 결과 | 의미 |
|---|
| 양수 | b가 a의 왼쪽 (반시계) |
| 음수 | b가 a의 오른쪽 (시계) |
| 절댓값 | 평행사변형 넓이 |
2D 외적 계산
1
2
3
| a = (ax, ay), b = (bx, by)
a × b = ax×by − ay×bx
|
예시: a = (3, 4), b = (5, 0)
1
2
3
| a × b = (3×0) − (4×5) = 0 − 20 = -20
→ 음수 → b가 a의 오른쪽
→ |−20| = 20 → 평행사변형 넓이
|
왜 이 공식인가? 3D 외적의 z성분만 꺼낸 것:
1
2
3
| | i j k |
| ax ay 0 | → z성분 = ax×by − ay×bx
| bx by 0 |
|
게임 활용: 좌우 판정
1
2
3
4
5
| float cross = FVector::CrossProduct(ForwardVec, ToEnemyVec).Z;
if (cross > 0)
TurnLeft(); // 적이 왼쪽
else
TurnRight(); // 적이 오른쪽
|
벡터 정규화 (단위벡터)
방향만 남기고 크기를 1로 만들기:
1
| d̂ = 벡터 / |벡터| = (x/|v|, y/|v|)
|
예시: A = (4, 2)
1
2
3
| |A| = √(4²+2²) = √20 = √(4×5) = 2√5 ≈ 4.47
d̂_A = (4/2√5, 2/2√5) = (2/√5, 1/√5) ≈ (0.894, 0.447)
|
루트 간소화: 루트 안에서 완전제곱수(4, 9, 16…)를 꺼낸다.
1
2
3
| √20 = √(4×5) = 2√5
√18 = √(9×2) = 3√2
√45 = √(9×5) = 3√5
|
자주 쓰는 루트 근사값: √2 ≈ 1.414, √3 ≈ 1.732, √5 ≈ 2.236
문제 풀이 — RPG 시야각 판정
조건: 캐릭터 (0,0), 전방 f̂ = (1,0), 시야각 90° (±45°)
적: A=(4,2), B=(3,4), C=(-2,3), D=(5,-1)
Step 1: 정규화
| 적 | 크기 | d̂ (근사) |
|---|
| A | 2√5 ≈ 4.47 | (0.894, 0.447) |
| B | 5 | (0.6, 0.8) |
| C | √13 ≈ 3.61 | (-0.555, 0.832) |
| D | √26 ≈ 5.10 | (0.981, -0.196) |
Step 2: 내적 f̂·d̂
f̂ = (1,0) 이라 x성분만 남는다 (y항은 0이 곱해져서 사라짐):
1
| f̂·d̂ = (1×dx) + (0×dy) = dx
|
| 적 | f̂·d̂ | > 0.707? |
|---|
| A | 0.894 | ✅ |
| B | 0.600 | ❌ |
| C | -0.555 | ❌ |
| D | 0.981 | ✅ |
시야 내 적: A, D
Step 3: 좌우 판정 (f × d̂의 z성분)
f̂ = (1,0) 이라 f×d̂ = dy (x항이 사라짐):
1
2
| 적 A: f×d̂_A = 0.447 > 0 → 왼쪽
적 D: f×d̂_D = -0.196 < 0 → 오른쪽
|
시야 내 + 왼쪽: A
Ch3 팀프로젝트 킥오프 회의
| *일시: 2026-04-23 17:00 | 참석: 5인 전원* |
게임 컨셉 확정
| 항목 | 결정 |
|---|
| 컨셉 | Risk of Rain 2 × Space Marine 2 — 좀비 버전 |
| 장르 | TPS 웨이브 생존 + 로그라이트 업그레이드 |
| 세계관 | K-좀비 (도시 폐허 + 지하철) |
| 맵 구조 | 박스 아레나 |
| 시그니처 메카닉 | 처형 연쇄 — 체력 임계값 이하 좀비 처형 시 주변 경직 → 연속 처형 |
| 무기 구조 | 근접 고정 + 원거리 카드 획득 |
| 과열 시스템 | 원거리 과열 → 근접 강제 전환 → 냉각 후 복귀 |
| 카드 트리거 | 웨이브 클리어 후 3장 중 1장 선택 |
| 스테이지 | 5웨이브 → 보스 웨이브 |
| 비주얼 컨셉 | 리얼리스틱 (04/23 회의에서 확정) |
역할 분담
| 역할 | 담당자 | 핵심 시스템 | 난이도 |
|---|
| A — 플레이어 | 오성현 | TPS 컨트롤러, 무기 시스템, 과열 게이지 | 상 |
| B — AI | 장재봉 | 좀비 AI (BT), 웨이브 매니저, 보스 | 상 |
| C — 전투 | 신장식 | 히트 판정, 처형 연쇄, 애니메이션 연동 | 중~상 |
| D — 시스템 | 문창욱 | 카드/업그레이드, 게임 스테이트 | 중 |
| E — 환경/UI | 김하승 | 아레나 레벨, HUD, 에셋 셋업 | 하~중 |
역할 간 주요 의존 관계:
- A → C: 처형 트리거 인터페이스 제공
- A ↔ D: 카드 효과 수신 인터페이스 사전 합의 필요
- B → D: 웨이브 클리어 이벤트 발행 (카드 UI 트리거)
- A → E: 체력/탄약/과열 데이터 바인딩
Week 1 병렬 작업 가능: A, B, E 독립 시작 / C는 A 이후 / D는 B 이후
에셋 현황
| 카테고리 | 상태 | 주요 후보 |
|---|
| 환경 / 맵 | ✅ 충분 | Post Apocalyptic Urban City, Metro Subway, Warehouse |
| 플레이어 | ✅ | Mechanic Character Sarah |
| 좀비 / 적 | ⚠️ CRITICAL | 후보 2개 카툰풍 → 리얼리스틱 재탐색 필요 (04/28 기한, 신장식+장재봉) |
| 원거리 무기 | ✅ | FPS Weapon Bundle |
| 근접 콤보 | ✅ | Easy Combo Buffering |
| VFX | △ | Niagara Mega VFX Pack — 포함 이펙트 확인 필요 |
| 전투 HUD | ❌ | 추가 탐색 필요 |
기술 합의 안건
| 항목 | 옵션 A | 옵션 B |
|---|
| 처형 트리거 범위 | Sphere Overlap | Event Broadcast |
| 좀비 군집 렌더링 | Character AI × N | Procedural NPC Crowds 플러그인 |
| 카드 UI | 전투 일시정지 후 선택 | 별도 화면 (시간 멈춤) |
| 과열 게이지 | 무기별 독립 | 공유 단일 게이지 |
| 대량 좀비 목표 | 100마리 60fps | 50마리 60fps |
팀 레포 생성
- 레포:
GoldBoll/NBC_Ch3_TeamProject (GitHub) - 로컬 경로:
D:\Unreal\NBC_Ch3_TeamProject - 엔진: Unreal Engine 5.4 / C++ + Blueprint
- 개발 시작: 2026-05-01
- Week 1 완료 기준: 좀비 10마리 스폰 + 플레이어가 처치 가능
5/1 전 개인 준비 (오성현):
- Sarah 캐릭터 에셋 UE5.4 임포트 + 기본 동작 확인
- TPS 컨트롤러 구조 파악 (Third Person Template 기반)
- Enhanced Input System 키바인딩 초안
- 문창욱(D)과 카드 효과 인터페이스 방식 사전 합의
오늘 배운 것 정리
- 삼각함수 = 각도 → 방향 변환 도구.
(cos θ, sin θ)으로 어떤 각도든 단위벡터로 변환할 수 있다. - 내적 = 앞/뒤 판단. 단위벡터 내적값이 cos θ와 같으므로, 시야각 임계값을 cos으로 바꿔서 비교하면 된다.
- 외적 = 좌/우 판단. 2D 외적
ax×by − ay×bx의 부호만으로 어느 쪽인지 바로 알 수 있다. - f̂ = (1,0)일 때 계산 단순화. 내적은 x성분, 외적은 y성분만 남는다 — 전방이 축과 정렬되면 계산이 극단적으로 간단해진다.
- 수식 암기보다 “어떤 도구인가” 먼저. 내적·외적을 구분하는 질문: “방향이 얼마나 같냐(내적)” vs “어느 쪽에 있냐(외적)”.