-
Notifications
You must be signed in to change notification settings - Fork 3
최종 프로젝트 보고서
2024 Fall 소프트웨어 개발의 원리와 실습 프로젝트 보고서
<에코히어로>
팀명: 에코시티즌
- 2020-10174 이상규
- 2020-16634 이선재
- 2019-12918 김준원
- 2020-16033 이정민
- 2022-17647 김동욱
- 팀명 : EcoCitizen
- 소개 : 저희는 환경문제에 대한 사회적 인식을 끌어올리기 위해 노력하는 팀입니다.
- 이상규: PM입니다. 컴퓨터공학부 3학년 재학 중이고 운영체제 수강 뒤 GPU 가속 관련 인턴을 진행했습니다. Blender, Unity 모두 처음입니다. Steam 퍼즐게임을 플레이해본 경험이 있습니다.
- 김동욱: 컴퓨터공학부 3학년 재학 중입니다. 실무 경험은 없지만 동기들과 함께 Unity를 통해 2D 게임을 제작하고 넥슨 주최 공모전에 제출한 경험은 있습니다. Blender 경험이나 3D 게임 제작 경험은 아직 없습니다.
- 김준원: 개발자를 맡고 있습니다. 자유전공학부 컴퓨터공학전공 3학년입니다. 산업기능요원으로 넥슨의 자회사에서 일했으며, 3년간 Node.js로 웹 백엔드 개발을 진행했습니다. 게임 개발 경험은 없으며, Blender, Unity 모두 처음 다뤄봅니다.
- 이선재: 저는 자유전공학부에서 컴퓨터공학과 생명과학을 전공하고 있습니다. 1년간 스윙에서 iOS 개발자로 일한 경험이 있으며, 컴퓨터공학부의 모바일 앱 개발 동아리인 와플스튜디오에서 활동하고 있습니다. 모바일 앱 개발 경험은 있지만, 게임 개발을 이번 강의를 통해 처음으로 접하게 되었습니다.
- 이정민: 자유전공학부 컴퓨터공학전공 3학년입니다. Blender, Unity 모두 처음 다뤄보고 개발경험이 많지 않지만 3년간 전공 수업을 들으며 지식을 많이 채웠습니다. 소개원실 수업에서 프로젝트 경험을 쌓고 싶습니다.
- 게임명 : 에코히어로 (EcoHero)
가까운 미래 (2034년), 도시가 유해한 쓰레기로 가득차 인간이 접근조차 할 수 없게 되었다. 이에 인류는 잃어버린 영토를 회복하고자 로봇을 이용해 쓰레기를 정리하는 계획을 세우게 된다. 이 과정에서 도시에 이미 설치된 CCTV를 이용하기로 한다. CCTV는 일정한 구역을 움직이면서 순찰하는데, 로봇이 화면 밖으로 나가면 안전을 위해 로봇이 정지하게 되어, 로봇을 화면 안에 유지하면서 쓰레기를 정리해야 한다. 여러분은 이 로봇을 원격으로 조종하는 역할을 맡았다. 힘내 보시라!
- 구성
- 멀티 스테이지 게임으로, 각 스테이지를 클리어하면 다음 스테이지를 플레이할 수 있다.
- 각 스테이지에서, 플레이어는 로봇을 조작해 쓰레기를 쓰레기통에 옮김으로써 스테이지를 클리어할 수 있다.
- 플레이어가 스테이지를 쓰레기를 놓치지 않고 빠르게 클리어할수록 높은 등급이 부여되고, 이 등급에 따라 받은 코인으로 플레이어는 로봇을 업그레이드할 수 있다.
- 각 스테이지의 게임 기믹은 동일하며, 맵의 구성만 다르다.
- 맵
- 맵은 직사각형으로, 가로 길이는 화면의 가로 길이와 같고, 세로 길이는 화면의 세로 길이보다 길어 화면에 일부만 노출된다. 화면은 맵의 아래 부분을 비추면서 시작해 점차 위쪽을 비춘다.
- 맵 위에는 네 가지 물체: 플레이어, 쓰레기, 쓰레기통, 장애물이 위치한다.
- 플레이어, 쓰레기, 쓰레기통은 사각형 1개를, 장애물은 사각형 1개 또는 2개를 차지한다.
- 맵의 끝에는 도착 기준선이 그려져 있어, 이 지점을 통과하면 스테이지를 클리어하게 된다.
- 카메라: 2.3 참고
- 오브젝트
- 플레이어블 유저 (로봇)
- 쓰레기: 종이, PET, 캔 음식물 중 1종류 ~ 4종류 (스테이지 난이도가 높을수록 더 많은 종류)
- 쓰레기통: 쓰레기의 종류와 1-1 대응됨. 각 쓰레기통에 대응되는 종류의 쓰레기만 버릴 수 있음
- 장애물: 유저의 이동을 방해하는 역할, 유저에게 데미지를 주진 않음
- 정지해 있는 장애물 (라바콘, 나무, 신호등 등)
- 규칙적으로 움직이는 장애물 (동물, 트럭, 자동차, 좀비 등)
- 아이템: 아이템의 위치로 이동하여 획득할 수 있고, 획득과 동시에 사용됨
- 배터리 팩: 소모한 목숨을 회복해줌
- 만능 쓰레기통: 들고 있는 모든 쓰레기를 비워줌
- 조작 방법 (키보드)
- 격자 위에서 상하좌우로 이동 (WASD, 방향키)
- 쓰레기 줍기
- 쓰레기가 있는 칸으로 이동하면 해당 칸으로 이동하는 동시에 쓰레기를 주움
- “한 번에 들고 있을 수 있는 최대 쓰레기 개수"의 쓰레기를 갖고 있으면 주울 수 없음
- 쓰레기 버리기
- 쓰레기통 오브젝트 앞에서 쓰레기통을 바라보고 “쓰레기 버리기" 키 (Space)를 누르면 갖고 있는 쓰레기들 중 대응되는 종류의 쓰레기를 버릴 수 있음.
- 아래 두 가지 방법 중 Queue를 기본으로, Dictionary of list를 업그레이드로 이용
- (Queue) 주운 쓰레기들 중 가장 먼저 주운 쓰레기 1개씩 버릴 수 있음 스스로 버린 것을 주워 큐의 상대적 위치를 조정하는 키가 있음
- (Dictionary of list) 쓰레기통에서 버리기 키를 누르면 자동으로 대응되는 쓰레기가 모두 버려짐
- Esc 키로 게임을 일시정지할 수 있다.
- 스테이지 게임 오버 (실패) 조건
- 목숨(배터리팩) 3개가 다 까이면 게임 오버 (스테이지 클리어 실패)
- 줍지 않은 쓰레기가 화면 하단에 닿은 경우 목숨 1개 차감
- 플레이어가 화면 하단에 닿은 경우 목숨 1개 차감하고 중앙에서 리스폰
- 스테이지 클리어 (성공) 조건
- 게임 오버가 되지 않고 맵의 끝(도착 기준선)에 도달
- 점수 및 등급
- 게임 플레이 중 실시간으로 표시
- (실시간 점수) = (플레이 시간) - (현재 지점의 기준 시간) + 5 * (버린 쓰레기 개수)
- (최종 점수) = clamp((플레이 시간) - (현재 지점의 기준 시간), -20, 20) + 5 * ((버린 쓰레기 개수) - (전체 쓰레기 개수)) + 100
- 게임 종료 후 점수에 따라 등급 부여 (등급에 따라 재화 차등 지급)
- 100점 이상 : A(3별), 90점 이상 : B(2별), 80점 이상 : C(1별), 80점 미만 : D(0별)
- 코인
- 스테이지를 최초 클리어시 등급에 따라 코인을 부여, 더 높은 등급으로 다시 클리어시 차이만큼 부여
- 등급별 부여 코인은 A - 3개, B - 2개, C - 1개, D - 0개
- 파워업(업그레이드)
- 부여된 코인을 소모해 플레이어를 업그레이드함
- 업그레이드의 종류는 아래와 같고, 가격은 추후 결정
- “한 번에 들고 있을 수 있는 쓰레기의 최대 개수" 늘리기
- “쓰레기 버리는 방법”을 변경 (Queue, Dictionary of list)
- 이동 속도 늘리기
- 초기 목숨 늘리기
- “한 번에 들고 있을 수 있는 쓰레기의 최대 개수" 늘리기
최근 통합위 발표에 따르면 "국민 70% 환경문제에 관심" 을 보였으며, 이 중 가장 시급한 환경문제로는 기후변화'를 꼽음 (63.9%). 이들은 일상 생활 속에서 환경을 보호하기 위한 다양한 실천 방안을 찾고 있으며, 게임에서 환경 보호 활동을 배우는 것에 큰 흥미를 느낄 것임.
사람들이 복잡한 분리수거 규칙에 대해 잘 알지 못하는데, 게임 내에서 자연스럽게 분리수거 규칙을 배우고, 이를 실생활에 적용할 수 있음. 특히 분리수거를 게임의 목표나 미션으로 설정하여 즐겁고 흥미롭게 경험할 수 있도록 하는 것이 중요함.
일상 속에서 부담 없이 가볍게 즐길 수 있는 게임이 이들에게 적합하며, 복잡한 규칙이나 전략보다는, 적당한 조작감과 몰입도를 제공하는 아케이드 스타일의 게임을 즐기고자 함. 이 게임은 간단한 조작감을 가지면서도, 파워업 시스템과 타임어택 요소를 활용해 지속적으로 흥미를 느낄 수 있게 설계함.
- 고대 사원에 있는 몬스터를 피해 탐험하는 컨셉, 어둡고 박진감있는 그래픽
- “엔드리스 러너” 장르: 플레이어는 끝없이 달리며 장애물을 피하고 코인을 모은다.
- 최대한 오래 살아남는 것이 게임의 목표. 게임이 진행될 수록 진행 속도가 빨라짐
- 조작법: 좌우 스와이프로 방향 전환, 상하 스와이프로 점프와 슬라이드
- 모은 코인을 이용해 파워업, 캐릭터와 아이템 잠금 해제 등이 가능함
차별성
- 가지고 있는 쓰레기 (인벤토리)의 개념의 존재로, 보다 복잡한 조작 방식을 가짐
- 단일 스테이지로 오래 살아남는 것이 아닌, 여러 스테이지를 차례로 클리어해나가는 것이 목표
- “템플런”과 유사한 메커니즘을 가짐: “엔드리스 러너", 조작법, “코인", 리더보드
- 밝고 캐주얼하며, 생동감 있는 그래픽
- 모은 코인을 이용해 파워업, 새로운 캐릭터와 스킨을 구매할 수 있음
차별성
- 본 게임의 목표가 도덕적으로 우위에 있음 (Subway Surfers: 경찰에게서 도망치기, 본 게임: 여러 자원을 재활용하기)
- 단순히 달리는 것 이상의 여러 작업을 수행해야 되기 때문에, 보다 복잡한 조작 방식을 가지며, 보다 느린 속도감으로 진행됨
- 도로, 강, 철로 등 다양한 장애물을 피하면서, 가능한 한 멀리 이동하는 것이 목표
- 간단한 조작법, 레트로한 픽셀 아트 스타일의 아기자기한 그래픽
- 맵에 배치된 코인을 모아, 닭, 소, 펭귄, 고양이 등 100개 이상의 독특한 애니메이션과 소리를 가진 캐릭터를 잠금 해제할 수 있음
- 리더보드가 존재함; 최고 기록을 친구와 비교하면서 경쟁할 수 있음
차별성
- 단순히 길을 건너는 것 이상의, “여러 자원을 분리수거한다"라는 구체적인 목표가 있어, 뿌듯함을 느끼기 유리함
- “파워업" 시스템이 존재한다. 플레이어가 계속해서 강해질 수 있기에, 반복 플레이를 보다 더 거부감 없이 수행할 수 있다.
- 환경 문제에 관심있는 유저로서, 게임을 통해 분리수거에 관한 인식을 고취하고 싶다. 환경보호에 기여한다는 뿌듯함을 얻을 수 있도록
- 게임 애호가로서, 적절히 어려운 조작감을 가진 아케이드 게임을 플레이하고 싶다. 게임 클리어를 통해 성취감을 느낄 수 있도록
- 게임 스테이지를 플레이하고 있는 유저로서, 더 빠르고 더 정확하게 쓰레기를 분류하여 쓰레기통에 넣고 싶다. 더 높은 점수로 게임을 클리어해서 코인을 받을 수 있도록
- 게임 플레이어로서, 받은 코인을 이용해 파워업을 구매해 로봇을 업그레이드하고 싶다. 다음 스테이지를 수월하게 플레이하고, 기존 스테이지를 더 높은 점수로 깰 수 있도록
- 게임 플레이어로서, 목표까지 남은 거리를 알고 싶다. 남은 플레이 시간을 예측해서 안정감을 느낄 수 있도록
- 게임 플레이어로서, 현재 점수를 알고 싶다. 목표 점수를 달성하기 위해 더 노력해야 할지 포기해야 할지 알 수 있도록
게임 화면은 GPT, DALL-E를 이용해 생성한 가상의 이미지를 편집한 것입니다.
화면에서 다음과 같은 동작이 이루어집니다.
- 이동: 플레이어는 화면상의 격자를 상하좌우로 이동함
- 쓰레기: 색으로 쓰레기 종류 분류. 맵에 있는 쓰레기를 줍거나 던질 수 있음.
- 장애물: 정적 장애물 (라바콘, 나무)와 동적 장애물(트럭, 차)
- 카메라: 카메라는 시간의 흐름에 따라 앞으로 전진함
- 아이템: 맵에 있는 아이템을 주워 사용할 수 있음
- 타겟 환경: WASD, 스페이스 바를 입력할 수 있는 키보드와 모니터를 가진 컴퓨터
- OS : Linux, macOS, Windows
- Graphics: NVIDIA GeForce 480 / AMD Radeon Rx 460 이상
- CPU: Intel Core i3 2.00Ghz 이상
- RAM: 최소 2GB
- 네트워크: 오프라인에서도 플레이 가능
(유사한 디자인의 게임 Sky Tale, Match Village를 참고함)
ID | Name | Priority (H/M/L) | Effort (hours) | Description |
---|---|---|---|---|
B‑001 | 로봇 캐릭터 모델링 | H | 4 | 로봇 캐릭터 Blender 모델링. 참고 Rigging 및 애니메이션 (걷기, 쓰레기 줍기, 쓰레기 버리기 등) 추가. |
B-002 | 쓰레기 및 쓰레기통 아이템 모델링 | H | 6 | 종이, PET병, 캔, 음식물 쓰레기 각각의 쓰레기 아이템 Blender 모델링. 쓰레기 종류에 맞는 쓰레기통 (노란색: 종이, 파란색: PET, 빨간색: 캔, 초록색: 음식물) Blender 모델링. |
B-003 | 맵 디자인 타일 세트 및 화면 배경 생성 | H | 6 | 길건너 친구들 스타일의 블록 그리드 기반 맵 타일 세트 생성. 참고 타일 세트: 도로, 잔디, 인도 등. |
B-004 | 쓰레기 수거 및 버리는 애니메이션 | M | 3 | 로봇이 쓰레기를 줍고, 지정된 쓰레기통에 버리는 애니메이션 적용. 쓰레기를 잘못 버렸을 때의 변화 (예: 환경이 어두워지는 효과) 추가. |
B-005 | 정적 장애물 및 배터리팩 아이템 모델링 | H | 2 | 도로에 배치될 다양한 장애물 3D 모델링 정적인 장애물(animation 필요X): 나무, 라바콘 배터리팩 아이템 모델링. |
B-006 | 동적 장애물 모델링 | L | 3 | 동적인 장애물(animation 필요O): 자동차, 트럭, 동물 |
B-007 | 고정 맵 디자인 | H | 3 | 3번에 만든 타일 세트와 5번에 만든 장애물로 맵 디자인. |
B-008 | 진행 바 및 UI 요소 디자인 | H | 5 | 왼쪽 상단: 상단의 배터리(헬스) 바, 진행 바(남은 거리) 디자인. 중앙: 쓰레기 목록 표시줄 디자인. 오른쪽 상단: 점수 표시 UI 및 중지 버튼 디자인. |
B-009 | Particles 및 Audio | M | 3 | 쓰레기를 올바른 통에 버릴 때 particles, 올바르지 않은 통에 버렸을 때 particles. 게임 진행중 재생되는 음악. 쓰레기를 올바른 통에 버릴 때 효과음, 올바르지 않은 통에 버렸을 때 효과음 장애물과 충돌할 때 효과음. 배터리 바 차감 시 효과음. 레벨 완료 시 효과음. |
B-010 | 게임 종료 및 레벨 완료 화면 디자인 | H | 4 | 게임 시작 메뉴 화면 디자인. 레벨 완료 시 별 및 점수 표시 UI. 게임 종료 시 화면 디자인. |
B-011 | 파워업 요소 모델링 | L | 4 | 코인 아이콘 제작 |
ID | Name | Priority (H/M/L) | Effort (hours) | Description |
---|---|---|---|---|
UG‑001 | Dummy Map 생성 | L | 2 | 기능 구현을 위한 기초적인 맵 생성 |
UG-002 | Player: 이동 기능 구현 | H | 3 | Player object 생성 키보드의 화살표 키, 또는 W/A/S/D 키를 눌렀을 때 Player가 전/후/좌/우로 그리드 기준 1칸 이동하도록 구현 그리드 위에만 위치하도록 제한 Player의 이동 도중 다른 이동 명령이 들어오면, 그 명령을 무시하도록 구현 |
UG-003 | UI 구성 | M | 2 | 플레이어의 현재 목숨 표시 플레이어의 현재 진행도 표시 플레이어의 현재 가방 상태 표시 플레이어의 현재 점수 표시 “일시정지” 버튼 표시 |
UG-004 | Trash 기능 구현 | H | 1 | Trash object 생성 Trash가 위치한 칸으로 Player가 들어왔을 시 동작 구현: Trash는 사라지고, Trash의 종류에 대응되는 항목을 Player의 가방에 enqueue |
UG-005 | Player: 던지기 기능 구현 | H | 2 | Space 키를 눌렀을 때, 다음 동작을 수행하도록 구현: Player의 가방에서 첫 번째 item 제거 Player가 바라보는 방향으로 1칸 앞에, 제거된 item에 대응되는 종류의 Trash를 생성 |
UG-006 | Bin: 기능 구현 | H | 1 | Bin이 위치한 칸에 Trash가 생성되었을 시, 다음 동작을 수행하도록 구현 Trash object 제거 Trash object의 종류와, Bin의 종류가 일치하는지 확인 |
UG-007 | 화면 스크롤 구현 | M | 2 | Camera가 일정한 속도로 전진 Player의 위치에 따라 Camera를 맵의 목적지 방향으로 이동 “스크롤 하단부” 정의 Trash가 “스크롤 하단부”에 접촉했을 시, Trash object를 제거하고 목숨 1 감소 Player가 “스크롤 하단부”에 접촉했을 시, Player object를 화면 중앙으로 이동시키고 목숨 1 감소 |
UG-008 | 목적지 구현 | H | 1 | 목적지 object 생성 Player가 목적지 Tile에 도착하면, Level Clear 이벤트 발생 및 화면 표출 |
UG-009 | 레벨 실패 이벤트 구현 | H | 1 | Player의 목숨이 0이 되면 Level Over 이벤트 발생 및 화면 표출 |
UG-010 | 아이템: 배터리팩 구현 | M | 1 | 배터리팩 object 생성 배터리팩이 위치한 칸으로 Player가 이동했을 시, 다음 동작을 수행하도록 구현 배터리팩 object 제거 Player의 목숨을 1 증가 |
UG-011 | 움직이는 장애물 구현 | L | 2 | 특정한 패턴에 따라, 장애물이 맵 안에서 움직이도록 구현 플레이어와 마찬가지로 그리드 위에만 위치하도록 제한 |
UG-012 | Player: 정적 장애물 상호작용 구현 | L | 2 | 정적 장애물의 위치로 Player를 이동시키는 명령을 무시하도록 구현 |
UG-013 | Player: 동적 장애물 상호작용 구현 | L | 3 | 동적 장애물에게 플레이어가 밀리게 된다 동적 장애물과 플레이어가 같은 장소로 동시에 이동하는 경우, 플레이어의 이동 제한 |
UG-014 | Dummy Map 제거 | L | 1 | UG-001에서 생성했던 맵 삭제 |
ID | Name | Priority (H/M/L) | Effort (hours) | Description |
---|---|---|---|---|
UE‑001 | 시작화면(StartingScene) 구현 | M | 1 | 게임 제목 "에코히어로" 표시 "레벨 선택" 버튼 구현 : 누르면 LevelSelectScene으로 이동 "파워업 관리" 버튼 구현 : 누르면 PowerupManageScene으로 이동 |
UE-002 | 파워업 관리 화면 (PowerupManageScene) 구현 | M | 3 | 현재 적용된 Powerup의 이름과 기능 표시 현재 보유 코인 표시 아직 구매하지 않은 Powerup의 이름, 기능, 가격 표시 아직 구매하지 않은 Powerup마다 "구매" 버튼 표시 아직 구매하지 않은 Powerup 중 가격이 현재 보유 코인보다 큰 Powerup의 "구매" 버튼 비활성 "뒤로가기" 버튼 구현 : StartingScene으로 이동 구매" 버튼의 기능은 #009에서 구현 |
UE-003 | 레벨 선택 화면(LevelSelectScene) 구현 | M | 2 | 현재 코인 표시 전체 레벨(스테이지) 목록 표시 레벨(스테이지)의 상태 (클리어, 플레이 가능, 플레이 불가능) 표시 클리어 상태인 레벨에 별 개수 (0, 1, 2, 3) 표시 클리어 또는 플레이 가능 상태인 레벨 클릭 시 해당 레벨의 Scene으로 이동 "뒤로가기" 버튼 구현 : StartingScene으로 이동 |
UE-004 | 레벨 클리어 화면 (LevelClearScene) 제작 | H | 1.5 | "Level Clear" 메시지 표시 클리어 점수 표시 클리어 등급(별) 표시 이번에 획득한 코인 개수 표시 "뒤로가기" 버튼 구현 : LevelSelectScene으로 이동 "다시하기" 버튼 구현 : 해당 레벨의 Scene으로 이동 |
UE-005 | 레벨 실패 화면 (LevelOverScene) 제작 | H | 0.5 | "Game Over" 메시지 표시 "뒤로가기" 버튼 구현 : LevelSelectScene으로 이동 "다시하기" 버튼 구현 : 해당 레벨의 Scene으로 이동 |
UE-006 | Persistent Storage 학습 | M | 1 | Unity에서 Persistent Storage를 구현하는 방법 탐색 |
UE-007 | Persistent Storage 구현 | M | 2 | 코인, 레벨의 상태, 파워업의 적용여부를 저장소에 저장하여 게임이 재시작되어도 상태를 유지할 수 있도록 구현 게임 시작 시 코인을 0으로 초기화 게임 시작 시 레벨 1의 상태를 플레이 가능, 나머지의 상태를 플레이 불가능으로 초기화 게임 시작시 파워업의 적용여부를 False로 초기화 |
UE-008 | Level clear 기능 구현 | H | 2 | Level i를 클리어하면 Level i의 상태를 클리어, Level i + 1의 상태를 플레이 가능으로 변경 Level의 클리어 별 개수 업데이트 받을 코인이 있다면 코인 개수 업데이트 |
UE-009 | 파워업 구매 기능 구현 | M | 2 | 파워업을 구매하면 코인을 차감하고, 파워업의 적용여부를 True로 변경 |
UE-010 | 레벨 1 설계 및 제작 | H | 5 | 레벨 1을 손쉽게 "1별"로 클리어할 수 있도록 설계 레벨 1을 다소 어렵게 "3별"로 클리어할 수 있도록 설계 |
UE-011 | 파워업 종류 및 가격 선정 | M | 1 | 레벨 1을 "2별"로 클리어하면 파워업을 구매할 수 있도록 설계 레벨 2를 파워업이 있으면 손쉽게 "1별"로 클리어할 수 있도록 설계 |
UE-012 | 레벨 2 설계 및 제작 | M | 5 | 레벨 2를 파워업 없이 클리어할 수 없도록 설계 레벨 2를 파워업이 있으면 손쉽게 "1별"로 클리어할 수 있도록 설계 |
UE-013 | StartingScene 미화 | L | 2 | 배경 이미지 제작 및 삽입 게임 제목 폰트 수정 |
UE-014 | 별, 코인 아이콘 제작 | L | 1 | 채워진 별 / 빈 별 아이콘 제작 코인 아이콘 제작 |
UE-015 | LevelSelectScene 미화 | L | 2 | 배경 이미지 제작 및 삽입 별 개수를 채워진 별 / 빈 별 아이콘으로 표시 코인 개수 옆에 코인 아이콘 표시 |
UE-016 | LevelClearScene 미화 | L | 2 | 배경 이미지 제작 및 삽입 별 개수를 채워진 별 / 빈 별 아이콘으로 표시 획득한 코인 개수 옆에 코인 아이콘 표시 |
UE-017 | Play Mode 테스트 구현법 학습 | M | 2 | Unity Test Runner Framework에서 Play Mode 테스트 구현방법 학습 |
UE-018 | 이동 테스트 구현 | M | 2 | 맵 끝에서 상하좌우를 누르는 테스트 구현 |
UE-019 | 정적 장애물 테스트 구현 | L | 2 | 정적 장애물 방향으로 이동하는 버튼을 눌렀을 때 이동하지 않고 정지하는지 테스트 |
UE-020 | 쓰레기통 큐 테스트 구현 | M | 2 | 쓰레기 queue가 다 찼을 때 새로운 쓰레기를 주울 수 없는지 테스트 |
UE-021 | QA : 코인 획득 테스팅 | M | 1 | 레벨 1을 클리어했을 때 코인을 주는지 확인 레벨 1을 별 1개로 클리어한 뒤 더 높은 별로 클리어했을 때 차액만큼 코인을 주는지 확인 |
UE-022 | QA : 코인 사용 테스팅 | M | 1 | 획득한 코인이 파워업 관리 화면에 나타나는지 확인 획득한 코인으로 파워업을 구매할 수 있는지 확인 |
UE-023 | QA : 파워업 사용 테스팅 | M | 1 | 구매한 파워업이 레벨에 들어갔을 때 적용된 것이 느껴지는지 확인 |
UE-024 | QA : 저장소 테스팅 | M | 1 | 게임을 껐다 켰을 때 Powerup, 코인, 레벨 클리어 상태가 유지되는지 확인 |
체크포인트, 날짜 | 할일 | 완료 후 상태 | |
---|---|---|---|
디자인 | Unity | ||
1: 기본 게임 구조 설정 날짜: 11/06 (End of Sprint 1) |
맵 타일 제작 플레이어 모델 제작 |
레벨 선택 화면 구현 테스트용 맵 구현 카메라 이동 구현 플레이어 이동 구현 레벨 클리어 화면 구현 레벨 실패 화면 구현 |
레벨을 선택하고 클리어/실패할 수 있음 |
2-1: 플레이어 애니메이션 날짜: 11/13 |
플레이어 애니메이션 제작 | 플레이어 이동시 애니메이션 재생 | 플레이어 이동시 애니메이션을 볼 수 있음 |
2-2: UI 및 게임 진행 상태 표시 날짜: 11/13 |
진행바 아이콘 제작 | 인게임 UI 구현 (진행바 등) | 진행상태를 확인할 수 있음 |
2-3: 쓰레기 수거 및 상호작용 구현 날짜: 11/13 |
쓰레기 및 쓰레기통 모델 제작 | 쓰레기 줍기 구현 쓰레기 던지기 구현 쓰레기로 인한 목숨 감소 구현 |
쓰레기를 주워 쓰레기통에 버릴 수 있음 |
3: 맵 디자인 및 아이템/장애물 배치 날짜: 11/20 (End of Sprint 2) |
정적 장애물 모델 제작 배터리팩 아이템 모델 제작 장애물 배치 |
장애물 충돌 구현 배터리팩 아이템 획득 구현 |
장애물을 피하고, 아이템을 획득할 수 있음 |
4-1: 파티클 및 음향, 음악 날짜: 11/27 |
파티클 제작 음향 효과 제작 음악 선정 |
다양한 상황에서의 파티클 / 음향 재생 메인 음악 재생 |
파티클과 음향, 음악과 함께 게임을 즐길 수 있음 |
4-2: (시간이 있으면) 동적 장애물 날짜: 11/27 |
동적 장애물 모델 제작 동적 장애물 애니메이션 제작 |
동적 장애물 움직임 구현 동적 장애물 충돌 구현 |
동적 장애물을 피하며 게임을 즐길 수 있음 |
5-1: 테스팅 및 디버깅 날짜: 12/04 (End of Sprint 3) |
테스팅 및 디버깅 | 테스팅 및 디버깅 | 버그 없이 게임을 플레이할 수 있음 |
5-2: (시간이 있으면) 파워업 날짜: 12/04 (End of Sprint 3) |
파워업 아이콘 제작 | 코인 획득 및 사용 구현 파워업 효과 구현 파워업 관리 화면 구현 |
코인을 획득하고, 획득한 코인으로 파워업을 구매하여 게임을 플레이할 수 있음 |
6: 테스팅, 디버깅, 리팩터링 날짜: 12/18 (End of Sprint 4) |
테스팅, 디버깅, 리팩터링 | 테스팅, 디버깅, 리팩터링 | 버그 없이 게임을 플레이할 수 있음 코드가 읽기 쉬움 |
형상 관리는 팀 Github Repository를 통해 git으로 진행할 계획이다. 2명씩 페어를 이룬 2개의 조가 각각 일감을 맡아 개발한다. 각 페어코딩 세션에서는 일감 단위로 브랜치를 만들어 개발을 진행한다.
Gitflow 패턴을 따른다. Main, develop, feature 브랜치를 관리할 계획이다.
- main - 프로젝트 진행 중에는 직전 스프린트 완료 후, 프로젝트 종료 이후에는 최종 작업물.
- develop - 현재 개발중인 브랜치. 정상적으로 빌드 가능해야 함.
- feature (ft/{기능 이름}) - 각 일감이 개발중인 브랜치.
다음과 같은 흐름으로 머지를 진행한다.
- 각 기능 개발 완료 이후 ft/{기능 이름} 브랜치 → develop 머지 진행
- 각 스프린트 개발 및 QA 완료 이후 (또는 최종 결과물 제출 이전) develop → main 머지 진행 main 브랜치의 작업물에 버그가 발견되어 hotfix가 필요한 경우에도, 가급적 feature → develop → main 브랜치 순서대로 머지를 진행한다.
각 스프린트의 구현이 완료되고 나서, main 브랜치에 각 스프린트 결과물에 대한 태그를 생성한다. 평가자가 확인하기 좋도록, Merge 이후에도 Source branch를 삭제하지 않도록 할 것이다.
일감은 github issue를 통해 관리한다.
- 스프린트 시작 이전, 스프린트에서 개발할 내용을 모두 각각 이슈로 만든다. 이슈 하나는 PR 하나 (작업 분량 2시간 이내)로 해결될 수 있는 규모가 바람직하다.
- 개발 진행과정 중 언제든, 버그가 발견되거나 수정하면 좋을 사항이 있으면 이슈로 만든다. 개발 초반에 버그 리포팅을 위한 이슈 템플릿을 만들 예정이다.
Unity 프로젝트는 특성상 Conflict 발생시 resolve가 매우 힘들다. 개발 진행은 2개조로 진행하므로, 개발 일정을 슬랙과 구글 캘린더로 사전 조율하여 되도록 앞선 브랜치가 머지된 이후에 후속 개발이 진행될 수 있도록 한다. 부득이하게 시간적으로 겹칠 때에는 conflict가 발생하지 않도록 영역이 최대한 겹치지 않는 일감을 고르며, 가능하다면 같은 공간에서 함께 진행하는 것으로 한다.
- Pull Request 생성 규칙
- PR은 일감 (이슈) 단위로 만든다.
- PR description에는 이슈 번호, 구현에 대한 설명, (있다면) 리뷰시 주요사항 등을 넣는다. 개발 초반에 이를 포함한 PR 템플릿을 만들 예정이다.
- PR은, 2명 (Pair coder와 PM)의 approve를 받은 다음에 머지하는 것으로 한다. 단, 불가피할 경우에는 더 적은 approve로도 머지할 수 있다.
- 개발 초반에 CI/CD를 만들어서, 빌드와 테스트가 성공했을 때에만 머지 가능하도록 할 것이다.
- Commit message: 게시글의 commit message 양식을 간소화해서 따르는 것으로 한다.
- Commit message 앞에, Feat:, Fix:, Chore:, Test: 등의 prefix를 붙인다.
- Commit message에 수정사항을 명확하고 간결하게 적는다.
- 선택: 관련된 이슈 번호를 메시지 끝에 붙여준다.
- 유니티에서 제공하는 Test Runner 프레임워크를 활용하여 자동화된 단위테스트를 진행할 수 있음.
- Edit Mode방식을 사용하여 핵심 로직의 기능을 테스트할 예정.
- Edit Mode: Unity 에디터내에서 실행되며, 게임이 실제로 동작하지 않는 상태에서 테스트를 진행. 개별 컴포넌트나, 함수의 로직을 테스트 하는데 적합하며, 게임 오브젝트의 초기 설정, 에셋 로딩, 데이터 구조 등을 검증
예시 |
---|
맵 끝에서 상하좌우를 누르는 테스트 구현 |
정적 장애물 방향으로 이동하는 버튼을 눌렀을 때 이동하지 않고 정지하는지 테스트 |
쓰레기 queue가 다 찼을 때 새로운 쓰레기를 주울 수 없는지 테스트 |
- 그러나 게임 시스템의 복잡성으로 자동화 테스트로 완전히 커버하기 어려운 부분이 많고, 게임의 시각적 요소나 밸런스 등은 자동화 테스트로 검증하기 어려움.
- 핵심 로직과 수동 테스트로 확인하기 어려운 극단적인 케이스(queue 가 다 차는 경우)등을 제외하고는 수동으로 테스트를 진행할 것임.
- 스프린트 백로그 및 태스크 선정 이유
- 선정 이유: 개발 일정을 따름. 게임 개발에 필요한 초기 셋업이라고 판단하여 스프린트 1에서 진행하기로 결정함.
- (B-001) 플레이어 모델 제작 - 4시간
- (B-003) 맵 타일 제작 - 3시간
- (UE-003) 레벨 선택 화면 구현 - 2시간
- (UG-001) 테스트용 맵 구현 - 2시간
- (UG-007) 카메라 이동 구현 - 2시간
- (UG-002) 플레이어 이동 구현 - 3시간
- (UE-004) 레벨 클리어 화면 구현 - 0.5시간
- (UE-005) 레벨 실패 화면 구현 - 0.5시간
- Github Project 셋업 - 1시간
-
개인별 가용시간 체크 및 태스크 할당 표
이선재 김동욱 이상규 이정민 김준원 1주 (10/24 - 10/30) 2시간 2 2 2 2 5 2주 (10/31 - 11/06) 2시간 10 12 5 10 4 - 54시간 -> 페어로 나누면 27시간
- 태스크 17시간 / 가용 27시간 -> 48% buffer
- Driver / Navigator 선정
Driver Navigator (B-001) 플레이어 모델 제작 이선재 이상규 (B-003) 맵 타일 제작 이선재 이정민 (UE-003) 레벨 선택 화면 구현 이정민 이선재 (UG-001) 테스트용 맵 구현 김동욱 김준원 (UG-007) 카메라 이동 구현 김동욱 김준원 (UG-002) 플레이어 이동 구현 김동욱 이상규 (UE-004) 레벨 클리어 화면 구현 이정민 이선재 (UE-005) 레벨 실패 화면 구현 이정민 이선재 깃허브 프로젝트 셋업 이상규 이선재 -
데일리 스크럼 주기 선정 (진행 / 진행상황 업데이트)
- 주 3회 진행
- (오프라인) 월요일 수업 끝나고
- (오프라인) 수요일 실습시간
- (온라인) 토요일 밤 9시 30분
-
깃허브 이슈 생성
- 각 Navigator가 생성
-
일별 테스크 진행 요약 표 작성
- 코드 및 애셋 커밋 기록
- 번다운 차트 등
- Github Project 이용
-
잘 된 부분
- Load Factor (24 / 20.5) = 1.17 가 좋다
- 10/30 실습시간에 한 PP가 순조로웠음
- 앞으로도 실습시간을 적극 활용해 PP 진행
- "Parallel PP"의 가능성 발견
- Driver, Navigator 페어가 동시에 작업을 진행
- 태스크를 서로가 서로의 Navigator가 되도록 선정
- 각자 코딩을 하다가 중간에 서로의 것을 보고, 다시 각자 하다가, ...
- PP에 적합한 태스크와 아닌 태스크 분류
- PP를 하면 좋을 태스크 : 리팩터링, 디버깅(한 명은 QA 및 원인 탐색, 한 명은 코딩)
- 해도 좋고 안 해도 좋은 태스크 : Feature 구현
- 아닌 태스크 : Blender 태스크 (디자인에 대한 의견을 중간중간 구하는 것은 좋음)
-
안 된 부분
- 8 / 13의 태스크만 완료되었다
- 프로젝트를 함께 해 본 경험이 없어서 삐걱댔다.
- PR 리뷰 확인이 느리다. -> PR 리뷰 요청/코멘트 날린 뒤에 슬랙으로도 한 번 더 전달
- 태스크의 예상 시간을 개발 기준으로 정해서 PR 날리고 돌아오는 시간을 고려하지 못했다.
- PP를 한다면 리뷰 latency를 없앨 수도...?
- 백로그에 부족했던 Specification
- LevelClearScene에 별 다는 게 빠져 있었음
- 플레이어 모델 제작이 애니메이션까지 만드는 것인지 불명확
- 플레이어 이동이 장애물이나 애니메이션을 포함하는 것인지 불명확함
- 중간고사가 껴있어서 급하게 시작하고 급하게 끝남
- 백로그 선정 이후에 선정한 내용을 세부적으로 논의하기
- 계획이 틀어진 5개의 태스크의 사유
- 리뷰 프로세스의 지연
- 애매한 태스크 Specification으로 인한 재작업 (+ 로 인한 추가적인 리뷰 지연)
- 스프린트 종료일을 11/6로 생각해서 11/6 PP에서 진행할 생각이었으나 11/5에 종료됨
-
백로그 우선순위 조정 기록
- 우선순위 조정은 없었음
- 카메라 이동 구현 Driver가 플레이어 이동 구현에 시간을 많이 쓰게 되어 Driver를 변경
- 스프린트 회의 / 백로그 작성 등의 태스크를 추가함
-
스프린트 백로그 및 태스크 선정 이유
-
선정 이유: 이전 스프린트에서 완료하지 못한 태스크가 인당 1~2시간 내외로 적어, 그대로 가져가고 "더 열심히" 하는 방법을 택함.
-
이전 스프린트에서 넘어온 태스크
- (UG-002) 플레이어 이동 구현 (Pending Review) : 1시간
- (UE-003) 레벨 선택 화면 구현 (Minor Changes) : 1시간
- (UE-004) 레벨 클리어 화면 제작 (Minor Changes) (B-008 이용) : 1시간
- (UG-007) 카메라 이동 구현 (Work In Progress) : 2시간
-
새로운 태스크 (1주차)
- (B-001) 로봇 캐릭터 리깅 & 애니메이션 (쓰레기 줍기, 버리기, 걷기) : 6시간
- (B-008) 인게임 UI 디자인 : 3시간
- (B-002) 쓰레기 및 쓰레기통 아이템 모델링 : 4시간
- (UG-004) 쓰레기 줍기 기능 구현 : 1시간
- (UG-005) 쓰레기 던지기 기능 구현 : 2시간
- (UG-006) 쓰레기통 기능 구현 : 1시간
-
새로운 태스크 (2주차)
- (UE-001) 시작 화면 구현 : 1시간
- (UG-008) 목적지 구현 : 1시간
- (UG-009) 레벨 실패 구현 : 1시간
- (B-003) 맵 타일 구현 (나머지 2개 레벨) : 1시간
- (B-007) 맵 3개 디자인 (B-003, B-005 이용) : 4시간
- (UG-003) 인게임 UI 구현 (B-008 이용) : 2시간
- (B-005) 정적 장애물, 배터리팩 아이템 모델링 : 2시간
- (UG-012) 정적 장애물 상호작용 구현 : 2시간
- (UG-010) 배터리팩 아이템 구현 (B-005 이용): 1시간
- (UE-006) Persistence Storage 학습 : 1시간
-
PM 태스크
- 스프린트 2 시작 회의 : 0.5시간
- 스프린트 2 종료 회의 : 0.5시간
- 일별 태스크 진행 요약 작성 (스프린트 1에 대함) : 0.5시간
- 일별 태스크 진행 요약 작성 (스프린트 2에 대함) : 0.5시간
- Critical Path 분석 : 1시간
- 진척도 Update 및 리스크 분석 (1주차) : 2시간
- 진척도 Update 및 리스크 분석 (2주차) : 2시간
-
기타 태스크
- 디자인 패턴 선정 : 1시간
-
-
개인별 가용시간 체크 및 태스크 할당 표
이선재 김동욱 이상규 이정민 김준원 합계 1주 (11/06 - 11/12) 2시간 10 12 5 10 4 41 2주 (11/13 - 11/19) 2시간 10 12 10 10 7 49 - 90시간, 20% 버퍼 제외하면 72시간. 페어 프로그래밍 1.5배로 계산하면 48시간. 1주차 22시간 + 2주차 26시간.
- (이전 스프린트) + (새로운 태스크 1주차) = 22시간
- (새로운 태스크 2주차) = 15시간
- PM 태스크 = 6.5시간
- 1주차 25 / 22시간
- 2주차 18 / 26시간
- 1주차 태스크가 일부 2주차까지 지연될 것으로 예상.
- Driver / Navigator(Reviewer) 선정
- Driver가 깃허브 이슈 생성
- 태스크 할당 표는 아래와 같으나, 스케쥴 참고.
Task ID | Description | Driver | Navigator / Reviewer | Type | Start Date | End Date | Hours |
---|---|---|---|---|---|---|---|
P6 | 스프린트 2 시작 회의 | 이상규 | - | Team meeting - planning, admin & updates | 11-6-2024 | 11-6-2024 | 0.5 |
B-001 | 로봇 캐릭터 리깅 & 애니메이션 | 이선재 | 이상규 | Asset - Animation | 11-6-2024 | 11-12-2024 | 6 |
B-002 | 쓰레기 및 쓰레기통 아이템 모델링 | 이선재 | 이상규 | Asset - Model | 11-6-2024 | 11-12-2024 | 4 |
B-008 | 인게임 UI 디자인 | 이정민 | 이상규 | Asset - Model | 11-10-2024 | 11-13-2024 | 3 |
UG-004 | 쓰레기 줍기 기능 구현 | 김동욱 | 김준원 | Programming - features | 11-13-2024 | 11-16-2024 | 1 |
UG-005 | 쓰레기 던지기 기능 구현 | 김준원 | 김동욱 | Programming - features | 11-13-2024 | 11-16-2024 | 2 |
UG-006 | 쓰레기통 기능 구현 | 김동욱 | 김준원 | Programming - features | 11-13-2024 | 11-16-2024 | 1 |
UE-001 | 시작 화면 구현 | 이정민 | 이상규 | Programming - features | 11-6-2024 | 11-9-2024 | 1 |
UG-008 | 목적지 구현 | 이정민 | 이상규 | Programming - features | 11-14-2024 | 11-19-2024 | 1 |
UG-009 | 레벨 실패 구현 | 이정민 | 김준원 | Programming - features | 11-14-2024 | 11-19-2024 | 1 |
B-005 | 정적 장애물, 배터리팩 아이템 모델링 | 이선재 | 이상규 | Asset - Model | 11-14-2024 | 11-16-2024 | 3 |
B-007 | 맵 디자인 (타일과 장애물 이용) | 이선재 | 이상규 | Asset - Model | 11-17-2024 | 11-19-2024 | 3 |
UG-003 | 인게임 UI 구현 | 이정민 | 김동욱 | Asset - Model | 11-13-2024 | 11-19-2024 | 2 |
UG-012 | 정적 장애물 상호작용 구현 | 김동욱 | 김준원 | Programming - features | 11-6-2024 | 11-12-2024 | 2 |
UG-010 | 배터리팩 구현 | 김준원 | 김동욱 | Programming - features | 11-17-2024 | 11-19-2024 | 1 |
UE-006 | Persistence Storage 학습 | 이정민 | 이상규 | Programming - other | 11-10-2024 | 11-13-2024 | 1 |
P7 | 스프린트 2 회고 회의 | 이상규 | - | Team meeting - planning, admin & updates | 11-19-2024 | 11-19-2024 | 0.5 |
P8 | 일별 태스크 진행 요약 작성 (스프린트 1) | 이상규 | - | Project Management - update | 11-6-2024 | 11-6-2024 | 0.5 |
UG-002 | 플레이어 이동 구현 | 김동욱 | 김준원 | Programming - features | 11-6-2024 | 11-9-2024 | 1 |
UE-003 | 레벨 선택 화면 구현 | 이정민 | 이선재 | Programming - features | 11-6-2024 | 11-9-2024 | 1 |
UE-004 | 레벨 클리어 화면 제작 | 이정민 | 이선재 | Programming - features | 11-6-2024 | 11-9-2024 | 1 |
UG-007 | 카메라 이동 구현 | 김준원 | 김동욱 | Programming - features | 11-6-2024 | 11-9-2024 | 2 |
P9 | 디자인 패턴 선정 | 이상규 | - | Team meeting - planning, admin & updates | 11-9-2024 | 11-9-2024 | 1 |
P10 | 일별 태스크 진행 요약 작성 (스프린트 2) | 이상규 | - | Project Management - other | 11-19-2024 | 11-19-2024 | 0.5 |
P11 | Critical Path 분석 | 이상규 | - | Project Management - other | 11-8-2024 | 11-9-2024 | 1 |
P12 | 진척도 Update, 리스크 분석 (1주차) | 이상규 | - | Project Management - update | 11-6-2024 | 11-12-2024 | 2 |
P13 | 진척도 Update, 리스크 분석 (2주차) | 이상규 | - | Project Management - update | 11-13-2024 | 11-19-2024 | 2 |
- 잘 된 부분
- 싸우지 않고 스프린트를 잘 마무리함
- 계획한 만큼 시간을 씀
- 게임이 계획대로 잘 만들어지고 있다 (윤곽이 잡히고 있다)
- 디자인 패턴에 대한 필요성을 조기에 발견하고 잘 대처 중임
- 안 된 부분
- 완료되지 않은 태스크가 8개 있음
- 백로그에서 명확하지 않았던 구현 범위
- 로봇 캐릭터 리깅 & 애니메이션 태스크가 "애니메이션을 만드는 것"까지 vs. "게임에 적용하는 것"까지인지에 대한 견해 차이
- 스프린트 2에서 애니메이션까지 만들고, 스프린트 3에서 유니티에 적용하기로 함
- 로봇 캐릭터 리깅 & 애니메이션 태스크가 "애니메이션을 만드는 것"까지 vs. "게임에 적용하는 것"까지인지에 대한 견해 차이
- 백로그에서 고려하지 못한 의존성
- "주운 쓰레기"에 의존하는 태스크가 4개, "남은 목숨"에 의존하는 태스크가 3개 있었음. (아래 그림 참조)
- 이를 MVC 패턴으로 구현하기로 했으나, Model에 대해 논의할 시간을 확보하지 못해 미리 정해진 모델 구조 없이 각자 개발함
- 특히 쓰레기를 4종류로만 구별해서, 큐상에서 쓰레기의 구체적인 종류 (바나나, 캔, ...)를 나타낼 수 없는 문제가 있었음
- -> 다음 스프린트에서는 디자인 패턴 및 사용할 모델 구조에 대해 논의해서 확실히 정한 후 개발을 시작할 수 있도록 할 계획
- 쓰레기 줍기와 쓰레기 던지기 기능은 강한 연관성이 있지만 11/13 PP에서 함께 개발하면 괜찮을 것이라고 생각했는데, 당일에 장애물 배치에 집중하다 보니 쓰레기 관련 기능 구현이 완료되지 못하고 따로 PP 일정을 잡지 않으면서 개발에 어려움을 겪음
- 백로그 우선순위 조정 기록
- 쓰레기 "던지기" 기능의 구현 난이도가 높은데 반해, 실익이 낮다고 판단해 바닥에 쓰레기를 놓는 대신 쓰레기 큐를 "rotate"하는 기능을 구현하기로 스펙 변경
- 쓰레기 버리기 (던지기) 기능의 구현을 줍기 기능이 완성된 후에 시작하기로 해서 Hold함
- 목적지 기능을 목적지 타일이 완성된 후에 해야 해서 Sprint 3으로 Hold함
- 인게임 UI가 쓰레기와 목숨 데이터 Model이 완성된 후에 해야 해서 Hold함
- 배터리팩이 목숨 데이터 Model이 완성된 후에 해야 해서 Hold함
- DataManager 구현이 다음 스프린트에 예정되어 있었으나 이번 스프린트에 진행함
- 바나나 렌더링이 제대로 되지 않아 태스크를 만들어 해결함
- 쓰레기 배치 로직과 쓰레기 interaction (줍기, 버리기) 태스크를 2개의 PR에서 진행함
- 스프린트 백로그 및 태스크 선정 이유
-
선정 이유: 이전 스프린트에서 넘어온 태스크의 양과 줄어든 개발 시간을 고려해, 동적 장애물을 포기하기로 결정.
-
파워업이 구현되고 완성도가 낮은 게임 vs. 파워업 없이 완성도가 높은 게임을 비교함.
- 파워업 없이도 충분히 재미있는 게임이 될 수도 있을 것이라고 생각함.
- 따라서, 파워업을 포기하고 스테이지의 난이도를 조절하는 데 시간을 더 쓰기로 결정함
-
이전 스프린트에서 넘어온 태스크 (14시간)
- (UE-010) 레벨 1 설계 및 제작 : (Incomplete) 2시간
- (UG-004) 쓰레기 줍기 기능 구현 : (Pending review) 1시간
- (UG-005) 쓰레기 버리기 기능 구현 : (Incomplete) 2시간
- 플레이어 애니메이션 적용 : (Not Started) 3시간
- (UG-010) 배터리팩 아이템 구현 : (Not Started) 2시간
- (UG-003) 인게임 UI 구현 : (Incomplete) 1시간
-
게임 클리어 (4시간)
- 목적지 타일 제작 : 1시간
- (UG-008) 목적지 구현 : 1시간
- 게임 클리어 구현 : 1시간
- 실시간 점수, 최종 점수 계산 : 1시간
-
파티클 및 음향 효과 (5.5시간)
- (B-009) 파티클 효과 제작 : 1시간
- (B-009) 음향 효과 제작 또는 선정 : 1시간
- (B-009) 게임 음악 선정 : 1시간
- 파티클 및 음향 효과 적용 : 1.5시간
- 음악 재생 : 1시간
-
스테이지 디자인 (12시간)
- 레벨 2용 타일 제작 : 2시간
- (UE-012) 레벨 2 설계 및 제작 : 4시간
- 레벨 3용 타일 제작 : 2시간
- 레벨 3 설계 및 제작 : 4시간
-
테스팅 (3시간)
- (UE-021) 게임 클리어 테스팅 : 1시간
- 게임 실패 테스팅 : 1시간
- (UE-024) Persistent Storage 테스팅 : 1시간
-
UI 미화 (7시간)
- (B-010) Start, LevelSelect, LevelClear, LevelFail 화면 디자인 : 2시간
- (UE-013) StartingScene 미화 : 1.5시간
- (UE-015) LevelSelectScene 미화 : 1.5시간
- (UE-016) LevelClearScene, LevelOverScene 미화 : 2시간
-
PM 태스크 (6시간)
- 스프린트 3 시작 회의 : 1시간
- 스프린트 3 종료 회의 : 0.5시간
- 일별 태스크 진행 요약 작성 : 0.5시간
- Critical Path 분석 : 1시간
- 진척도 Update 및 리스크 분석 (1주차) : 0.5시간
- 진척도 Update 및 리스크 분석 (2주차) : 0.5시간
- 스프린트 3 회고 회의 준비 : 0.5시간
- 스프린트 4 시작 회의 준비 : 1.5시간
-
기타 태스크 (1시간)
- 디자인 패턴 논의 : 1시간
- 개인별 가용시간 체크 및 태스크 할당 표
이선재 김동욱 이상규 이정민 김준원 합계 1주 (11/20 - 11/26) 2시간 10 10 10 10 10 50 2주 (11/27 - 12/03) 2시간 5 12 7 10 7 41
- 91시간, 20% 버퍼 제외하면 73시간. 페어 프로그래밍 1.5배로 계산하면 49시간. 총 태스크 52.5시간.
- 스프린트 4는 기말고사 기간임을 고려해서 QA와 리팩터링 기능에 집중하고, 이번 스프린트에 무리해서라도(52.5/49 시간) 완료하기로 계획.
- 스프린트 내 개발 완료가 무엇보다 중요한 만큼 스프린트 기간을 아래의 4개 기간으로 나누어 관리
- Checkpoint 1 : 11/20(수) - 11/23(토)
- Checkpoint 2 : 11/24(일) - 11/26(화)
- Checkpoint 3 : 11/27(수) - 11/30(토)
- Checkpoint 4 : 12/01(일) - 12/03(화)
- 페어 프로그래밍은 11/27(수) 실습시간에 진행하기로 결정
- 12/3에 기말고사가 있는 점을 고려해, 첫 3개 Checkpoint에 대부분의 태스크를 배치함.
- dependency graph를 그려 태스크를 계획함
- C1, C2, C3, C4는 각 태스크가 몇 번 체크포인트 안에서 진행될 계획인지 나타냄
- ALL, ㄷㅇ(동욱), ㅈㅇ(준원), ㅅㅈ(선재), ㅈㅁ(정민), ㅅㄱ(상규)는 태스크의 Driver의 이니셜을 나타냄.
- 파란색으로 형광펜 칠한 부분이 이번 스프린트의 Critical Path임.
- 태스크 할당 표의 구체적인 내용은 스케쥴 참고.
- 잘 된 부분
- 스프린트 3까지 게임의 대부분의 기능이 구현 완료됨 v1.1.0
- "1주차까지 게임 구현 완료"의 목표를 달성함 v1.0.0
- 테스팅을 통해 문제점을 발견하고 버그를 고침 #60 #72
- 계획된 시간을 사용하고, 80% 이상의 태스크를 완료함 (https://github.com/2024FALL-SWPP/team-project-for-2024-fall-swpp-team-02/issues/72) #73
- 갑작스러운 휴강 시간을 적극 활용하여 PP를 진행함
- 안 된 부분
- Checkpoint 1, 2, 3, 4로 나눠서 진행하였으나 계획에 변동이 많았음
- 팀원의 대회, 퀴즈, 기말고사 등 일정으로 인한 가용시간 감소가 예상보다 컸고, 이에 유연하게 대처하지 못함
- (UG-010) 배터리팩 아이템 구현이 C1 (11/20-11/23)에 계획했으나 C3가 시작할 때(11/27)에 완료(#76)됨
- (B-009) 파티클 효과, 음향 효과가 C2, 음악 선정, 효과 적용이 C3에 계획했으나 파티클 효과는 담당자 변경 후 C3에(#82), 나머지는 C4가 끝날 때(#105)에 시작되었음.
- 이로 인해 Scene 미화 관련 계획이 Hold됨
- -> 일정을 맞추지 못할 것으로 예상되면 빠르게 PM에게 알리고, 태스크를 재분배하는 등의 방법으로 태스크를 모두 수행할 수 있도록 하기
- 스크럼에서 진행 상황에 대한 Update는 받았지만 PR이 올라오지 않아 후속 작업이 늦어짐
- (UE-010) 레벨 1 설계가 C2에 계획했고 C3 시작 (11/27 PP)에 거의 완료되었으나, PR이 스프린트 종료 직전에 올라와 후속 작업이 스프린트 직전에 수행됨 (#100)
- -> 기능이 완성되기 전에도 Draft PR의 형태로 진행상황 Commit하고 push해두기
- 계획이 변경되고 시간에 쫓기면서 PR이 거대해지고 리뷰가 승인되는 확률이 높아짐
- 예상치 못한 변수가 많았다
- 백로그 우선순위 조정 기록
Task ID | Description | 변경 항목 | 변경 전 | 변경 후 | 비고 |
---|---|---|---|---|---|
UG-010 | 배터리팩 아이템 구현 | Checkpoint | C1 | C2 | 지연 |
B-009 | 파티클 효과 제작 | 담당자 | 김동욱 | 이선재 | 태스크 과다 |
B-009 | 음향 효과 제작 또는 선정 | Checkpoint | C2 | C3 -> C4 | 지연 |
B-009 | 파티클 및 음향 효과 적용 | Checkpoint | C3 | C4 | 지연 |
B-009 | 게임 음악 선정 | Checkpoint | C3 | C4 | 지연 |
P30 | 음악 재생 | Checkpoint | C3 | C4 | 지연 |
UE-024 | Persistent Storage 테스팅 | Checkpoint | C1 | C4 | 테스팅 및 디버깅 |
P31 | 게임 실패 테스팅 | Checkpoint | C2 | C4 | 테스팅 및 디버깅 |
UE-021 | 게임 클리어 테스팅 | Checkpoint | C3 | C4 | 테스팅 및 디버깅 |
B-010 | Start, LevelSelect, LevelClear, LevelFail 화면 디자인 | 우선순위 | Not Started | Hold | 우선순위 낮다고 판단 |
P32 | 레벨 3 설계 및 제작 | 우선순위 | Not Started | Hold | 우선순위 낮다고 판단 |
UE-013 | StartingScene 미화 | 우선순위 | Not Started | Hold | 우선순위 낮다고 판단 |
UE-015 | LevelSelectScene 미화 | 우선순위 | Not Started | Hold | 우선순위 낮다고 판단 |
UE-016 | LevelClearScene, LevelOverScene 미화 | 우선순위 | Not Started | Hold | 우선순위 낮다고 판단 |
장애물 방향으로 가려고 하면 회전 | 신설 | X | 신설 | 신설 | |
쓰레기 큐가 가득 찼을 때 예외 처리 | 신설 | X | 신설 | 신설 | |
Linter 적용 | 신설 | X | 신설 | 신설 | |
CI 구축 | 신설 | X | 신설 | 신설 |
- 스프린트 백로그 및 태스크 선정 이유
-
마지막 스프린트이므로 프로젝트 제안서에 있었던 모든 태스크를 완료해야 함.
-
프로젝트 제안서 계획대로 테스팅 (및 디버깅), 리팩터링을 집중적으로 수행
-
프로젝트 제안서에 있었던 UE-021 ~ UE-024 중 코인 획득과 저장소 테스팅은 이미 수행하였고, 코인 사용은 구현하지 않을 계획이라 추가하지 않음.
-
완성도가 떨어지는 레벨 3개 vs. 완성도가 높은 레벨 2개를 고려할 때, 데모 시간이 제한되어 있으므로 레벨 2개에 집중하는 것이 좋다고 판단함.
-
사용 설명서가 제출물에 포함되어 있으므로 튜토리얼을 만들지 않기로 결정함.
-
파티클 및 음악: 2시간
- 선정 이유: 음향과 파티클은 게임의 재미에 핵심적인 역할을 하고, 저번 스프린트에서 완료되지 않아 이월하여 선정함.
- 파티클 효과 구현: 1시간
- 버튼 클릭 효과음 구현: 1시간
- 선정 이유: 아래 태스크들은 12/4(수) 0시 ~ 회의 전까지 완료되었으나, 저번 스프린트에 완료했다고 볼 수 없어 이번 스프린트에서 처리한 것으로 간주함.
- 게임 음악 선정: 2시간
- 음향 효과 적용: 2시간
- 음악 재생: 1시간
-
각종 Scene 미화: 3시간
- 선정 이유: 현재 각종 Scene이 기본적인 UI만 있어 게임의 퀄리티가 낮아 보임. 최소한의 퀄리티를 만들기 위해 Scene 미화에 시간을 투자하지만, 본 게임이 중요하므로 너무 많은 시간을 쓰지 않도록 함.
- (UE-013) StartScene 미화 (오브젝트 배치): 1시간
- (UE-015) LevelSelectScene 미화 (StartScene 복사 후 수정): 0.5시간
- (UE-016) LevelClearScene 미화 (StartScene 복사 후 수정): 0.5시간
- LevelOverScene 미화 (StartScene 복사 후 수정): 0.5시간
- (UE-014) 코인 아이콘 제작 및 적용 (후순위) : 0.5시간
-
스테이지 완성도 높이기: 4시간
- 선정 이유: 게임 자체의 재미가 가장 중요하므로 밸런스 조정 작업을 수행하고, 배경을 기본 배경 대신 예쁜 배경으로 변경하고자 함.
- 최종 점수 실시간 점수에 맞추기
- 레벨 1 Skybox 넣기: 1시간
- 레벨 1 밸런스 조정: 1시간
- 레벨 2 Skybox 넣기: 1시간
- 레벨 1 밸런스 조정: 1시간
-
테스팅: 5.5시간
- 선정 이유: 게임의 작동을 보장하기 위해 기본적인 요소 위주로 Release 버전에 대해 수동 테스팅을 진행함.
- UI Navigation Test(시작 화면 -> 레벨 선택 -> 플레이 -> 재시작 -> 뒤로가기): 1.5시간
- In-Game Test(이동, 회전, 장애물, 쓰레기, 목숨, 클리어, 실패): 2.5시간
- Effect Test(효과음, 음악, 파티클): 1.5시간
-
테스팅 및 리팩터링: 5시간
- 선정 이유: 쓰레기 관련 Enum이 초기 계획과 다르게 덧붙여지면서 코드가 지나치게 복잡해짐. 리팩터링을 통해 구조를 단순화하고자 함.
- 쓰레기 관련 Class 정리 및 UML 작성: 1시간
- 쓰레기 관련 Class중 바뀌지 않아야 하는 로직에 대한 테스트 작성: 1시간
- 쓰레기 관련 Class 리팩터링: 2시간
- 쓰레기 관련 Class에 대한 테스트 수행 및 디버깅: 1시간
-
PM 태스크: 4시간
- 선정 이유: PM 업무 수행에 필요한 기본적인 태스크임
- 스프린트 4 시작 회의: 1시간
- 스프린트 4 종료 회의: 0.5시간
- 일별 태스크 진행 요약 작성: 0.5시간
- Critical Path 분석: 0.5시간
- 진척도 Update(1주차): 0.5시간
- 진척도 Update(2주차): 0.5시간
- 스프린트 4 회고 회의 준비: 0.5시간
-
프로젝트 마무리 태스크: 6시간
- 선정 이유: 마지막 스프린트에 필요한 제출 항목을 제작하기 위함
- 모든 문서를 요약한 문서 작성: 1시간
- 게임 사용 설명서 작성: 1.5시간
- 최종 발표 자료 제작: 1.5시간
- 최종 데모 게임 빌드 및 배포: 1시간
- 최종 발표 준비: 1시간
- 개인별 가용시간 체크 및 태스크 할당 표
이선재 김동욱 이상규 이정민 김준원 합계 1주 (12/04 - 12/10) 2시간 6 6 6 3 6 27 2주 (12/11 - 12/17) 3시간 3 3 3 8 6 23
총 50시간. 버퍼 20% 부여하면 40시간. 리뷰 1.5배 고려하면 50/1.5 = 26시간. 총 태스크 27.5+2시간. 2시간은 스프린트 4 회고 회의, 최종 발표 준비에 해당하는 시간으로 스프린트 종료 후에 진행하게 되므로 가용시간 내에 포함하지 않아도 된다. 1.5시간이 넘치지만 PM 태스크는 1.5배가 아니므로 강행한다.
- 파티클 및 음악 : 준원
- Scene 미화, Skybox 넣기: 선재, 정민
- 리팩터링: 준원, 상규
- UI 테스팅: 준원
- In-game 테스팅: 선재
- Effect 테스팅: 동욱
- 설명서, 발표자료: 정민, 상규
- 최종배포: 상규
- 잘 된 부분
- 디버깅 세션의 취지에 맞게 꼼꼼하게 게임을 뜯어 버그를 고쳤다.
- 남은 버그 리스트는 1개. Minor하다고 판단해 새로운 버그 생성을 막기 위해 고치지 않기로 결정했다.
- QA 과정을 통해 사소한 버그를 놓치지 않고 fix할 수 있었다.
- 중간에 정한 목표대로 게임의 완성도를 높이는 데 성공했다.
- UI와 스테이지 모두 귀엽고 통일된 분위기를 준다.
- 점수가 적절하게 계산되어 1별 / 2별 / 3별을 쓰레기를 잘 주운 정도에 따라 부여한다.
- 비어 있던 레벨 3를 웹페이지로 추가했다.
- 사소한 부분까지 터치하여 사용자 경험을 향상시켰다.
- 계획한 시간에서 크게 벗어나지 않게 스프린트를 마무리했다.
- 기말고사 기간인 것을 감안해서 약 40시간의 태스크를 계획했는데, 마지막 스프린트에서 무리한 버닝 (예. 24시간 밤샘 코딩)을 하지 않고 약 44시간 정도에 잘 끝냈다.
- 기획 단계에서 구상한 게임과 일치하는 게임을 만들었다.
- 화목하게 프로젝트를 마무리했다.
- 모두에게 소중한 경험이었고, 많이 배웠다는 의견이 지배적이다.
- 안 된 부분
- 기말고사 기간이라 정신이 없었던 걸 감안하더라도 태스크 분배가 매끄럽지 못했다.
- 다음에는 새로 생겨나는 버그들을 어떻게 관리하고 담당할지 명확히 하는 게 좋겠다.
- 앞 스프린트에서 밀린 일에 스프린트 4에 예정되었던 것까지 같이 하면서 급하게 마무리해야 했다.
- 마지막에 QA를 진행하면서 "QA fix"와 같은 형태로 PR을 머지하기도 했다. #139
- 다음에 다시 한다면 시간을 잘 분배해서 스테이지 3이나 튜토리얼까지 만들어 볼 수 있을 것 같다.
- 게임의 목적을 잠깐 잊었다.
- 환경 문제에 대한 경각심 고취, 분리수거 학습 효과의 방향성을 놓치고 재미만을 추구하며 개발을 마무리했다.
- 추가적인 스토리텔링을 통해 놓친 가치를 다시 찾을 수 있을 것 같다.
- 백로그 우선순위 조정 기록
Task ID | Description | 변경 항목 | 변경 전 | 변경 후 | 사유 |
---|---|---|---|---|---|
P37 | 파티클 효과 적용 | 담당자 | 김준원 | 이정민 | 담당자 업무 지연 |
P46 | 레벨 1 밸런스 조정 | 내용 | 맵 전체 조정 | 점수 체계만 조정 | 시간 부족 |
P47 | 레벨 2 밸런스 조정 | 내용 | 맵 전체 조정 | 점수 체계만 조정 | 시간 부족 |
P65 | 최종 발표 자료 제작 | 담당자 | 이상규,이정민 | 이상규,이선재 | 희망자로 변경 |
P70 | CD 구축 | - | - | - | 신설 |
P71 | WebGL 빌드 오류 해결 | - | - | - | 신설 |
P72 | 스테이지 3 대신 웹페이지 띄우기 | - | - | - | 신설 |
스케줄을 참고해 주시기 바랍니다.
10/27
- 스프린트 1 시작 회의
- 깃허브 프로젝트 셋업
10/30 (실습)
11/2
- 플레이어 이동 구현 801bdc2
11/3
11/4
- 레벨 실패 화면 구현 b5ba3da
- 스프린트 2 백로그 작성
11/5
- 플레이어 모델 제작, 맵 타일 제작 705b302
- 플레이어 이동 버그수정 (리뷰 반영) 604d8c5
- 레벨 선택 화면 리뷰 반영 c7d0c1e
- 레벨 클리어 화면 리뷰 반영 8cb6975
- 레벨 실패 화면 수정 f103c9e
11/6
11/9
11/10
- 쓰레기통 모델링 84a242d
11/11
11/12
11/13
11/15
- DataManager 구현 완료 f06fd9c
11/16
- 배터리팩 아이템 모델링 dfd92d6
11/17
11/18
- 맵 타일 수정 9fed1d7
11/19
11/20
- 수업 내용
- 실습
- (UG-003) 인게임 UI 구현 d809b1f
11/22
- (P24) 목적지 타일 제작 282c7f1 등
11/23 End of Checkpoint 1
- (UG-004) 쓰레기 줍기 898a640 등
- (P23) 플레이어 애니메이션 (Idle, 이동) 적용 781eab4 등
- (P24) 목적지 타일 피드백 #58 549887c
- (UG-008) 목적지 구현 b5bf9f1 등
- (UE-024) Persistent Storage 테스트 작성 #60-comment1
11/25
- (UG-010) 배터리팩 아이템 FBX로 Unity에 불러오기 2f4c525
- (P35) 린터 CI fix 9c2a9eb 등
- (P23) 플레이어 애니메이션 리뷰 반영 417e559
- (P25) 레벨 2 타일 제작 1e7ce6f
- (P26) 레벨 3 타일 제작 e017fcd
11/26 (End of Checkpoint 2)
- (UG-008) 목적지 구현 디자인 패턴 리뷰 반영 5126f9a
- (P23) 플레이어 애니메이션 2차 리뷰 반영 df2eddc
- (P25) 레벨 2용 장애물 제작 9025a24
- (P27) 점수 계산 구현 b72eb06
11/27 (폭설로 비대면 PP)
- PP 이전 개인 작업
- (UG-003) 인게임 UI 구현 5056761 등
- (UG-008) 목적지 구현 디자인 패턴 리뷰 반영(cont'd) f8fbb75
- (UG-005) 쓰레기 버리기, 돌리기 구현 1272b21
- (UE-021) 게임 클리어 테스트 작성 #72-comment1
- (P31) 게임 실패 테스트 작성 #73-comment1
- 인게임 기능 PP (이정민, 이상규)
- 레벨 2 제작 PP (이선재, 김동욱)
- (P25) 레벨2 모델 FBX export e97fad4 등
- 레벨1, 2 제작 방향 논의
- PP 이후 개인 작업
- (P23) 쓰레기 줍기/버리기 애니메이션 적용 6098503
11/28
- (B-009) 파티클 효과 제작 951536e 등
11/29
- (UE-012) 레벨 2 제작 1206673
11/30
- (P33) "장애물 방향 Rotation" 버그 수정 63529d5
12/02 (휴강으로 PP: 사진은 남기지 못함)
- 테스트 PP (이선재, 이상규)
- (UE-024) PersistentStorage 테스트 fail #60-comment2
- (UE-021) 게임 클리어 테스트 fail #72-comment2
- (P31) 게임 실패 테스트 fail #73-comment2
- (UE-024) PersistentStorage 테스트 fix b0f7574 등
- (P36) CI 구축 및 자동화 Test 구현 71e13b1 등
- 레벨 1, 2 제작 PP (이정민, 김동욱)
- (UE-012) 레벨 2 완성 05b5ea3 등
12/03
- 버그 fix
- 테스트 실패 반영
- 테스트 다시 수행
- (UE-024) PersistentStorage 테스트 Success #60-comment3
- (UE-021) 게임 클리어 테스트 Success #72-comment3
- (P31) 게임 실패 테스트 Success #73-comment3
- (B-009) 음향 효과 선정 0bf371b
12/4 (PP, 휴강 및 실습 시간 활용)
- (P15) 스프린트 종료 회의 9차 회의
- (P70) CD 구축 add72e5 등
- (B-009, P29, P30) 인게임 음향 효과, 음악 선정 및 적용 (무료 애셋: #104 #105 참고) d16fb32 등
- (P49) Pause 버튼 버그 fix 3d34d90 등
- Scene 미화
- 리팩터링
12/6
12/7
- (P42) LevelOverScene UI 수정 3b31202
- (P41) LevelClearScene UI 수정 7848d68
- (P40) LevelSelectScene UI 수정 ce987c7
- Level 1 머지 6b6b036
12/8
12/9 (Scrum)
- (P43) 코인 이미지 추가 22aad49
12/11 (PP)
- (P37) 파티클 효과 적용 172d1e4
- (P48) UI QA 진행 및 버그 수정 077b1a1 등
- (P49) In-game QA 진행 및 버그 수정 e17f574 등
- (P71) WebGL 빌드 이슈 해결 (CD 수정) d61c854 등
12/12 ~ 12/14
- 기말고사 기간으로 활동 없음.
- 강의시간(휴강시)/실습시간만 활용하여 프로젝트 집중 수행
12/15
- (P48) 레벨 선택 화면 버그 fix 44abf5f
12/16 (PP, 휴강 시간 활용)
- (P64) 게임 설명서 작성 및 인게임 버튼 추가 22a6a2c
- (P46, P47) 점수 밸런스 조정 715f9cc
- (P50) Effect QA 진행 및 버그 fix
- (P72) 스테이지 3 대체 웹사이트 제작 bd183de
- (P72) 웹사이트를 포함하여 CD fix f6afdf4 등
12/17 (D-1)
스케줄을 참고해 주시기 바랍니다.
- 전반적으로 Planned와 Actual이 일치하여, 프로젝트가 계획대로 잘 수행되었음을 보여줌.
- 스프린트 1과 4는 각각 중간고사, 기말고사 기간으로 기울기가 완만한 편이고, 스프린트 2와 3이 기울기가 가팔라 집중적인 개발이 이루어졌음을 보여줌.
- 스프린트 4가 1에 비해 기울기가 가파른 것은 휴강시간과 실습시간을 활용하여 개발할 수 있었던 덕도 있고, 마감을 위해 노력한 면도 있음.
- TM은 스프린트 1, 2에서 다소 낮은 모습을 보여주고, 3, 4로 갈수록 개선됨.
- 개발자도 Unity나 Blender에 익숙해지고 자신의 가용 시간에 대한 감을 더 잡아가고, PM도 태스크 배정을 하다보니 실력이 늘어 TM이 개선되는 것으로 보임.
- 스프린트 4는 마감을 맞추기 위해 TM이 1 이상이 될 수 밖에 없었던 환경인 면도 있음.
- 프로젝트를 다시 진행한다면 스프린트 1, 2에 시간을 더 효율적으로 활용하여 태스크를 완료하는 게 중요할 것으로 보임.
- 스프린트 1에서는 비교적 쉬운 Repository Setup, 기본 맵 구현 등을 PP로 진행하며 PPHM이 1에 가까웠음.
- 스프린트 2, 3으로 가면서 더 어렵고 복잡한 태스크를 PP에 배정하면서 시간을 예상보다 많이 쓰게 돼 PPHM이 낮아짐.
- 스프린트 4에서는 다소 개선되었으나 발표자료 준비에 예상보다 많은 시간이 소요됨.
- 계획할 때 가용시간을 맞추기 위해 PP 시간을 "같이 하면 금방 할 수 있을 거야!"라며 깎았지만 함께 하게 된다고 일을 더 빨리 하게 되는 것은 아니라 PPHM이 낮은 것으로 보임.
- Load Factor는 프로젝트 전체에 걸쳐 0.8 ~ 1.2 사이의 값을 가지면서 가용 시간을 잘 반영해 계획했다는 점을 알 수 있었음.
- 스프린트 2에서 쓰레기 관련 로직의 의존성 때문에 헤맨 부분, 스프린트 4에서 WebGL, CD 등 배포에서 헤멘 부분이 Load Factor 감소에 주요했던 것으로 보임
- 나머지 두 스프린트에서는 특별한 문제가 없어 Load Factor가 1 이상인 것으로 보임
- HPM은 전체적으로 평균 60시간 주변 (50~70시간)에서 분포하는 것으로 보임.
- 선재님이 Asset을 주로 담당하시고, 부PM으로서 프로젝트 관리 태스크에 참여해 Non-prog Hours가 많음
- 상규님(PM)이 모든 Asset의 리뷰를 담당해서 Non-prog Hours가 많음
- Participant와 PP가 1:1로 반영되는 구조인데, 현재는 PP 대신 리뷰로 진행되는 경우가 많아 개인별 기여도를 정확하게 반영하기에는 무리가 있음
- HPM이 가장 많은 두 명이 현재 프로젝트에 불만을 가지지 않고 있고, 나머지 팀원의 시간도 60시간 정도로 비슷해 큰 불화 없이 프로젝트가 마무리되었음.
- 상규님(PM)이 마지막 스프린트에 버그 fix에 시간을 쓰면서 Prog Hrs가 높아졌음.
- Singleton Pattern
- DataManager : MonoBehavior를 상속받고 static member
Instance
로 유일한 인스턴스 반환 - 여러 개 Scene에서 공유하는 데이터를 관리
- 모두 DataManager에 넣기 (비대한 DataManager)
- 많아지면 분야별로 나눠서 LevelManager, PowerupManager, ... 등의 Singleton을 각각 관리
- DataManager : MonoBehavior를 상속받고 static member
- MVC(Model-View-Controller) Pattern
- 게임 잔여 시간, 게임 진척도 (맵상에서 몇% 왔는지), 목숨 개수, 쓰레기 상태
- Model <---subscribe--- View
- Model ----Update-----> View
- Model ----Read-------> Controller
- Model <---update------ Controller
- Model(data만 들어있는 class), Controller(함수가 들어있는 class)는 GameScene에서만 쓰는 Singleton.
- View는 각 UI Component마다 만들어서 Model에 subscribe : 찾아보기
- GameScene을 새로 load했을 때 초기화 : Model의 초기값 사용하고, Level-specific한 값들은 Global Singleton(LevelManager, GameManager 등) 이용
- Strategy Design Pattern
- InputController class로 추후 입력방식의 확장을 용이하게 제작
- Observer Design Pattern
- MVC에서 "View"가 "Model"에 subscribe.
-
관리 방식
- DataManager 싱글톤 클래스 이용.
- JSON 파일 형태로 로컬에 저장/로드
- 개발 중에는 repository 내에 세이브파일을 저장하여 push.
- Release 상태에서는 영구적인 경로에 저장(
Application.persistentDataPath
)
- Scene 이동간 데이터 전달 필요시 DataManager에 맡기고 찾음
- LevelPlayInstance:
- int sceneNumber
- int score = 0
- LevelPlayInstance:
- 영구히 저장하여야 하는 데이터는 DataManager에 저장/불러오기.
- int coin
- Powerup 구매시 감소
- Level Clear시 업데이트
- bool[] isPowerupActive
- GameScene에서 이용
- Powerup 구매시 true로 업데이트
- LevelData[] levelDataList
- Level Clear시 해당 레벨 LevelData 업데이트
- Level Clear 정보 저장
- (level, stars, isCleared, isPlayable)
- int coin
-
데이터 흐름 클리어 상태는 LevelClearScene에서 변경함을 유의한다.
1. LevelSelectScene에서 레벨 1 버튼을 누름
2. ActiveLeveData(level, score=0)을 DataManager에 맡기고 Level1 Scene load.
3. Level1 Scene에서 LevelPlayInstance를 DataManager에서 받아오고 게임 플레이
4. 레벨 클리어시 ActiveLeveData에 score를 저장하고 DataManager에 맡기고 LevelClearScene load.
5. LevelClearScene는 DataManager에서 ActiveLeveData를 받아오고 score값을 이용해 star, coin 계산
6. LevelClearScene는 DataManager에서 해당 LevelData의 isCleared, stars를 받아오고 지급해야 하는 coin을 다시 계산
7. 필요하면 DataManager에 LevelData의 isCleared, stars 업데이트
8. 다시 플레이하기를 누르면 ActiveLeveData.level를 읽고 score를 0으로 초기화한 뒤 LevelScene 로드
9. 레벨 실패시 LevelOverScene으로 비슷하게 진행
- Singleton 패턴
- DataManager
- coin 정보, 레벨 정보가 구현됨.
- StageManager
- 게임의 상태 (플레이중, 게임 오버, 클리어 등)를 관리할 계획이나, 아직 게임 오버 기능만 구현됨.
- MVC 패턴
- Model : PlayerBag
- View : BatteryUI, ScoreUI
- Controller : PlayerBagController
- 쓰레기는 Model과 Controller 일부(줍기)가 구현됨.
- 쓰레기 관련 나머지 Contoller(버리기), View는 스프린트 3에서 구현 예정.
- 점수, 목숨(배터리)는 View가 구현됨.
- 점수, 목숨(배터리) 관련 Controller와 Model은 스프린트 3에서 구현 예정.
- 진척도는 카메라의 좌표를 직접 참조하여 별도의 MVC 없이 구현함.
- Strategy 패턴
- InputManager
- Player에
move()
함수가 있고, InputManager에서 input에 따라move()
함수를 호출하는 형태로 구현하여 추후 입력 방식 변경에 대응할 수 있음.
- Observer 패턴
- 게임 플레이 중 UI 엘리먼트가 상태 변경에 따라 실시간으로 변경될 수 있도록 Observer 패턴을 이용하여 구현할 계획.
디자인 패턴 선정 (8차 회의)
디자인 패턴 논의 회의
인게임 데이터
점수 : int : 모델에서 관리
쓰레기 버리면 증가
카메라 이동시 쓰레기가 화면 끝에 닿으면 감소
목숨 : int : 모델에서 관리
쓰레기 화면에 닿으면 감소
배터리팩 먹으면 증가
0이 되면 Game Over
진척도 : float (0 ~ 1) 카메라 불러와서 바로 계산
(카메라의 z좌표 - 카메라의 시작 z좌표) / (목적지의 z좌표 - 카메라의 시작 z좌표)
들고 있는 쓰레기 Queue
현재는 List of (TrashType, TrashSubtype)
List of (TrashSubtype)를 저장하고, 필요할때 Mapping[TrashSubType, TrashType]을 이용
Item 관련 로직을 Trash와 비슷한 구조로 구조화
- 인게임 데이터(들고있는 쓰레기, 목숨, 진척도, 점수)에 대해서는 MVC 패턴 사용하기로 결정하였음
- 들고있는 쓰레기
- Model: PlayerBag Script(Queue)
- Controller: PlayerBagController Script
- View: InventoryUI Script
-
InventoryUI.UpdateInventory()
를PlayerBag
에서 상태가 업데이트 될 때마다 호출
- 플레이어 목숨
- Model: PlayerBehaviour Script의 life(int)
- Controller: PlayerBehaviour Script의 IncreaseLife, DecreseLife
- View: BatteryUI Script
-
IncreaseLife
,DecreaseLife
에서BatteryUI.UpdateBattery()
직접 호출 -> 리팩터링을 통해 MVC 구조로 스프린트 4에서 변경 예정
- 게임 진척도
- Model: DistanceBarUI Script의 cameraProgress
- Controller: DistanceBarUI Script의 Update
- View: DistanceBarUI Script의 Update
- 진척도는 Camera의 현재 위치로부터 바로 계산할 수 있어 MVC 패턴을 이용하지 않고 DistanceBarUI 스크립트에서 바로 계산함
- 점수
- Model: ScoreModel Script
private float startTime;
private float startZ;
private float referenceSpeed;
private int trashDisposeCount;
private int trashMissCount;
private int trashPickupCount;
- Controller: ScoreModel Script의 UpdateScore, CalculateFinalScore, IncTrashPickupCount 등
- View: ScoreUI Script
-
PlayerBehaviour.Update
->ScoreModel.UpdateScore(transform.position.z)
->ScoreUI.UpdateScore
순으로 실행 - Model과 Controller를 분리할 필요성을 느끼지 못해 통합함
- PlayerBehaviour의 개입 없이 자동으로 Score가 업데이트가 되는 방법도 스프린트 4에서 고려 예정
- 이번 프로젝트에서 배터리팩 아이템 1개만 구현할 계획이지만, 확장성을 고려하여 임의의 "아이템"을 구현할 수 있는 구조로 설계함
- ItemSpawner, ItemType 과 같이 Trash에서 사용한 것과 동일한 구조로 설계함
- Trash와 Item에서 중복되는 로직이 있는데 OOP와 Generic을 이용해 구조화가 더 가능할 것으로 예상
- 플레이어가 목적지에 도착했는지 여부를 확인하기 위해
goalZ
라는 float 좌표값을 저장해야 했음 - 기존의 StageManager는 게임 전체에 걸쳐 Singleton이라, 초기에는 좌표 3개를 저장해서 Level별로 리턴하는 방식으로 구현
private List<float> goalZList = new List<float>() { 24.5f, 24.5f, 24.5f };
public float GetGoalZ()
{
int level = DataManager.Instance.GetActiveLevelData().level;
return goalZList[level-1];
}
- StageManager는 각 Scene별로 하나만 있는 것이 적절하다고 생각해, 각 Scene별로 StageManager가 다시 생성되도록 하고,
[SerializeField] goalZ
를 1개 두어 각 Scene의 Unity Editor에서 goal 좌표를 수정할 수 있도록 변경
[SerializeField] private float goalZ;
public float GetGoalZ()
{
return goalZ;
}
- InputManager의 확장 가능한 디자인 덕에, 조작키를 쉽게 변경할 수 있었음. #148
(변경 전)
// Player movement
if (Input.GetKey(playerLeftKey))
{
player.Move(Direction.Left);
}
if (Input.GetKey(playerRightKey))
{
player.Move(Direction.Right);
}
if (Input.GetKey(playerFrontKey))
{
player.Move(Direction.Front);
}
if (Input.GetKey(playerBackKey))
{
player.Move(Direction.Back);
}
(변경 후)
// Player movement
if (Input.GetKey(playerLeftKey) || Input.GetKey(KeyCode.LeftArrow))
{
player.Move(Direction.Left);
}
if (Input.GetKey(playerRightKey) || Input.GetKey(KeyCode.RightArrow))
{
player.Move(Direction.Right);
}
if (Input.GetKey(playerFrontKey) || Input.GetKey(KeyCode.UpArrow))
{
player.Move(Direction.Front);
}
if (Input.GetKey(playerBackKey) || Input.GetKey(KeyCode.DownArrow))
{
player.Move(Direction.Back);
}
- 입력을 처리하는 모든 로직을
InputManager
에 모아놓았기 때문에 한 파일만 수정해서 동작을 쉽게 변경할 수 있었음.
- TrashPicker에서 쓰레기를 줍는 것을 전담해서 처리했기 때문에, 큐가 꽉찼을 때 소리를 내고 화면을 흔드는 효과를 쉽게 구현할 수 있었음. #154
(변경 후)
var markerPos = _trashTilemap.WorldToCell(transform.position);
bool alert = markerPos != lastVisitedPos;
lastVisitedPos = markerPos;
if (!CheckIfTrashExists(markerPos)) return;
if (CheckIfBagIsFull())
{
if (alert)
{
AudioManager.Instance.PlaySFX("MotionFail");
GameObject.Find("InventoryBackground").GetComponent<UIShake>().Shake(0.25f, 5f);
}
return;
}
- 리팩터링을 통해 쓰레기 Mapping에 대한 정보를
TrashMappingItem
Asset 하나에 의존하게 바꿀 수 있었음. - 지자체에 따른 분리수거 규칙 차이를 반영할 때 "TrashMappingItem` Asset 하나만 수정하거나, 여러 버전을 만들어 갈아끼울 수 있음
(변경 전)
public static string TrashColor(TrashType trashType)
{
switch (trashType)
{
case TrashType.PaperGrouped: return "Yellow";
case TrashType.PaperSingle1: return "Yellow";
case TrashType.PaperSingle2: return "Yellow";
case TrashType.CanHorizontal: return "Red";
case TrashType.CanVertical: return "Red";
case TrashType.PetBottleHorizontal: return "Blue";
case TrashType.PetBottleVertical: return "Blue";
case TrashType.Banana: return "Green";
}
return "";
}
(변경 후)
public string TrashColor(TrashType type)
{
if (type == TrashType.None) return "";
foreach (var item in items)
if (item.MatchObject(type)) return item.markerTile.name.Replace("TrashMarker", "");
throw new System.InvalidOperationException("No mapping found for " + type);
}
- Unity Test Framework와 game-ci의 Github Action을 이용해서 CI를 구축함. #90
- asmdef를 작성하는 과정에서 많은 버그와 문제를 마주했으나, 결국 CI를 deploy함 #99
- 핵심적인 로직인
PlayerBag
에 대한 Test를 작성함
- 리팩터링 전후의 동일성 보장을 위해 Unit Test를 작성하여 성공함을 확인하였음.
- Persistent Storage 테스트 #60
- 게임 처음 실행시 초기화 상태임을 확인 (보유하는 코인 0개, 완주한 레벨 없음).
- 레벨 1 클리어 후 게임 재실행시 레벨 클리어 내역 및 득탬한 코인과 별 개수 정보 모두 유지함을 확인.
- 레벨 2 클리어 후 동일한 형식으로 테스트 진행함.
- 처음 테스트 진행했을 때는 레벨 선택화면에서 레벨 1 화면으로 넘어가는 StageManager가 연결되지 않아 테스트 진행이 불가하였으나, 해당 이슈 해결 후 테스트 성공함.
- 게임 클리어 테스트 #72
- 플레이어를 이동시켜 목적지까지 이동 시 Level Clear 화면으로 전환되며 확득한 코인 및 별을 보여줌을 확인.
- 플레이가 카메라 하단선에 닿아 Respawn되어 목적지에 도달했을 경우 같은 결과임을 확인함.
- 처음 테스트 진행했을 때 플레이어가 목적지 선에 도달했을 때 StageManager가 GameClearScene으로 전환시키는 기능이 구현되지 않아 실패하였으나, 해당 이슈 해결 후 테스트 성공함.
- 게임 실패 테스트 #73
- 플레이어가 줍지 않은 쓰레기가 전진하는 카메라 하단선에 닿았을 때 목숨이 하나 감소해야함. 해당 기능은 첫 테스트에 실패함.
- 플레이어가 쓰레기를 주운 위치가 카메라가 지나갈 때 목숨이 감소하거나 증가하지 않아야함. 이는 쓰레기 오브젝이 주웠을 때 해당 좌표에는 쓰레기가 더이상 존재하지 않다는 것을 확인하기 위함. 해당 테스트는 위 테스트에 의존성이 있기에 해결 후 제테스팅 진행함.
- 플레이어 자체도 카메라 선에 닿으면 Respawn이 되며 목숨이 하나 감소해야하고 목숨 3개 모두 잃는 즉시 Game Over임을 테스트함. 해당 테스트들은 첫 테스트에 통과함.
- 쓰레기가 카메라 하단선에 닿았을 때 목숨이 감소하는 기능을 구현 후 테스트 성공함.
Edge Case보다는 당연히 만족해야 할 일을 테스트로 작성하였는데, 기능들이 모두 통합되지 않아 생각보다 실패하는 테스트가 많았음. 스프린트 마지막에 모든 기능 통합 및 테스트에서 발견한 버그 수정 후 모든 테스트를 통과함. 테스트를 실패하고 놓쳤던 부분을 구현하면서 테스트의 유용성을 확인할 수 있었음.
- 이하 모든 테스트와 QA는 12/11 Version 1.2.0 배포 후 배포된 버전에 대해 실습시간 중 PP로 진행하였음.
- Unity 환경에서 제대로 작동하더라도 WebGL 배포에서는 작동하지 않을 수 있는 점을 고려해 배포된 버전에서 테스트 및 QA를 진행함.
- UI에서는 기본적인 Navigation은 플레이해보면 당연히 가능하다는 것을 확인할 수 있어, 버튼이나 배경에 어색한 부분이 없는지 QA 위주로 진행함.
- 인게임에서는 수동 테스트 목록을 만들어 테스팅을 하고, 추가적으로 어색한 부분이 없는지 QA를 진행함.
- 수동 테스팅 #128 (comment)
- 대부분의 테스트 Success
- 목숨이 모두 깎이면서 플레이어가 finish line으로 이동하는 경우에 Fail이 아니라 Clear가 되는 오류 발견 후 해결 #139
- QA #128 (comment)
- Effect와 관련해서는 "효과가 적절한 타이밍에 재생된다"와 같이 테스크가 모호할 것으로 예상해, 직접 플레이해 보면서 어색한 부분이 없는지 확인하는 QA 형태로 진행했고, 아래 기능이 부족하다고 판단함.
쓰레기 관련 클래스에는
TrashType
, TrashInfo
, TrashMapping
, TrashMappingItem
, TrashPicker
, PlayerBag
, PlayerBagController
, PlayerBehaviour
가 있음.
우선 PlayerBag
, PlayerBagController
, StageManager
에서 양방향 dependency를 발견함
-
field: 점선
-
Property, function: 실선
-
PlayerBag
,PlayerBagController
,StageManager
가 모두 1개만 생성되는데 StageManager만 Singleton으로 구현되어 있어 모두StageManager
를 참조한 후에Controller
를 타고 오는 구조였음. -
PlayerBag
과PlayerBagController
의 역할이 명확하게 분리되어 있지 않음
-
Trash
의 분류를 알려주는 static 함수TrashColor()
와 Trash의 충돌을 handling하는OnTriggerEnter
가 같은 Script 내에 있어서 양방향 참조 중이었음. -
Trash
의 분류를 알려주는 함수를 분리 -
OnTriggerEnter
부분은TrashBehaviour
라는 이름의 class로 분리
-
PlayerBag
,PlayerBagController
,StageManager
-
PlayerBag
은 테스트가 이미 있음 -
PlayerBagController
에 대해 테스트 똑같이 구현 df09a0b
-
-
TrashInfo
,PlayerBehaviour
-
TrashColor
에 대한 테스트 구현 6097406 - 쓰레기 충돌에 대한 테스트는 수동 테스팅(QA)로 위임
-
Refactoring #123
-
StageManager
->PlayerBagController
->PlayerBag
989bac7
- 쓰레기 충돌 관련 로직
TrashBehaviour
로 분리 - 쓰레기 종류 (TrashColor) 관련 로직을 TrashMapping으로 통합 6097406 등
- 리팩터링 이후 Unit 테스트를 통과하여, 기능이 같음을 확인하였음.
- 쓰레기 관련 파일의 이동으로 인해 수동 테스팅이 실패하는 것을 확인해, 오류를 수정하였음. #124
- 재미있고 완성도 있는 게임을 계획대로 만드는 데 성공했습니다.
- 프로젝트 계획 단계에서 고민했던 게임의 "의미"(환경, 분리수거 학습)에 대해 더 고민이 필요할 것 같습니다.
- 이상규(PM)
- 프로젝트 관리의 어려움을 체감했습니다. 모든 PM을 respect합니다.
- 어려운 점도 많았지만 대체로 계획대로 잘 흘러갔는데, 좋은 팀원이 있었던 덕분인 것 같습니다. 모두 앞으로도 좋은 일 가득하길 기원합니다.
- SW Engineering을 입문하기 좋은 강의였습니다.
- 이선재
- 단순해 보이는 게임도 무시하지 않겠습니다. 소중한 경험이었습니다!
- 기말기간에 모두 힘내주셔서 잘 끝낼 수 있었다고 생각합니다!! 특히 상규님께서 저희 팀 이끌어주셔서 너무 감사하고 수고 많으셨습니다!
- 김준원
- 한 학기 고생하셨습니다 ^o^
- 이정민
- 한 학기 동안 정말 많은것을 배울 수 있었습니다. 모두 고생하셨습니다!
- 이런 단체 프로젝트 경험이 처음이라서 어색한 점도 많고 걱정도 많았는데, 다들 잘해주셔서 한 학기동안 재미있게 게임을 만들면서 많은 것들을 배웠던것 같습니다. 저한테 정말 소중한 경험이 될 것 같습니다. 모두 정말 고생 많으셨습니다!
- 김동욱
- 생각보다 모르는 거 많이 배워갈 수 있는 시간이었습니다. 모두들 고생하셨습니다!
- 솔직히 이런 단체 프로젝트 참여해보는 게 처음이었던 분도 있었을 것 같은데, 모두가 각자 힘내서 이 정도의 결과물을 만든 게 저로서도 신선한 경험이었지 않나 싶어요. 아무튼 다들 이번 학기 정말 수고 많으셨습니다.
- Home
- Schedule
- 회의록
- 스프린트
- 스프린트 2
- 스프린트 3
- 스프린트 4
- 최초 프로젝트 제안서
- 최종 프로젝트 제안서
- 최종 프로젝트 보고서