no image
프로젝트 소개 - 「현대세계 최후의 궁수」
🎮 1. 게임 소개이번 프로젝트는 '궁수의 전설(Archero)'에서 영감을 받아 제작한 탑다운 슈팅 기반의 액션 게임입니다.현대 세계를 배경으로, 마지막 남은 궁수가 되어 적들을 물리치고 스테이지를 클리어하는 것이 목표입니다.게임의 제목은 **「현대세계 최후의 궁수」**입니다.유저는 다양한 무기와 스킬을 활용하여 몬스터와 보스를 처치하고, 방을 클리어하며 점점 더 강해지는 전투를 경험할 수 있습니다.🕹️ 2. 플레이 방법이동 조작 : W, A, S, D 키로 캐릭터를 상하좌우로 움직입니다.공격 조작 : 마우스 좌클릭으로 공격합니다. 자동 발사 방식이 아니며, 직접 눌러야 발사됩니다.스킬 선택 : 방을 클리어할 때마다 3개의 스킬 중 하나를 무작위로 선택하여 강화할 수 있습니다.스테이지 진행 : 각 ..
2025.08.05
no image
내일배움캠프 26일차 TIL [팀프로젝트(Archero)]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 11:00 : StageChangeTrigger 조건문 로직 디버깅11:00 ~ 12:30 : MonsterSpawnManager 개선 (스폰 포인트별로 몬스터 순차 소환 / 프리팹 랜덤)🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 15:30 : 카메라와 Canvas 연결 이슈 해결 (CanvasCameraSetter.cs)15:30 ~ 17:00 : MainCamera 정리 및 Orthographic vs Perspective 비교 학습17:00 ~ 18:00 : GitHub 커밋 히스토리 기반 금요일/월요일 작업 정리, 스크립트 구조 설계 리팩토링🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 21:00 : ..
2025.08.04
no image
Unity - Unity의 메인 카메라(Main Camera) & Projection
🎥 Unity의 메인 카메라(Main Camera)란?✅ 1. 기본 정의Unity 씬(Scene)에서 **플레이어가 보는 시점(Viewport)**을 결정하는 렌더링 카메라기본적으로 Main Camera 태그를 가진 GameObject로 자동 생성됨Camera.main 으로 쉽게 접근할 수 있음 (GameObject.FindWithTag("MainCamera")의 성능 최적화 버전)✅ 2. Camera 주요 설정속성설명Clear Flags배경을 어떻게 처리할지 결정 (Skybox, Solid Color, Depth Only, Don't Clear)Culling Mask어떤 레이어의 오브젝트만 렌더링할지 선택Projection카메라 투영 방식 (Perspective: 원근, Orthographic: 평면..
2025.08.04
no image
WIL - 본 캠프 5주차(25.07.28~08.01)
1. 이번 주 가장 인상 깊었던 배움은 무엇이었나요?Skill & Upgrade System을 ScriptableObject 기반으로 설계하고, 실제 게임 흐름에 연동시켜본 경험이 가장 인상 깊었다.그동안 ScriptableObject를 단순 데이터 저장 용도로만 이해하고 있었는데, 이번 주에는 게임 흐름 안에서 그 데이터를 실시간으로 불러오고 UI와 연동해, 유저가 스킬을 선택하고 실제로 적용되도록 구현해봤다.특히 방을 클리어할 때 무작위 스킬 카드들이 뜨고, 선택된 스킬이 플레이어 능력치나 특성에 영향을 미치는 흐름을 만들면서,단순한 데이터 보관이 아니라 확장성과 유지보수를 고려한 설계 방식이라는 걸 직접 체감했다.단순히 기능을 넣은 것이 아니라, UI 흐름과 연계하고 PlayerState에 적용되도..
2025.08.04
no image
내일배움캠프 25일차 TIL [팀프로젝트(Archero)]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : GitHub 커밋 및 기능 구현보스 일반 공격 충돌 문제 해결스테이지 클리어 UI 기능 마무리보스 중력 및 히트 애니메이션, 붉은색 피격 효과 적용몬스터 사운드, 파티클, HP Bar 상호작용 기능 추가 및 수정튜토리얼 관련 버그 수정 및 기능 개선StageChangeButton 관련 로직 개선 시도🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 18:00 :몬스터 FSM과 SpawnManager 연결 로직 점검스테이지 전환 중 클리어 처리 예외 상황 확인보스 태그/프리팹 설정 및 애니메이션 처리 개선GitHub 정리 및 커밋 다수 진행🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 21:00 : 팀원..
2025.08.01
no image
내일배움캠프 24일차 TIL [팀프로젝트(Archero)]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 12:00 :MonsterSpawnManager 수정 및 커밋Skill&UpgradeSystem_LeeJaeEun 브랜치 병합MainScene UI 테스트 및 사운드 추가Read-Only 애니메이션 클립 복제 방법 팀원에게 설명애니메이션 전환 부드럽게 하기 위한 Transition Duration 값 수정🍽️ 점심시간12:00 ~ 13:00 : 점심시간✅ 오후13:00 ~ 18:00 :SkillTutorialUIManager 코루틴 오류 해결 (SetActive(true) 및 currentIndex = 0)스킬 튜토리얼 UI 순차 출력 구현 및 수정GameManager 튜토리얼 로직 최종 수정Main 브랜치의 MainScene 최종 통합 및 테스트🍽️ 저녁시..
2025.07.31
no image
내일배움캠프 23일차 TIL [팀프로젝트(Archero)]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 12:30 :CameraManager 스크립트 구조 설계 및 기본 구현2.5D 스타일 카메라 구현 (Z축만 따라가고 X축/Y축 고정)타이틀 상태에서는 고정 위치로 이동하도록 상태 분기 처리followOffset 도입으로 플레이어가 카메라 중앙쯤 보이게 조정🍽️ 점심시간12:30 ~ 13:30 : 점심시간✅ 오후13:30 ~ 18:00 :카메라 X축 고정 방식 개선: GameState.Playing 상태마다 X값 갱신되도록 변경lastState 도입으로 상태 전환 감지 구현GameManager → CameraManager로 ResetFixedX() 직접 호출하는 구조 설계playerTransform 참조 오류 해결 (null 방지 처리: FindWithTag("..
2025.07.30
no image
내일배움캠프 22일차 TIL [팀 프로젝트(Archero)]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:00 : Unity 입문 프로젝트 발제 자료 확인10:00 ~ 11:00 : Unity 강의 수강 (입문 프로젝트 소개 중심)11:00 ~ 13:00 : 팀 회의 및 주제 결정 (궁수의 전설 기반), 역할 분담🍽️ 점심시간13:00 ~ 14:00 : 점심식사✅ 오후14:00 ~ 16:00스킬 UI 시스템 개발 (ScriptableObject 기반)무작위 스킬 표시 기능 구현Horizontal Layout Group의 Spacing 조절로 겹침 문제 해결팀원 보스 기능 개발 보조 (콜라이더, Rigidbody, 애니메이터 구성 도움)16:00 ~ 18:00챌린지반 특강 2회차 수강: 메모리 구조🍽️ 저녁시간18:00 ~ 19:00 : 저녁 식사 및 휴식✅..
2025.07.29
반응형

🎮 1. 게임 소개

이번 프로젝트는 '궁수의 전설(Archero)'에서 영감을 받아 제작한 탑다운 슈팅 기반의 액션 게임입니다.
현대 세계를 배경으로, 마지막 남은 궁수가 되어 적들을 물리치고 스테이지를 클리어하는 것이 목표입니다.
게임의 제목은 **「현대세계 최후의 궁수」**입니다.
유저는 다양한 무기와 스킬을 활용하여 몬스터와 보스를 처치하고, 방을 클리어하며 점점 더 강해지는 전투를 경험할 수 있습니다.


🕹️ 2. 플레이 방법

  • 이동 조작 : W, A, S, D 키로 캐릭터를 상하좌우로 움직입니다.
  • 공격 조작 : 마우스 좌클릭으로 공격합니다. 자동 발사 방식이 아니며, 직접 눌러야 발사됩니다.
  • 스킬 선택 : 방을 클리어할 때마다 3개의 스킬 중 하나를 무작위로 선택하여 강화할 수 있습니다.
  • 스테이지 진행 : 각 방을 클리어하면 자동으로 다음 방으로 이동되며, 최종 방에서는 보스가 등장합니다.

🛠 3. 사용 기술

본 프로젝트는 Unity 엔진을 기반으로 개발되었으며, 다음과 같은 기술들을 활용하였습니다:

  • Unity 2022.3.4f1 : 프로젝트 전체 구성 및 게임 구현
  • C# : 게임 로직 전반 구현
  • GitHub : 협업을 위한 형상 관리 및 버전 관리
  • ScriptableObject : 스킬 데이터 관리 및 확장성 있는 구조 구성
  • Singleton + Manager Pattern : GameManager, SoundManager 등 핵심 매니저 구조 설계
  • FSM 기반 보스 AI : 상태 전이에 따라 공격, 이동, 스킬 등을 제어
  • 랜덤 방 생성 알고리즘 : 던전 구조를 무작위로 생성하여 반복 플레이 요소 강화
  • 2D Sprite Animation : 플레이어 및 적 애니메이션 구현
  • Sound System : BGM 및 효과음 관리

✨ 4. 주요 구현 기능

  • 무작위 스킬 선택 시스템
    방을 클리어할 때마다 3개의 스킬 중 1개를 선택해 능력을 강화할 수 있으며, ScriptableObject 기반으로 유연하게 확장 가능합니다.
  • 스테이지 클리어 흐름 및 UI 연결
    플레이어가 모든 몬스터를 처치하면 스테이지가 클리어되고, 이후 보상 및 다음 스테이지로 자연스럽게 넘어가는 구조를 구현하였습니다.
  • 보스 패턴 구현
    FSM 구조를 기반으로 한 보스의 다양한 패턴 공격과 애니메이션 전환 로직을 구현하였습니다.
  • 사운드 매니저 및 효과음 시스템
    배경음과 효과음을 상황에 따라 다르게 출력하고, 중복 재생 방지 및 볼륨 설정 기능을 추가하였습니다.

🖼 5. 게임 화면

아래는 실제 게임 실행 화면 일부입니다. 플레이어 조작, 스킬 선택, 보스전, UI 구성이 포함된 장면으로, 다양한 게임 요소들이 조화를 이루도록 구현하였습니다.

  • 기본 전투 화면: 플레이어가 적을 향해 자동으로 공격하며, 일정 시간마다 보조 스킬을 사용할 수 있도록 구성하였습니다.
  • 스킬 선택 UI: 스테이지 클리어 시 3개의 스킬 중 1개를 선택하여 성장하는 방식이며, 시각적 피드백을 강화한 UI 디자인으로 몰입감을 높였습니다.
  • 보스 전투 화면: 보스의 다양한 공격 패턴이 적용되며, 체력 바 및 연출이 강화된 별도 스테이지에서 진행됩니다.
  • 게임 클리어 화면: 최종 보스를 처치하면 승리 연출과 함께 엔딩 씬으로 전환됩니다.
  • 타이틀 화면, 튜토리얼 화면 등등..

 

설명 추가 되어있는 영상

 

짧은 설명 X 영상

 


📂 6. 프로젝트 폴더 구조

📦 02. Scripts/
├── 📂Boss/ # 보스 관련 제어 스크립트
│ ├── Axe.cs # 보스 무기 충돌 감지
│ ├── BossController.cs # 보스 상태 전이 및 FSM
│ └── BossHpBar.cs # 보스 체력 UI
├── 📂Camera/
│ └── CanvasCameraSetter.cs # UI 캔버스에 메인 카메라 자동 연결
├── 📂Manager/ # 전역 시스템 관리자 클래스들
│ ├── 📂Camera/
│ │ └── CameraManager.cs
│ ├── 📂Monster/
│ │ └── MonsterSpawnManager.cs
│ ├── 📂PlayerSpawn/
│ │ └── PlayerSpawnManager.cs
│ ├── 📂Skill/
│ │ └── SkillManager.cs
│ ├── 📂Sound/
│ │ ├── PlayerSound.cs
│ │ └── SoundManager.cs
│ ├── 📂Stage/
│ │ ├── NextStageParticle.cs
│ │ └── StageManager.cs
│ ├── 📂Tutorial/
│ │ └── SkillTutorialUIManager.cs
│ ├── 📂UI/
│ │ ├── 📂Player/
│ │ │ ├── PlayerHpBar.cs
│ │ │ └── PlayerStatUI.cs
│ │ ├── 📂SettingUI/
│ │ │ └── SoundUI.cs
│ │ ├── 📂Skill/
│ │ │ └── SkillUIManager.cs
│ │ ├── 📂Tutorial/
│ │ │ └── TutorialSlotUI.cs
│ │ └── UIManager.cs
│ └── GameManager.cs # 게임 전반 흐름 관리
├── 📂Monster/ # 일반 몬스터 AI 및 전투 관련 스크립트
│ ├── Melee_Damage.cs
│ ├── MonsterFSM.cs
│ ├── MonsterHpBar.cs
│ ├── MonsterParticleControl.cs
│ ├── MonsterProjectile.cs
│ └── MonsterStat.cs
├── 📂Player/ # 플레이어 조작 및 상태 관리
│ ├── Bullet.cs
│ ├── PlayerMovement.cs
│ ├── PlayerShooting.cs
│ └── PlayerStat.cs
├── 📂ScriptableObject/ # 스킬 데이터 저장용 ScriptableObject
│ └── SkillData_ScriptableObject.cs
├── 📂Singleton/ # 제너릭 싱글톤 베이스 클래스
│ └── Singleton.cs
├── 📂Sound/ # 사운드 재생 소스
│ └── SoundSource.cs
├── 📂Stage/ # 스테이지 전환 로직
│ └── StageChanger.cs
├── 📂Test/ # 테스트 및 디버깅용
│ ├── End.cs
│ └── TimeController.cs
├── 📂UI/ # UI 관련 스크립트
│ ├── 📂Animation/
│ │ └── UIAnimationHandler.cs
│ ├── 📂Production/
│ │ └── Siren.cs
│ ├── 📂Skill/
│ │ └── SkillSlotUI.cs
│ └── 📂Title/
│ ├── StageChangeButton.cs
│ └── StateChangeButton.cs
├── 📂Utils/ # 유틸리티 스크립트
└── └── EnemyUtil.cs

 


👤 7. 개발자

이름 역할 담당 업무 요약
이재은 팀장 스킬 및 업그레이드 시스템 구현, UI 시스템 제작, 전체 프로젝트 구조 설계 및 총괄
김용민 팀원 랜덤 방 생성 로직 구현, 배경 및 사운드 전반 설정
정세윤 팀원 보스전 로직 설계 및 구현 (AI, 애니메이션 전환, 보스 연출 등)
김유경 팀원 적 AI 설계, 공격 패턴 작성 및 난이도 조정
김노아 팀원 플레이어 이동 및 공격 시스템 구현, QA 테스트 및 전반적 기능 보완

🛠 8. 트러블슈팅 (문제 해결 기록)

 

 

👤 9. 자체 평가 의견

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 11:00 : StageChangeTrigger 조건문 로직 디버깅
  • 11:00 ~ 12:30 : MonsterSpawnManager 개선 (스폰 포인트별로 몬스터 순차 소환 / 프리팹 랜덤)

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심시간

✅ 오후

  • 14:00 ~ 15:30 : 카메라와 Canvas 연결 이슈 해결 (CanvasCameraSetter.cs)
  • 15:30 ~ 17:00 : MainCamera 정리 및 Orthographic vs Perspective 비교 학습
  • 17:00 ~ 18:00 : GitHub 커밋 히스토리 기반 금요일/월요일 작업 정리, 스크립트 구조 설계 리팩토링

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁시간

✅ 저녁

  • 19:00 ~ 21:00 : 팀원들과 함께 프로젝트 결과 보고서 작성
  • 21:00 ~ 22:00 : 트러블슈팅 정리 (제너릭 싱글톤 적용 / ScriptableObject 스킬 시스템 구조 정리)

✅ 오늘 학습 키워드

 

Unity - Unity의 메인 카메라(Main Camera) & Projection

🎥 Unity의 메인 카메라(Main Camera)란?✅ 1. 기본 정의Unity 씬(Scene)에서 **플레이어가 보는 시점(Viewport)**을 결정하는 렌더링 카메라기본적으로 Main Camera 태그를 가진 GameObject로 자동 생성됨Camera.main

dev-jen.tistory.com

  • StageChangeTrigger 조건문 수정 및 디버깅
  • 몬스터 스폰 방식 개선 (스폰 포인트 순서대로 / 프리팹 랜덤)
  • Canvas에 MainCamera 자동 할당 (CanvasCameraSetter.cs)
  • MainCamera와 UI RenderMode 간 연동 구조 이해
  • 3D에서 Orthographic 카메라 사용 시의 효과
  • GitHub 커밋 로그 기반 개발 작업 히스토리 정리
  • 스크립트 폴더 구조 시각화 및 역할별 분류

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

오늘은 주로 게임 흐름과 UI, 몬스터 스폰 관련 시스템을 다듬는 데 집중했다.

우선 StageChangeTrigger에서 조건식 오류가 있어,

스킬 UI가 불필요한 스테이지에서도 출력되는 문제를 발견하고 조건문을 다시 점검했다.

기존에는 ||(or) 연산자를 사용해서 항상 true가 되는 구조였기 때문에 &&로 바꾸는 식으로 로직을 수정했다.

또한, MonsterSpawnManager에서는 기존에 몬스터가 스폰 포인트에 무작위로 겹쳐 나오는 문제가 있었는데,

스폰 위치는 고정(순차적), 몬스터 프리팹은 랜덤하게 생성되도록 구조를 바꿨다.

이후 다시 겹치지 않도록 로직을 다듬으면서 각 스테이지별 마릿수도 조정했다.

UI 쪽에서는 Canvas의 RenderMode가 Screen Space - Camera일 때

MainCamera가 수동으로 연결되지 않아 발생하는 문제를 해결하기 위해,

CanvasCameraSetter.cs 스크립트를 만들어 자동 연결되도록 처리했다.

이를 통해 씬 내 모든 Canvas들이 메인 카메라를 자동 참조하게 되어 UI 출력 문제가 해소되었다.

그리고 Camera 설정에서 Orthographic 모드와 Perspective 모드의 차이도 실제 씬을 통해 확인했다.

Orthographic은 3D 환경에서도 깊이감이 없이 평면적으로 보이기 때문에,

UI나 미니맵처럼 깊이 정보가 필요 없는 영역에 적합하다는 걸 알게 되었다.

마지막으로 GitHub 커밋 로그를 정리하면서 금요일~오늘까지의 작업 흐름을 팀원들과 함께 정리했고,

전체 스크립트 폴더 구조를 정돈하면서 각 스크립트가 어떤 역할을 하는지 다시 정리해보는 시간을 가졌다.


🧩 학습하며 겪었던 문제점 & 에러

1. 스킬 UI가 불필요한 스테이지에서 출력되는 문제

  • 문제정의: StageChangeTrigger에서 스킬 UI를 출력하는 조건이 잘못되어, Boss, Tutorial, MainStage에서도 스킬 UI가 계속 뜨는 현상이 발생함.
  • 시도: ||(or) 연산자를 사용해서 특정 스테이지가 아닐 때 UI를 띄우려 했지만, 조건이 항상 true로 작동함.
  • 해결 방법:
  • // 잘못된 코드 if(GameManager.Instance.CurrentStage != StageType.Boss || GameManager.Instance.CurrentStage != StageType.Tutorial) // 수정된 코드 if (GameManager.Instance.CurrentStage != StageType.Boss && GameManager.Instance.CurrentStage != StageType.Tutorial && GameManager.Instance.CurrentStage != StageType.MainStage) { SkillUIManager.Instance.ShowSkillUI(); }
  • 새롭게 알게 된 점: ||를 사용할 경우 어느 하나만 참이어도 전체 조건이 참이 되므로, "모두 아닐 때"의 조건엔 &&를 써야 정확함.
  • 다시 만나게 된다면: 조건문은 먼저 논리적으로 반례를 떠올려보고, 필요한 경우 Debug로 흐름을 직접 찍어보자.

2. 몬스터가 스폰 포인트에 겹쳐서 생성되는 문제

  • 문제정의: MonsterSpawnManager에서 몬스터가 랜덤 위치에 랜덤하게 스폰되다 보니, 동일 위치에 여러 마리가 겹치는 경우 발생.
  • 시도: 위치와 프리팹 모두 랜덤 선택 → 스폰 위치는 고정, 프리팹만 랜덤으로 조정.
  • 해결 방법:
  • for (int i = 0; i < spawnPoints.Length; i++) { int prefabIndex = Random.Range(0, monsterPrefabs.Length); Transform spawnPoint = spawnPoints[i]; GameObject prefabToSpawn = monsterPrefabs[prefabIndex]; GameObject monster = Instantiate(prefabToSpawn, spawnPoint.position, Quaternion.identity); spawnedMonsters.Add(monster); }
  • 새롭게 알게 된 점: 랜덤 스폰도 조건에 따라 순서를 고정하거나, 위치 중복을 제한하는 로직이 필요함.
  • 다시 만나게 된다면: 상황에 따라 “랜덤성”과 “질서”의 균형이 필요함을 염두에 두자.

📝 메모

오늘은 팀 프로젝트의 거의 마무리 단계에서 각종 UI 조건 처리나 몬스터 스폰 방식 같은 세세한 부분들을 계속 다듬었고, 결과적으로 훨씬 완성도 있는 흐름이 만들어진 것 같아서 뿌듯하다. 특히 조건문에서 자주 쓰는 ||와 &&의 차이를 다시금 체감했고, 작은 실수가 전체 흐름을 망칠 수 있다는 걸 또 배웠다.

또한, 겹침 없이 몬스터가 순서대로 등장할 수 있도록 고정된 포인트를 활용한 구조가 적용되면서, 전투의 시작이 더 자연스러워졌다.

무엇보다 오늘은 팀원들과 마지막까지 함께 앉아 결과보고서를 정리했다. 각자 기능을 담당하면서도 끝까지 책임감을 갖고 마무리한 게 느껴졌고, 서로서로 수고했다는 말 한마디가 참 고맙고 따뜻했다.

이제 마지막 피드백만 잘 반영하고 마무리까지 멋지게 달려보자!

끝날 때까지 끝난 게 아니다. 내일도 화이팅!!!! 🌟


테스트 이미지

반응형
반응형

🎥 Unity의 메인 카메라(Main Camera)란?

✅ 1. 기본 정의

  • Unity 씬(Scene)에서 **플레이어가 보는 시점(Viewport)**을 결정하는 렌더링 카메라
  • 기본적으로 Main Camera 태그를 가진 GameObject로 자동 생성됨
  • Camera.main 으로 쉽게 접근할 수 있음 (GameObject.FindWithTag("MainCamera")의 성능 최적화 버전)

✅ 2. Camera 주요 설정

속성 설명
Clear Flags 배경을 어떻게 처리할지 결정 (Skybox, Solid Color, Depth Only, Don't Clear)
Culling Mask 어떤 레이어의 오브젝트만 렌더링할지 선택
Projection 카메라 투영 방식 (Perspective: 원근, Orthographic: 평면)
Field of View 시야각 (Perspective일 때만 적용)
Clipping Planes 카메라가 렌더링할 최소/최대 거리
Depth 여러 카메라가 있을 때 그리는 순서 (높을수록 위에 그려짐)
Target Texture RenderTexture에 출력하고 싶을 때 사용 (예: 포탈, CCTV 효과)

✅ 3. 카메라 제어 예시

🎮 플레이어 따라가기

public class FollowCamera : MonoBehaviour
{
    public Transform target;
    public Vector3 offset;

    void LateUpdate()
    {
        if (target != null)
            transform.position = target.position + offset;
    }
}

🎞 카메라 흔들기 (Shake)

public IEnumerator CameraShake(float duration, float magnitude)
{
    Vector3 originalPos = transform.localPosition;

    float elapsed = 0f;
    while (elapsed < duration)
    {
        float x = Random.Range(-1f, 1f) * magnitude;
        float y = Random.Range(-1f, 1f) * magnitude;

        transform.localPosition = new Vector3(x, y, originalPos.z);
        elapsed += Time.deltaTime;
        yield return null;
    }

    transform.localPosition = originalPos;
}

✅ 4. 메인 카메라 관련 실전 예시

예시 설명
2D 게임 Orthographic 투영 사용, 플레이어를 따라다니며 흔들림 없음
3D 게임 Perspective 투영 사용, 자유 시점 회전, 줌 인/아웃
미니맵 별도 카메라 사용 + RenderTexture
포탈/거울 카메라 + RenderTexture + RawImage 사용

✅ 5. 자주 하는 실수

  • 카메라가 씬에 두 개 이상 있을 때, Camera.main은 가장 먼저 찾은 MainCamera 태그만 사용함 → 명확한 참조 권장
  • 카메라 Depth 설정 안 해서 UI용 카메라가 게임 씬을 덮어버리는 경우 발생
  • 클리핑 거리 조정 실패 → 너무 멀거나 가까운 물체가 안 보이는 경우

🧠 마무리 정리

개념 기억 포인트
Main Camera 태그 Camera.main 접근 대상
Projection 설정 2D: Orthographic / 3D: Perspective
이동 LateUpdate로 자연스럽게 따라가기
다중 카메라 Depth, Culling Mask, RenderTexture 활용
최적화 너무 많은 카메라 활성화는 성능 저하 가능

 

 

🎯 3D에서 Orthographic 카메라를 쓰면?

✅ 핵심 효과

  • **원근감(Perspective)**이 없어진다
  • 카메라와의 거리에 상관없이 모든 오브젝트가 같은 크기로 보인다
  • 멀리 있는 물체도 작아지지 않음
  • 투시 왜곡 없음 → 마치 2D처럼 보이는 3D

👀 비교 예시

항목 Perspective (원근) Orthographic (직교)
가까운 물체 크게 보임 동일하게 보임
먼 물체 작게 보임 동일하게 보임
시야각 Field of View 설정 Size로 보기 범위 설정
대표 사용 일반 3D 게임, FPS, 3인칭 등 전략 시점, 건축 시뮬, 퍼즐, 등각 뷰 게임 등
 

🎮 시각적 차이 예시

  • Perspective
    캐릭터 앞에 있는 적은 큼직하게, 멀리 있는 적은 작게 보임 → 자연스러운 현실 느낌
    예: FPS, RPG
  • Orthographic
    앞에 있는 적이든, 멀리 있는 적이든 크기가 똑같이 보임 → 깊이 구분이 없음
    예: 전통적 RTS, 스타듀밸리 같은 탑뷰, 건축 프리뷰, 에디터 툴

🧪 Unity 실습: 전환 방법

Camera.main.orthographic = true;      // 직교 투영 모드로 전환
Camera.main.orthographicSize = 5f;    // 보이는 영역 범위 조정

🧠 언제 Orthographic을 쓰면 좋을까?

쓰면 좋은 경우 이유
등각뷰 게임 (ex: 시뮬레이션, 탑뷰 퍼즐) 모든 오브젝트를 동일한 크기로 정밀하게 보여주고 싶을 때
건축/에디터 툴 정확한 위치 비교와 거리감 없는 작업이 필요할 때
2.5D 게임 3D 모델을 사용하지만 카메라 뷰는 2D처럼 고정할 때

 


✅ 요약

  • Orthographic은 원근이 없는 평면적 시점
  • 3D 씬에서도 2D처럼 연출 가능
  • 객체가 카메라에서 멀어져도 크기 변화 없음
  • 2D UI 느낌이나 등각뷰 게임에 적합

 

사실 이걸 작성하는건 이번에 궁수의 전설 모티브로 2.5D 게임을 만들었어야 했는데 어떻게해도 잘 안됐었다..그러다보니 3D 메인 카메라에서 Orhographic을 쓰면 된다고 그러길래 해봤더니..완벽했다 허허.. 새로운걸 하나 배워간다.

왼쪽은 Projection - Perspective 오른쪽은 Projection - Orhograpihc

 

반응형
반응형

1. 이번 주 가장 인상 깊었던 배움은 무엇이었나요?

Skill & Upgrade System을 ScriptableObject 기반으로 설계하고, 실제 게임 흐름에 연동시켜본 경험이 가장 인상 깊었다.

그동안 ScriptableObject를 단순 데이터 저장 용도로만 이해하고 있었는데, 이번 주에는 게임 흐름 안에서 그 데이터를 실시간으로 불러오고 UI와 연동해, 유저가 스킬을 선택하고 실제로 적용되도록 구현해봤다.

특히 방을 클리어할 때 무작위 스킬 카드들이 뜨고, 선택된 스킬이 플레이어 능력치나 특성에 영향을 미치는 흐름을 만들면서,
단순한 데이터 보관이 아니라 확장성과 유지보수를 고려한 설계 방식이라는 걸 직접 체감했다.

단순히 기능을 넣은 것이 아니라, UI 흐름과 연계하고 PlayerState에 적용되도록 설계한 전체적인 흐름이
'아, 이게 진짜 시스템을 만드는 거구나' 하고 느끼게 해준 아주 좋은 경험이었다.

 

2. 그 배움을 얻기까지 어떤 어려움이 있었나요?

처음엔 ScriptableObject로 어떻게 스킬 정보를 관리하고 UI에 적용할지 구조가 머릿속에 잘 그려지지 않았다.
데이터는 분리했지만, 방 클리어 → UI 출력 → 스킬 선택 → 선택된 스킬의 효과 적용이라는 전체 흐름을 유기적으로 연결하는 로직을 구성하는 데 어려움이 있었다.

또한, UI에서 무작위로 3개의 스킬을 고르고, 버튼 클릭 시 해당 스킬이 Player에게 제대로 적용되는지 확인하는 과정도 만만치 않았다.
ScriptableObject를 통해 스킬을 전달했는데, 내부 값을 가져오는 과정에서 참조/복사 이슈로 적용이 안 되는 버그가 발생했다.

그리고 선택된 스킬을 Player의 상태에 반영하는 구조를 어디에 둘지,
SkillUIManager와 Player 사이의 역할을 어떻게 분리할지 고민하다가 UIManager → GameManager → Player 흐름으로 정리하게 되었다.

이 흐름을 다 잡고 나서야 스킬 시스템이 자연스럽게 동작했고, 전체 설계가 안정감을 갖게 되었다.

 

3. 그 과정에서 나는 무엇을 깨달았고, 어떤 감정/생각이 들었나요?

처음에는 단순히 "데이터를 나눠서 관리하면 좋겠지"라는 생각으로 ScriptableObject를 사용했는데,
이번에 시스템 전체를 연결하면서 **'데이터 구조 설계가 곧 게임의 흐름을 좌우한다'**는 걸 실감하게 됐다.

처음에는 생각보다 복잡하고 잘 안 풀려서 머릿속이 뒤죽박죽이었다.
UI도 따로, Player도 따로, 스킬도 따로 움직이는 느낌이라 "내가 잘못 짠 건가?" 하는 불안도 있었고,
스킬이 적용되지 않을 때는 어디서 문제인지 몰라서 한참을 디버깅했다.

하지만 결국 전체 흐름을 정리하고 나서 스킬이 적용되고 플레이어가 변화하는 걸 보니까
"아, 내가 만든 구조가 플레이어 경험에 직접적으로 영향을 주는구나" 하는 뿌듯함이 크게 느껴졌다.

그리고 이 경험을 통해 나는, 단순히 로직을 구현하는 개발자가 아니라
플레이어의 선택과 경험을 설계하는 사람이 되고 있다는 걸 깨달았다.

 

4. 메모 (느낀 점, 다짐)

이번 주는 "시스템을 만들었다"는 느낌이 뚜렷한 한 주였다.
단순히 기능을 구현하는 걸 넘어서, 플레이어 경험을 설계하고 연결하는 과정을 직접 만들어갔다.
특히 ScriptableObject를 사용해서 스킬 시스템을 구성한 건 내 개발자 인생에서도 **첫 번째로 제대로 된 '설계 중심의 개발 경험'**이었다고 생각한다.

구현이 잘 안 풀릴 땐 답답했지만, 팀원들이랑 함께 구조를 나누고 흐름을 정리하면서
같이 만들어가는 협업의 재미와 뿌듯함도 강하게 느꼈다.

앞으로도 복잡해 보여도 직접 부딪혀보면서 흐름을 하나하나 만들어가고 싶다.
다음주는 게임의 완성도를 더 끌어올릴 수 있는 디테일에 집중해서,
"직관적이고 몰입도 있는 게임 시스템"을 만드는 데 힘을 쏟자.

"내가 만든 시스템이 플레이어의 선택을 변화시키고,
그 선택이 게임 전체 흐름을 만들어간다"는 사실을 잊지 말자.

 

 

📅이번주 TIL 목록

 

내일배움캠프 21일차 TIL [Unity 생명주기와 C# 알고리즘 핵심 복습]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 11:00 : GitHub 과제 업로드, 제출 및 README.md 정리🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 17:00 :Unity 학습 내용 복습 (라이프사이클, 코루틴, Instantiate 등)

dev-jen.tistory.com

 

내일배움캠프 22일차 TIL [팀 프로젝트(Archero)]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:00 : Unity 입문 프로젝트 발제 자료 확인10:00 ~ 11:00 : Unity 강의 수강 (입문 프로젝트 소개 중심)11:00 ~ 13:00 : 팀 회의 및 주제 결정 (궁수의 전설 기반), 역할 분담

dev-jen.tistory.com

 

내일배움캠프 23일차 TIL [팀프로젝트(Archero)]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 12:30 :CameraManager 스크립트 구조 설계 및 기본 구현2.5D 스타일 카메라 구현 (Z축만 따라가고 X축/Y축 고정)타이틀 상태에서는 고정 위치로 이동하도록 상태 분기

dev-jen.tistory.com

 

내일배움캠프 24일차 TIL [팀프로젝트(Archero)]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 12:00 :MonsterSpawnManager 수정 및 커밋Skill&UpgradeSystem_LeeJaeEun 브랜치 병합MainScene UI 테스트 및 사운드 추가Read-Only 애니메이션 클립 복제 방법 팀원에게 설명애니메

dev-jen.tistory.com

 

내일배움캠프 25일차 TIL [팀프로젝트(Archero)]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : GitHub 커밋 및 기능 구현보스 일반 공격 충돌 문제 해결스테이지 클리어 UI 기능 마무리보스 중력 및 히트 애니메이션, 붉은색 피격 효과 적용몬스터 사운

dev-jen.tistory.com

 

 

📅이번주 Study 목록

 

Unity - Unity MonoBehaviour 생명주기 (Lifecycle) 정리

🌀 Unity MonoBehaviour 생명주기 (Lifecycle) 정리Unity는 MonoBehaviour 기반의 스크립트를 일정한 순서로 호출하며, 게임 오브젝트의 생성부터 종료까지 다양한 이벤트 함수를 실행한다. 아래는 각 단계별

dev-jen.tistory.com

 

Unity - Unity Coroutine(코루틴)

📌 Coroutine이란?**코루틴(Coroutine)**은 Unity에서 제공하는 특별한 함수로, 작업의 흐름을 중간에 일시정지하고, 조건이 충족되면 다시 이어서 실행할 수 있다.코루틴은 IEnumerator 반환형을 가지며, S

dev-jen.tistory.com

 

Unity - Invoke() vs Coroutine 비교 정리 & InvokeRepeating()

⏰ Unity Invoke() vs Coroutine 비교 정리Unity에서 일정 시간 이후에 어떤 작업을 수행하려면 보통 Invoke()나 Coroutine을 사용한다.둘 다 **시간 지연(delay)**을 다룰 수 있지만, 구조와 활용도에는 큰 차이가

dev-jen.tistory.com

 

Unity - Unity Instantiate() 오버로드 정리 & 자식으로 설정할 때의 차이

🧱 Unity Instantiate() 오버로드 정리 & 자식으로 설정할 때의 차이Unity에서 동적으로 오브젝트를 생성할 때 가장 많이 사용하는 함수는 Instantiate()다.하지만 부모를 지정하는 방식, 월드 좌표 유지

dev-jen.tistory.com

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 13:00 : GitHub 커밋 및 기능 구현
    • 보스 일반 공격 충돌 문제 해결
    • 스테이지 클리어 UI 기능 마무리
    • 보스 중력 및 히트 애니메이션, 붉은색 피격 효과 적용
    • 몬스터 사운드, 파티클, HP Bar 상호작용 기능 추가 및 수정
    • 튜토리얼 관련 버그 수정 및 기능 개선
    • StageChangeButton 관련 로직 개선 시도

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심시간

✅ 오후

  • 14:00 ~ 18:00 :
    • 몬스터 FSM과 SpawnManager 연결 로직 점검
    • 스테이지 전환 중 클리어 처리 예외 상황 확인
    • 보스 태그/프리팹 설정 및 애니메이션 처리 개선
    • GitHub 정리 및 커밋 다수 진행

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁시간

✅ 저녁

  • 19:00 ~ 21:00 : 팀원들과 회의 및 개발 보고서 작성
    • 각자 진행 상황 공유
    • 기능 및 역할 정리
    • 향후 일정 조율 및 코드 통합 논의

✅ 오늘 학습 키워드

  • MonsterFSM 상태 관리 (Die 상태 처리 및 상태머신 전환 로직)
  • MonsterSpawnManager에서 몬스터 전체 사망 체크 및 UI 연동
  • StageChangeButton을 통한 스테이지 전환 조건 처리
  • GameManager의 SetStage 구조 및 클리어 처리 타이밍 확인
  • 스테이지별 매니저 활성화 순서와 OnEnable() 트리거 순서 이해
  • GitHub 커밋 내역을 기반으로 작업 흐름 관리 및 협업 상황 파악

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

오늘은 게임의 핵심 흐름 중 하나인 스테이지 전환과 클리어 처리 로직을 중점적으로 다뤘다.

먼저 StageChangeButton을 통해 스테이지를 변경할 때, 해당 스테이지가 이미 클리어된 경우 다음 미클리어 스테이지를 탐색해 자동으로 전환되도록 구현했다. 다만 이 과정에서 튜토리얼과 메인 스테이지는 클리어 조건이 적용되면 안 되는데, 튜토리얼에도 클리어 조건이 들어가 버려서 스킵되는 문제가 있었다. 이를 IsStageCleared() 내부에서 조건 분기로 해결했다.

또한 GoToMainStage() 함수에서 중간 스테이지에서도 메인으로 복귀할 수 있도록 처리했는데, 이때도 SetStage() 내부에서 클리어 처리가 함께 실행되어 버리는 구조 때문에, 스테이지를 클리어하지 않고 메인으로 이동했는데도 클리어가 되는 문제가 발생했다. 이를 해결하기 위해 SetStage() 호출 전에 클리어 처리 분기 제어가 필요함을 확인했고, 추후 구조 개선을 고려 중이다.

한편, MonsterSpawnManager에서 스폰된 몬스터들이 모두 사망하면 SkillUIManager를 호출해 스킬 선택 UI를 자동으로 띄우는 기능도 구현했다. FSM 구조와 상호작용하며 IsAlive()를 통해 몬스터 생존 여부를 체크하는 구조는 간단하지만 매우 실용적이었다.

마지막으로 팀원들과 회의하면서 개발보고서 작성을 진행했고, 전체 흐름을 점검하며 오늘까지 구현된 내용을 정리했다. 협업 리듬을 유지하면서도 각각의 시스템이 안정적으로 동작할 수 있도록 점검한 하루였다.


🧩 학습하며 겪었던 문제점 & 에러

1. 문제정의

GoToMainStage() 함수 호출 시, 현재 스테이지가 클리어 처리되는 문제

  • 메인으로 단순 이동하고 싶을 뿐인데 GameManager.Instance.SetStage(...) 내부 로직에서 이전 스테이지를 클리어 처리함.

시도

public void GoToMainStage()
{
    GameManager.Instance.SetStage(StageType.MainStage);
}

이때, 내부적으로 SetStage()에서 이전 스테이지 클리어가 자동 처리됨:

switch (CurrentStage)
{
    case StageType.Stage1:
        StageManager.Instance.stage1Clear = true;
        break;
    ...
}

해결방법

임시로 다음과 같이 분기 조건을 넣었지만 구조적으로 아쉬움:

public void GoToMainStage()
{
    if (GameManager.Instance.CurrentStage != StageType.MainStage)
    {
        // 강제 클리어 방지용으로 별도 플래그나 조건 제어 필요
    }
    GameManager.Instance.SetStage(StageType.MainStage);
}

새롭게 알게 된 점

  • SetStage() 내부에서 무조건 현재 스테이지를 클리어 처리하고 있었음.
  • 이 로직은 “클리어한 후 다음 스테이지로 간다”는 전제를 깔고 있어서, 중간 이탈이나 테스트용 스테이지 이동에는 부적절함.

다시 만나게 된다면

  • SetStage() 호출 방식 리팩토링 필요. 이동 목적이 "클리어 + 다음 스테이지" 인지, "그냥 이동"인지 구분하는 인자를 도입하는 방식 고려 필요.
public void SetStage(StageType newStage, bool markClear = true)

2. 문제정의

스테이지 클리어 후 스킬 UI가 자동으로 안 뜸

시도

  • MonsterSpawnManager 내부에서 모든 몬스터가 죽었는지 체크해서 SkillUIManager.Instance.ShowSkillUI() 호출함.
if (spawnedMonsters.Count > 0 && AreAllMonstersDead())
{
    SkillUIManager.Instance.ShowSkillUI();
}

해결방법

  • 문제는 IsAlive()를 제대로 체크하지 못하거나, Die 상태로 바뀌었음에도 GameObject가 Destroy() 전까지는 살아있다고 판단하는 점 때문이었음.
  • FSM의 UpdateDie()에서 isDie = true;와 Destroy(gameObject, 3f);를 설정하고 있었음 → IsAlive()가 이 상태를 기준으로 false를 반환하도록 수정.

예시 코드

public bool IsAlive()
{
    return !isDie;
}

새롭게 알게 된 점

  • Unity에서 Destroy()는 실제로는 다음 프레임에 처리되기 때문에, 직접 상태 플래그로 죽음을 판단해야 한다.

다시 만나게 된다면

  • FSM은 상태 기반이므로, 사망 체크는 반드시 Die 상태와 isDie 같이 명시적으로 관리되어야 신뢰성이 있음.

📝 메모

오늘은 스테이지 이동 시스템과 몬스터 클리어 판정, FSM 상태 관리 등 게임 전반의 흐름을 결정짓는 핵심 시스템들을 다뤘다.

처음엔 단순히 "메인 화면으로 가고 싶다"는 동작이었지만, 그 안에 숨겨진 클리어 처리 로직사이드 이펙트들을 하나씩 파악하면서,

게임 설계에서 로직 분리와 명확한 의도 전달이 얼마나 중요한지 다시 한 번 느꼈다.

그리고 오늘 저녁엔 팀원들과 회의를 통해 개발보고서를 작성하며,

각자의 작업 내역을 공유하고 서로가 만든 시스템을 이해하려고 노력하는 시간이 정말 뜻깊었다.

하나의 기능을 만들고, 그것이 팀 전체의 흐름 속에서 어떻게 연결되는지를 고민하는 일이 정말 재미있고 보람찼다.

이제 정말 프로젝트의 완성도를 높이는 작업이 되고 있다는 게 느껴진다.

기능 구현에서 디테일 조정, 예외 처리, 그리고 클리어 후 보상 시스템까지…

하나하나 챙겨가며 정리하고 있다는 것이 자랑스럽기도 하다.

앞으로도 "작동하니까 됐어"가 아니라

"왜 이렇게 동작하지?"

"지금 이 로직은 진짜 이 목적에 맞는 걸까?"

하는 생각을 놓지 않고 더 단단하게 만들어가고 싶다.


반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 12:00 :
    • MonsterSpawnManager 수정 및 커밋
    • Skill&UpgradeSystem_LeeJaeEun 브랜치 병합
    • MainScene UI 테스트 및 사운드 추가
    • Read-Only 애니메이션 클립 복제 방법 팀원에게 설명
    • 애니메이션 전환 부드럽게 하기 위한 Transition Duration 값 수정

🍽️ 점심시간

  • 12:00 ~ 13:00 : 점심시간

✅ 오후

  • 13:00 ~ 18:00 :
    • SkillTutorialUIManager 코루틴 오류 해결 (SetActive(true) 및 currentIndex = 0)
    • 스킬 튜토리얼 UI 순차 출력 구현 및 수정
    • GameManager 튜토리얼 로직 최종 수정
    • Main 브랜치의 MainScene 최종 통합 및 테스트

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁시간

✅ 저녁

  • 19:00 ~ 현재 :
    • 기술스택 정리 (FSM, Generic Singleton, ScriptableObject 사용 이유/결과)
    • 프로젝트 수행 절차 작성
    • 트러블슈팅 기록 정리
    • 슬라이드용 내용 문서화 지원

✅ 오늘 학습 키워드

  • Time.timeScale을 활용한 게임 속도 조절 함수 구현
  • Singleton<T> 상속 클래스에서 base.Awake() 호출 필요성
  • Read-Only 애니메이션 클립 복사 및 Animation Event 삽입 방법
  • Quaternion.LookRotation 사용 시 회전 방향 보정 (180도 Y축 회전)
  • StartCoroutine() 호출 시 GameObject가 활성화 상태여야 실행 가능
  • SkillTutorialUIManager의 코루틴 초기화 및 재실행 조건
  • Animator Transition Duration을 통한 애니메이션 끊김 해결
  • 스테이지 전환 시 GameManager의 상태 구조 설계 (StageType과 연결)

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

1. 시간 속도 조절 함수 구현

Unity에서는 Time.timeScale을 조절함으로써 게임 전체의 흐름 속도를 바꿀 수 있다.

이를 활용해 2배 빠르게 실행되도록 만들고, 다시 원상 복구하는 함수를 각각 하나씩 만들었다.

실제로 메인 화면 버튼과 연결해서 게임이 빨라지는 효과도 테스트했다.


2. Singleton 사용 시 base.Awake() 호출의 중요성

SkillUIManager가 Singleton<T>을 상속하고 있는데, 자식 클래스에서 base.Awake()를 호출하지 않으면 인스턴스가 등록되지 않아 Instance가 null이 된다.

싱글톤을 쓸 때는 반드시 base.Awake()를 호출해야 한다는 걸 실전에서 경험했다.


3. Read-Only 애니메이션 클립은 복제해서 써야 한다

외부에서 가져온 FBX나 모델에 포함된 애니메이션 클립은 Read-Only 상태라서 Animation Event를 추가할 수 없다.

이 문제를 해결하기 위해 해당 클립을 복제한 후 새롭게 만든 Animation Clip에 이벤트를 넣어 사용하는 방식으로 전환했다.

이 방법을 팀원에게도 공유하며 설명해줬다.


4. LookRotation과 발사체 회전 방향

Quaternion.LookRotation(direction)을 사용했는데, 투사체가 반대 방향으로 날아갔다.

이는 프리팹의 기본 앞 방향이 Z-였기 때문에 생긴 문제였고, * Quaternion.Euler(0, 180f, 0)를 곱해줌으로써 해결했다.

앞으로도 방향이 안 맞는 경우엔 프리팹 방향과 회전 기준을 반드시 점검해야겠다.


5. 비활성화된 오브젝트에서는 코루틴이 실행되지 않는다

SkillTutorialUIManager에서 코루틴이 실행되지 않아 원인을 찾았더니, 해당 GameObject가 SetActive(false) 상태였다.

Unity에서는 GameObject가 비활성화된 상태에서는 StartCoroutine() 자체가 실행되지 않는다는 걸 다시 한번 확실히 알게 되었다.

그래서 StartTutorial() 호출 전에 SetActive(true) 처리를 추가했다.


6. 튜토리얼 UI 반복 실행 시 초기화 필요

튜토리얼에서 스킬 UI를 순차적으로 보여주는데, 한 번 실행하고 다시 실행하려고 하니 아무것도 나오지 않았다.

그 이유는 내부 인덱스 변수 currentIndex가 초기화되지 않아 조건을 만족하지 못했기 때문이다.

StartTutorial() 시작 시 currentIndex = 0;을 넣어 해결했다.

재실행이 필요한 시스템에서는 항상 초기화를 염두에 둬야 함을 배웠다.


7. Transition Duration을 통한 애니메이션 끊김 해결

보스 애니메이션이 너무 뚝뚝 끊겨서 어색하다는 피드백이 있었다.

Animator에서 상태 전환 시 Transition Duration 값을 조절함으로써 부드러운 전환이 가능하다는 것을 적용했고,

그 효과를 팀원에게도 설명해주며 문제를 해결했다.


8. GameManager의 StageType 구조 활용

GameManager는 StageType과 GameState를 분리해서 스테이지 전환 로직을 명확하게 구현했다.

튜토리얼 상태에서도 이 구조를 확장해서 적용함으로써 메인, 스테이지1~4, 보스, 튜토리얼 흐름을 모두 통합 관리할 수 있게 되었다.

확장 가능한 상태 구조를 설계하는 것의 중요성을 느꼈다.


🧩 학습하며 겪었던 문제점 & 에러

1. SkillUIManager.Instance가 null

  • 문제정의
  • SkillUIManager.Instance를 호출했을 때 null reference 에러가 발생함
  • 시도
  • 싱글톤 구조를 확인했지만, 인스턴스가 제대로 할당되지 않은 것을 발견
  • 해결방법
  • SkillUIManager의 Awake()에서 base.Awake(); 호출을 추가하여 인스턴스 등록 문제 해결
  • 새롭게 알게 된 점
  • 제너릭 싱글톤 패턴에서는 반드시 base.Awake()를 호출해줘야 instance가 등록됨
  • 다시 만나게 된다면
  • 싱글톤 구조를 상속할 때 항상 base.Awake() 호출을 빠뜨리지 않도록 체크리스트화할 것

2. Read-Only 애니메이션 클립에 이벤트 추가 불가

  • 문제정의
  • 공격 애니메이션에 이벤트를 넣으려 했지만, 해당 애니메이션이 Read-Only여서 수정이 불가능했음
  • 시도
  • 애니메이션을 선택 후 이벤트 추가를 시도했지만 이벤트 창이 비활성화 상태였음
  • 해결방법
  • 애니메이션 클립을 복제한 뒤 .anim 파일로 새롭게 저장하여 이벤트 삽입 가능하게 만듦
  • 새롭게 알게 된 점
  • FBX 등에서 가져온 애니메이션 클립은 읽기 전용이기 때문에 복제해서 써야 함
  • 다시 만나게 된다면
  • 커스터마이징이 필요한 애니메이션은 처음부터 별도 .anim 파일로 만들어 사용할 것

3. 투사체가 반대로 날아감

  • 문제정의
  • LookRotation을 사용해 방향을 지정했는데, 발사체가 플레이어와 반대 방향으로 날아감
  • 시도
  • direction 벡터를 확인하고 회전값을 조정해봄
  • 해결방법
  • transform.rotation = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180f, 0); 추가하여 Y축 회전 보정
  • 새롭게 알게 된 점
  • LookRotation은 Z+ 방향 기준이고, 프리팹의 실제 앞 방향이 Z-일 경우 반대로 회전함
  • 다시 만나게 된다면
  • 발사 방향과 프리팹의 forward 방향(Z축)을 먼저 일치시킬 것

4. SkillTutorialUIManager 코루틴이 실행되지 않음

  • 문제정의
  • StartTutorial()에서 코루틴이 호출되지 않음
  • 시도
  • 코루틴 함수 구조와 실행 순서를 확인했지만 동작하지 않음
  • 해결방법
  • StartCoroutine() 호출 전에 gameObject.SetActive(true) 처리하여 코루틴이 실행 가능하도록 수정
  • 새롭게 알게 된 점
  • 비활성화된 오브젝트에서는 코루틴이 실행되지 않음
  • 다시 만나게 된다면
  • 코루틴 호출 전 GameObject가 activeSelf == true인지 먼저 체크할 것

5. 튜토리얼 재실행 시 UI가 나오지 않음

  • 문제정의
  • 튜토리얼 UI가 한 번은 잘 나오지만, 다시 실행하면 아무것도 표시되지 않음
  • 시도
  • UI가 생성되는 구조와 루프 조건 확인
  • 해결방법
  • StartTutorial() 안에서 currentIndex = 0;을 추가하여 루프 조건을 만족하게 만듦
  • 새롭게 알게 된 점
  • 코루틴 반복 실행을 위해서는 내부 상태값을 항상 초기화해줘야 함
  • 다시 만나게 된다면
  • 반복 가능한 시스템은 항상 초기화 코드 포함 여부를 점검할 것

6. 보스 애니메이션이 뚝뚝 끊김

  • 문제정의
  • 보스가 애니메이션 전환 시 부자연스럽고 급격하게 끊기는 현상이 발생
  • 시도
  • 애니메이터 내 상태 전환 간 Transition 설정 확인
  • 해결방법
  • Transition Duration 값을 늘려 자연스럽게 이어지도록 수정함
  • 새롭게 알게 된 점
  • 애니메이션 상태 전환은 Duration 값에 따라 부드러움이 결정됨
  • 다시 만나게 된다면
  • 모든 전환 구간에 대해 적절한 Exit Time, Duration 설정을 해둘 것

📝 메모

오늘은 기술적으로도, 팀워크적으로도 아주 밀도 있는 하루였다.

싱글톤 구조의 base.Awake() 누락 문제부터, 코루틴이 실행되지 않는 이유, Read-Only 애니메이션 클립 복사 등 직접 부딪혀서 해결한 이슈들이 많았다.

특히 팀원들과 나눈 대화 속에서 내가 알고 있는 내용을 설명해주는 순간이 많았고, 그 과정에서 나도 한층 더 이해가 깊어졌다.

보스 애니메이션 전환 문제를 해결해주거나, 발사체 방향 문제를 정리한 것도 나에겐 의미 있는 경험이었다.

하나하나 꼼꼼히 체크하고 설명해주는 일이 많았던 하루였고, 개발 외적으로도 팀 분위기를 이끌 수 있었다는 게 뿌듯했다.

이제 게임의 흐름과 시스템이 대부분 정리되었으니, 남은 작업은 완성도 높이기다.

지금까지 해온 것처럼 차근차근 마무리해보자!! 내일도 화이팅!!!! 💪😊


4주차 10조 우리 팀원들!

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 12:30 :
    • CameraManager 스크립트 구조 설계 및 기본 구현
    • 2.5D 스타일 카메라 구현 (Z축만 따라가고 X축/Y축 고정)
    • 타이틀 상태에서는 고정 위치로 이동하도록 상태 분기 처리
    • followOffset 도입으로 플레이어가 카메라 중앙쯤 보이게 조정

🍽️ 점심시간

  • 12:30 ~ 13:30 : 점심시간

✅ 오후

  • 13:30 ~ 18:00 :
    • 카메라 X축 고정 방식 개선: GameState.Playing 상태마다 X값 갱신되도록 변경
    • lastState 도입으로 상태 전환 감지 구현
    • GameManager → CameraManager로 ResetFixedX() 직접 호출하는 구조 설계
    • playerTransform 참조 오류 해결 (null 방지 처리: FindWithTag("Player"))
    • UI 시스템 전반 구성 시작
      • PlayerStat UI, HP Bar, Skill UI, Title UI 등 각종 UI Canvas 정리
      • UIManager에서 GameState에 따라 활성화되는 UI 관리 구조 설계
      • UpdateUI() 함수에서 Dictionary 기반으로 UI 전환 동작 처리

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁시간

✅ 저녁

  • 19:00 ~ 21:00 :
    • UIManager와 GameManager 상태 연동 마무리
    • 팀원들이 작성한 기능 코드 병합
    • 병합 후 전체 흐름 테스트 및 디버깅
    • CameraManager + UIManager 전체 구조 점검
    • TIL 작성

✅ 오늘 학습 키워드

  • Unity 카메라 추적(Camera Follow)
  • 2.5D 카메라: X 고정, Z 추적, Y 고정 + Offset
  • GameState 상태 분기 및 전환 감지
  • CameraManager와 GameManager 연결 구조
  • UIManager 상태 기반 UI 전환
  • 팀 프로젝트 병합 및 연결 테스트

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

오늘은 카메라 움직임과 UI 시스템을 게임 흐름에 맞게 자연스럽게 연동시키는 작업에 집중했다.

처음에는 카메라가 플레이어를 따라가게 만들었지만, X축을 따라가면 플레이어가 너무 옆으로 치우쳐서

결국 X축은 고정하고 Z축만 따라가는 2.5D 방식으로 구조를 바꾸게 됐다.

이 과정에서 단순히 Start()에서 X값을 고정하면 안 된다는 걸 알게 되었고,

스테이지가 바뀌는 시점마다 X를 다시 잡아야 한다는 걸 깨달았다.

그래서 GameState가 Playing으로 바뀌는 타이밍을 감지해서

그 순간의 플레이어 X값을 저장하는 구조를 만들었고,

이걸 GameManager에서도 직접 호출할 수 있도록 ResetFixedX() 메서드도 추가했다.

그리고 오후에는 카메라와 함께 작동할 UI 시스템 전체를 정리했다.

플레이어 스탯, HP바, 스킬 UI 등 게임 플레이 중 보여줘야 하는 UI와

타이틀 상태에서만 보이는 UI를 구분하고,

GameState에 따라 자동으로 활성화/비활성화되도록 구조화했다.

전체적으로 기능 구현보다는 "흐름을 만드는 설계" 에 가까운 하루였고,

이전보다 더 체계적으로 상태와 기능이 맞물리는 구조를 만들어낸 것 같아 만족스러웠다.


🧩 학습하며 겪었던 문제점 & 에러

1. 카메라 X값이 0으로 고정되어 플레이어가 화면 중심에서 벗어남

  • 문제정의스테이지가 바뀌고 플레이어 위치가 달라져도 카메라는 엉뚱한 위치를 비췄다.
  • 카메라가 Z축은 잘 따라가는데, X값이 항상 0으로 고정되어 있어서
  • 원인 코드 (초기 시도)→ 문제는 Start()에서 한 번 고정한 fixedX가 스테이지가 바뀌어도 갱신되지 않는 것이었다.
  • private void Start() { fixedX = playerTransform.position.x; } private void LateUpdate() { Vector3 targetPos = new Vector3( fixedX, fixedY + followOffset.y, playerTransform.position.z + followOffset.z); cameraToControl.transform.position = Vector3.Lerp( cameraToControl.transform.position, targetPos, Time.deltaTime * followSpeed); }
  • 해결 방법 (상태 전환 감지)
    private UIManager.GameState lastState;
    
    private void LateUpdate()
    {
        var currentState = UIManager.Instance.GetCurrentState();
    
        // 상태가 Playing으로 전환될 때마다 X 고정값 갱신
        if (currentState == UIManager.GameState.Playing && lastState != UIManager.GameState.Playing)
        {
            fixedX = playerTransform.position.x;
        }
    
        lastState = currentState;
    
        Vector3 targetPos = new Vector3(
            fixedX,
            fixedY + followOffset.y,
            playerTransform.position.z + followOffset.z);
    
        cameraToControl.transform.position = Vector3.Lerp(
            cameraToControl.transform.position,
            targetPos,
            Time.deltaTime * followSpeed);
    }
    
  • 상태가 Main → Playing으로 전환되는 순간을 감지해서 그때 playerTransform.position.x을 다시 저장하도록 개선했다.
  • 새롭게 알게 된 점스테이지나 상태가 바뀌는 흐름에서는 언제 값을 갱신해야 하는지 기준을 명확히 잡아야 한다는 걸 깨달았다.
  • 단순히 Start()에서 한 번 고정하는 건 한 씬 안에서는 괜찮지만,
  • 다시 만나게 된다면한 흐름 안에서 자동으로 처리하도록 구조 설계부터 깔끔하게 가져가야겠다고 느꼈다.
  • 상태 전환이 필요한 구조에서는 상태 감지, 값 초기화, UI 동기화 등을

📝 오늘의 회고 & 메모

오늘은 팀원들과의 협업 속에서 내가 얼마나 성장하고 있는지를 느낄 수 있었던 하루였다.

특히 보스 몬스터 공격에 대한 질문을 받았던 게 기억에 남는다.

팀원이 만든 보스가 도끼를 휘두르기 전에 이미 Collider에 닿아서

플레이어가 공격 애니메이션이 시작되기 전부터 피해를 입는 문제가 있었고,

그걸 함께 해결하기 위해 애니메이션 클립에 이벤트를 등록해서

공격 타이밍에 맞춰 bool 값을 켜고 끄는 방식으로 조정해줬다.

또, 공격이 끝났는데도 도끼가 다시 플레이어에 닿아서 데미지가 들어가는 상황도 있어서

딜레이용 bool 변수를 하나 더 두어 애니메이션 흐름에 맞춘 로직을 설계했다.

이 과정에서 팀원은 계속 미안해했지만, 나는 전혀 그렇지 않았다.

오히려 덕분에 보스 몬스터의 공격 시스템에 대한 이해도가 높아졌고,

어떻게 타이밍을 제어할 수 있는지를 몸소 배울 수 있었던 값진 경험이었다.

또한, 다른 팀원들의 질문도 계속 이어졌고

나도 모르게 여러 문제에 도움을 주고 있다는 걸 실감하게 되었다.

그 과정이 부담이 아니라 즐거움이었다.

팀원들과의 신뢰도와 친밀감이 더 깊어진 느낌이 들었고,

함께 게임을 만들어간다는 팀워크가 피부로 느껴졌다.


💭 메모

  • “모르는 걸 부끄러워하지 말자”는 생각을 다시금 되새겼다. (나도 잘 모르기때문..)
  • 팀원이 실수하거나 막히는 부분은 곧 나에게도 배움의 기회가 된다.
  • 도와주며 내가 더 많이 배운다는 걸 느꼈고, 덕분에 오늘도 같이! 성장했다 오예!

 

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 10:00 : Unity 입문 프로젝트 발제 자료 확인
  • 10:00 ~ 11:00 : Unity 강의 수강 (입문 프로젝트 소개 중심)
  • 11:00 ~ 13:00 : 팀 회의 및 주제 결정 (궁수의 전설 기반), 역할 분담

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심식사

✅ 오후

  • 14:00 ~ 16:00
    • 스킬 UI 시스템 개발 (ScriptableObject 기반)
    • 무작위 스킬 표시 기능 구현
    • Horizontal Layout Group의 Spacing 조절로 겹침 문제 해결
    • 팀원 보스 기능 개발 보조 (콜라이더, Rigidbody, 애니메이터 구성 도움)
  • 16:00 ~ 18:00
    • 챌린지반 특강 2회차 수강: 메모리 구조

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁 식사 및 휴식

✅ 저녁

  • 19:00 ~ : 21:00
    • 오늘 구현한 스킬 UI 흐름 복습
    • TIL 작성

✅ 오늘 학습 키워드

  • Unity UI 자동 정렬 (HorizontalLayoutGroup)
  • ScriptableObject를 활용한 데이터 바인딩
  • 무작위 스킬 선택 로직
  • Canvas 내 프리팹 인스턴스 정렬 이슈
  • 팀원 간 역할 분담 실무
  • 메모리 구조 (특강 내용 기반)

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

오늘은 내가 맡은 스킬 및 업그레이드 시스템의 핵심 뼈대를 만들었다.

무작위로 스킬을 선택해서 UI에 띄우고, 해당 스킬을 선택하면 능력치가 반영되도록 구조를 설계했는데,

ScriptableObject를 사용하면서 데이터 중심 설계의 중요성을 체감했다.

UI에서 가장 헷갈렸던 건, 프리팹을 생성했는데 왜 자꾸 겹쳐지는가였는데,

알고 보니 LayoutGroup의 spacing 문제였다.

이런 걸 하나하나 겪으면서 “자동 정렬도 결국 내가 기준을 명확히 잡아줘야 한다”는 걸 배웠다.

그리고 팀원들과의 협업도 중요했다.

내 일만 보는 게 아니라, 구조적으로 문제가 생기지 않게 보스 오브젝트 구조나 트리거 처리까지 같이 살펴봤다.

게임 개발은 혼자 하는 게 아니라는 걸 다시 한번 느낀 하루였다.


🧩 학습하며 겪었던 문제점 & 에러

1. UI 슬롯이 겹치는 문제

  • 문제정의 : 생성된 스킬 슬롯들이 모두 오른쪽 위에 겹쳐 표시됨
  • 원인 : Layout Group의 Spacing 값이 0으로 되어 있어 자동 정렬이 되지 않음
  • 해결방법 : HorizontalLayoutGroup 컴포넌트의 Spacing 값을 조정 (예: 50 이상)
  • 새롭게 알게 된 점 : LayoutGroup은 spacing이 없으면 프리팹 위치가 겹칠 수 있음
  • 다시 만나게 된다면 : 프리팹 UI 만들 때 초기 spacing 설정도 꼭 점검하기

📝 메모

  • 팀원들 도와줄 때도, 내가 담당한 기능을 구현할 때도
  • 기본 구조를 이해하는 게 얼마나 중요한지 다시 느꼈다.
  • 작동만 하면 되는 게 아니라 정돈된 방식으로 작동하도록 만드는 게 더 어려운 일이다.
  • 복습하면서 내가 어떤 문제를 어떻게 풀었는지 돌아보는 이 시간이 정말 중요하다.

💭 회고

오늘 협업을 진행하면서 느꼈다.

나도 아직 완벽하진 않지만, 다들 열심히 해주시고 나를 좋게 봐주시는 모습이 너무 감사했다.

그런데도 팀원 중 몇 분은 스스로 부족하다며 민폐가 아닐까 걱정하시는데… 정말 절대 그럴 필요가 없다.

지금은 함께 배우는 시기고, 같이 한 발씩 나아가는 과정이 제일 중요하다.

천천히, 하나씩 개발하면서 협업의 의미를 자연스럽게 함께 느껴갔으면 좋겠다.

시간도 많고, 사람도 많고, 무엇보다 우리 팀은 함께하고 있으니까.

서로를 믿고 부담 없이, 편하게 진행해갔으면 한다 😊

오늘도 벌써 하루가 저물었다.

내일도 힘내서 함께 달려보자! 화이팅!! 💪🌟


오늘 협업중 제작한 스킬 선택화면! 아직은 테스트버전!

반응형