✅ 1. FPS 게임의 화면 회전 구현 (1번 문제)
▶ 문제 대상
FPS 게임에서 마우스를 이용해 화면을 회전하게 하고, 키보드로 플레이어가 방향성으로 이동하도록 구현하는 문제.
▶ 도전 결과
CameraLook 함수 내 마우스 입력 처리에 오류가 발생. mouseDelta.x, mouseDelta.y가 어느 축을 기준으로 작용하는지 해결하지 못해 화면이 잘못된 방향으로 적용됨.
▶ 해결 절차
- 마우스 입력은 Vector2 mouseDelta로 받고, x는 좌/우 (Y축 회전), y는 상/하 (X축 회전)임을 확인.
- Unity에서 X축은 Pitch (상하), Y축은 Yaw (좌우)로 처리되며, 카메라는 로컬 회전(X), 플레이어는 글로벌 회전(Y)을 사용.
- mouseDelta.y를 camCurXRot에 누적하고 Clamp 해서 상하 각도를 제한.
- Player 오브젝트의 eulerAngles.y에 mouseDelta.x를 곱하여 회전 적용.
✅ 2. IDamagable 인터페이스를 통한 데미지 처리 (문제 2번)
▶ 문제 대상
CampFire 오브젝트가 일정 범위 안의 아군과 적에게 데미지를 주는 시스템을 구현해야 하며, 아군/적 유닛은 각각 IDamagable 인터페이스를 구현하고 있음.
▶ 도전 결과
각각의 유닛 타입을 직접 검사하거나 조건문으로 분기하려 했으나, 코드가 비효율적이고 다형성을 제대로 활용하지 못함. 인터페이스의 용도와 구조에 대한 이해 부족이 있었음.
▶ 해결 절차
- Ally.cs, Enemy.cs 클래스가 IDamagable을 구현하고 있는지 확인.
- CampFire.cs 내에서 List<IDamagable> 타입의 리스트를 선언하여 다형성 기반으로 관리.
- OnTriggerEnter(Collider other) 및 OnTriggerExit(Collider other)에서 TryGetComponent<IDamagable>을 통해 범위 내 객체를 감지 및 제거.
- InvokeRepeating을 사용하여 주기적으로 리스트 내의 모든 IDamagable 대상에게 TakePhysicalDamage(damage) 호출.
private List<IDamagable> things = new List<IDamagable>();
...
if (other.TryGetComponent(out IDamagable target))
{
things.Add(target);
}
...
things[i].TakePhysicalDamage(damage);
이 구조는 추후 중립 NPC나 구조물 등 추가 대상에도 쉽게 확장 가능함.
✅ 3. 게이지와 텍스트 UI 동기화 (문제 3번)
▶ 문제 대상
스킬 사용 시 남은 사용 횟수를 UI 게이지와 텍스트로 표시해야 하며, Image 컴포넌트와 TextMeshProUGUI를 사용함.
▶ 도전 결과
게이지가 항상 0으로 유지되고, 텍스트가 올바르게 표시되지 않음. 원인은 정수형 나눗셈에서 float 캐스팅이 빠졌기 때문임.
▶ 해결 절차
- remainSkillCnt, maxSkillCnt가 int형이므로 float형으로 캐스팅하지 않으면 fillAmount가 0이 됨.
- TextMeshPro는 string만 받으므로 $"{remainSkillCnt} / {maxSkillCnt}" 형식으로 출력.
- 각 값이 변경될 때마다 UI를 갱신하도록 SetSkillUI() 메서드에서 일괄 처리.
remainGaugeBar.fillAmount = (float)remainSkillCnt / maxSkillCnt;
remainText.text = $"{remainSkillCnt} / {maxSkillCnt}";
✅ 4. 시점 전환 시 동일한 Ray 처리 (문제 4번)
▶ 문제 대상
1인칭 시점에서는 화면 중앙 기준으로, 3인칭 시점에서는 특정 포인트 기준으로 정면을 Ray로 감지하는 로직 작성. Ray의 origin과 direction이 동일하게 유지되어야 함.
▶ 도전 결과
1인칭에서 ScreenPointToRay를 쓰면서도 3인칭에서는 다른 기준을 사용해 Ray의 방향이 어긋났음. Camera와 기준 Transform의 위치 및 회전 상태에 대한 이해가 부족했음.
▶ 해결 절차
- 1인칭 시점에서는 카메라의 중앙 픽셀 기준으로 ScreenPointToRay() 사용.
- 3인칭 시점에서는 기준 Transform(=interactionRayPointTransform)의 위치와 forward 방향을 사용해 new Ray() 생성.
- 구성 상 두 기준의 위치 및 회전이 동일하므로, Ray의 결과가 일치하게 됨.
✅ 5. Coroutine 흐름과 중단 타이밍 (문제 5번)
▶ 문제 대상
코루틴 실행 중 Invoke를 통해 동일 코루틴이 다시 시작될 경우, 이전 코루틴은 어떤 시점에서 중단되고 어떤 로그가 출력되는지 확인.
▶ 도전 결과
Console에 a, b, a, b, c 순으로 로그가 찍혀야 했으나, 중간 StopCoroutine의 동작 시점을 이해하지 못해 예상 결과가 어긋남.
▶ 해결 절차
- Start에서 첫 코루틴 실행 → "a" 출력 → yield null → 다음 프레임에 "b" 출력
- 1초 후 Invoke로 다시 StartTestCoroutine() 호출되며 이전 코루틴 중단됨 → "c"는 출력되지 않음
- 새 코루틴 실행 → "a" 출력 → yield null → "b" 출력 → 3초 후 "c" 출력
최종 출력: a, b, a, b, c
✅ 6. 싱글톤 패턴과 금액 포맷 (문제 6번)
▶ 문제 대상
MoneyManager 싱글톤 구현 및 금액을 1만 단위로 문자열 포맷팅하는 기능 구현
▶ 도전 결과
싱글톤 패턴의 핵심인 static, this, DontDestroyOnLoad 순서 및 의미를 제대로 기억하지 못했음. 또한 금액 포맷 시 단위별 처리 로직도 불완전했음.
▶ 해결 절차
- A: static → 클래스 변수로 전역 접근
- B: this → 현재 객체 참조
- C: DontDestroyOnLoad(gameObject) → 씬 이동 간 유지
- FormatMoney: 10000 단위로 나누며 각 단위별 문자열을 결합
✅ 7. 특정 라이트 색상에서만 보이는 오브젝트 (문제 7번)
▶ 문제 대상
라이트의 색상이 특정 오브젝트의 reactionColor와 일치할 때만 해당 오브젝트를 보이게 설정하는 기능 구현. Raycast로 감지된 오브젝트만 보이게 해야 함.
▶ 도전 결과
Renderer를 껐다 켜는 방식에서 .enabled 속성을 착각했으며, RaycastAll 사용 시 조건 설정을 제대로 하지 않아 LayerMask 필터링이 누락됨.
▶ 해결 절차
- Renderer의 보이기 여부는 .enabled 속성으로 조절함
- 라이트 색상 비교는 lanternLight.color를 사용해 reactionColor와 비교
- RaycastAll의 인자는 (origin, direction, distance, layerMask) 순으로 정확히 작성해야 함
💬 느낀 점
당일 배치고사는 기능 구현을 넘어서 Unity의 해당 개념들을 실제 코드만으로 어떻게 적용할 수 있는지를 깊이 고민하게 해주었다. 특히 인터페이스 기반 구조 설계(IDamagable), Coroutine 흐름 중단 타이밍, Ray 시스템의 정확한 원리 등은 그동안 알고 있다고 생각했지만 실제로는 이해가 부족했다는 것을 체감했다.
또한, UI와 관련된 문제들(게이지 업데이트, 문자열 포맷 등)은 평소 간단하게 지나쳤던 과정이 모두 올바른 문법과 구조와 관련이 있어 다시금 개별적으로 신경 써야 함을 느꼈다. 작지만 중요한 로직의 차이가 전체 결과에 큰 영향을 준다는 점에서 앞으로 디버깅 시 더 정밀한 시선이 필요하다고 느꼈다.
마지막으로 싱글톤 패턴은 매우 자주 사용되는 구조지만, 정확한 초기화 조건 및 DontDestroyOnLoad 처리를 반드시 고려해야 한다는 교훈을 얻었다. 전반적으로 매우 유익했고, 실전에서 자주 마주치는 개념들을 복습하고 정리할 수 있는 유용한 기획이었다.
'팀스파르타 내일배움캠프' 카테고리의 다른 글
| Unity UI Panel 개발 - 문제해결 과정 (1) | 2025.06.12 |
|---|---|
| 📝 [TIL] 2025-06-04 (수) - ATM UI 시스템 구현 (2) | 2025.06.04 |
| 🧗 JumpKing 3D - Unity 과제 최종 TIL (0) | 2025.05.23 |
| 🎮 Unity 개인 과제 – 점프킹 3D 기능 구현 완료 (1) | 2025.05.23 |
| 📌 Unity에서 인스펙터 드래그 앤 드롭보다 코드 구독이 선호되는 이유 정리 (6) | 2025.05.22 |