Home CK 하늘섬 (1학기) 개발일지
Post
Cancel

CK 하늘섬 (1학기) 개발일지

해당글은 2022년 6월 19일날 최종 수정된 글이며, 2024년 1월 5일에 github.io로 이주하며 수정을 거치지 않은 글입니다.

하늘섬의 최종버전과는 많이 다르며, 작업했던 모든일이 기술되어 있지 않습니다.

틀린내용, 사담, 단체가 아닌 개인의 의견이 다수 포함되어 있을 수 있습니다.

재미로 읽어주세요.

감사합니다.

(제발 작성할 때 katex를 안썼길 바라며…)


서론


하... 하…

※주차 내부에 적힌 작업은 연속성을 보장할 수 없음

※30분 이내에 처리된 문제해결도움 및 기타 처리는 작성하지 않음

※바쁠땐 기록을 대충함

1주차(3월 1일~)


게임서버 및 클라이언트 구조 작성 및 설계 (1)


기존에는 이동까지 구현되었는데, 이후 클라이언트와 서버의 동기화를 작업하며

무기 줍기 및 물리 동기화를 구현함. 다만 작업자 병목 발생

프로토콜에 대해서도 다시 작성. 구조 처리

게임서버 및 클라이언트 구조 (2)


문제가 많음. 설계를 안들어가고 작성을 하다보니 클래스는 많아지고 역할은 파편화되며, 데이터는 일관성 없고 흐름은 읽기 어려워짐. 작업능률이 떨어져서, 작업자를 실제로 불러 같은 공간에서 페어 프로그래밍.

이후 작업자 추가 투입시 발생하는 설계공유 과정에서 많은 애로사항이 있을 것으로 고려됨과 동시에, 추후 개발 복잡성이 늘어남을 염두하고 재설계의 필요성을 느낌.

익일, 실제 작업자의 문제 발생. 문제가 심각해지기 시작해서 확실하게 재설계 시작

게임서버 및 클라이언트 구조 설계 (3)


또다시 회의. 구조 설계. 클라이언트 프로토타입(객체간 동작 플로우 설명용)을 버리는 쪽으로 선택.

실제 오프라인 회의를 진행하며 화이트보드와 오프라인 문서에 정리

Untitled

이후 알로에서 작업자와 실제 작업용 구조 설계 시작(그리고 수많은 수정)

Untitled

Untitled

Untitled

Untitled

Untitled

게임서버 및 클라이언트 구조 구현(4)


Untitled

변경된 설계

기존 이상하던 시스템에서 깔끔하게 구조를 정리

Untitled

작업중 약식으로 대강 구현해둔 구조 리팩토링도 진행

Untitled

Untitled

등등.

구현하다 보니 모든 entity 순회로직이 많아, 타입별로 분리를 진행.

Untitled

작업만하면 재미 없으니까 재미있는 코드를 작성

테스트를 약식으로 진행하여, 작업자에게 테스트 요청.

애니메이션 관련하여 문제 발생. 마스킹이 제대로 되어있지 않음.

2022-03-07 이동 및 무기줍기 동기화.gif

수정.

refactoringTest2.gif

서버 연결, 바인딩, 무기줍기, 이동, 애니메이션 테스트 완료

게임서버 및 클라이언트 구조 설계(5)


따라서 이제 무기를 발사하고, 공격이 어떻게 실행되어 어떤식으로 동기화 되어야 하는지 작업이 필요.

Untitled

따라서 공격타입에 따라 Projectile, Hitscan, Logical로 분리 후 알아서 각자 구현하는 것으로 설정.

프로그래밍 마일스톤 및 개발방향 설정


추가 영입된 클라이언트 프로그래머와, 백엔드 개발의 우선순위사항에 변동 발생.

아트팀에서 요청한 관성 애니메이션 사항에 대해,

Boing Bone을 레퍼런스로 추가 영입된 클라이언트 분에게 설명 및 R&D 자료 전달.

잡무


리소스 적용, 작업내용 확인, 투사체 시스템 회의, 새로운 기획자분 영입을 위한 면담, 프로젝트 설정 및 권한 적용, 애니메이션 레퍼런스 조사, 깃 및 소스트리 설치 가이드, 3월8일 발표 문서 회의.. 그런 것들

커밋로그


Untitled

차주 목표


투사체를 발사 - 피격 - 사망 - 부활에 관한 설계 및 구현

2주차(3월8일~)


리팩토링 및 개인공부


Notifier

Notifier에 대해 요청도 있고 네이밍이나 중복코드에 대한 문제점이 발견됨.

어짜피 오늘(3월9일)은 좀 쉬려했던 것도 있어서 해당 클래스 분해 및 리팩토링을 진행

**EqualityComparer.Default**** 부분을 통해 전체적으로 구성하고,

추가로 override하여 comparer할 수 있게 구성. 중복코드 제거.

사용하지 않는 일부 변수가 있어 그냥 제거.

Mono Notifier Event Riser

매 유니티 업데이트마다 최종변경사항을 call해달라는 요청에 따라

Mono에서 동작하는 이벤트 라이저를 작성

진행하다보니 까먹은게 있어서 좀 뒤적뒤적

유니티 2018부터 PlayerLoop라고 추가된게 있다.

어짜피 지식은 머릿속에 있으니 분류와 순서만 대충 메모

뎁스 R&D


커비 디스커버리를 보면 오브젝트에 커비가 가릴 때,

뎁스값이 great인 대상을 override한 머테리얼 을 적용하여 실루엣을 그리고 있다.

Untitled

그래서 음.. 그냥 하면 되는거 아닌가? 했더니

Untitled

어림도없다.

일단 override 한 머테리얼에 대해 연결된 부위가 두번 그려지고있다.

그러면 이걸 어떻게 처리할 것인가. 뎁스를 한번 더 검사하나?

답은 『스텐실』이다.

Untitled

그렇게 작업을 했더니 반만 정상적으로 작동한다.

그렇다. 자기자신과의 뎁스 비교를 통해 스스로를 다시 그리고 있다!!

그렇다면 어떻게 해야하는가.

어? 그러면 남는부분 (less 부분)만 다시 그리면 되는거 아님?

Untitled

ㅇㅇ 아님.

자 이제 잘 생각을 해보자..

왜 이미 override된 머테리얼이 그린 영역 내의 뎁스가 더 높은 지역만 다시 그리고 있을까?

이유는 간단하다.

Untitled

뎁스를 다시 작성하고 있기 때문이다.

그러면 이제 원래 그리던 것 처럼 깊이검사를 모두 수행하고,

어딘가에 가려진(뎁스값이 높은) 대상에 대해 오버라이드 된 머테리얼을 그리고,

가려지지 않은(뎁스값이 낮거나 같은) 대상에 대해 다시 원본 머테리얼을 그린다.

뎁스값은 다시쓰지 않는다.

그럼 짜잔

Untitled

Untitled

완성.잘 작동함을 알 수 있다.

silhouette2.gif

레거시 코드 정리


remove.gif

^^

보잉 보완(포지션 적용)


기존 구현된 보잉에서, 회전만 적용되어 늘어나는 느낌을 추가적으로 주고 싶었다.

따라서 해당부분에 대해 조금 천천히 따라와, 늘어나는 느낌을 구현.

Untitled

Untitled

구현본 구현본

적용된 귀(기즈모o)와 안된 귀(기즈모x) 적용된 귀(기즈모o)와 안된 귀(기즈모x)

보완해야할 부분은 있지만…

초기 R&D단계에서 이정도 시각화면 괜찮다고 생각.

추후 다시 작업자에게 재할당하여 제대로된 수학식과 함께 구현 예정

클라이언트 사이드 구현


서버에서 전송한 액션(약한 강제성 이벤트) 처리와

클라이언트에서 별개로 진행하는 충돌시 처리 (공통 로직의 다형성 구현)

그리고 클라이언트에서 사용할 데이터가 추가로 필요.

따라서 피격(검출)에 대한 데이터 구조를 수정.

Untitled

사망 액션, 부활, 피격 이펙트등에 대한 처리완료

이펙트는 더미 개발리소스입니다 이펙트는 더미 개발리소스입니다

나무와 이펙트는 더미 개발 리소스입니다 나무와 이펙트는 더미 개발 리소스입니다

커밋로그


Untitled

차주목표


개발 테스트용이 아닌 실제 게임 제작 시작

인게임 UI 리스트업

카메라 R&D 1차 (레퍼런스 : 커비 디스커버리)

스테이지 2 제작 (폴리 브러시)

다른 공격방식의 무기 1종,

3월21일 팀 내 1차적 접속 및 플레이 가능하도록

3주차(3월15일~)


저번주차는 대부분 서버쪽 구현에 대한 작업이라,

이번주부터는 클라이언트에 대해 작업을 진행하고자 한다.

목표 : 3월21일 팀 내 1차적 접속 및 플레이 가능하도록

인게임 UI 리스트업(협업 - 윤관)

카메라 R&D 1차 (레퍼런스 : 커비 디스커버리)

스테이지 2 제작 (폴리 브러시)

다른 공격방식의 무기 1종(협업 - 최지욱)

카메라 R&D


카메라 R&D

시발점

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
커비 - 디스커버리를 보면 고정형 카메라인데 추가조작을 통해 약간의 각도 돌릴 수 있어, 

생각보다 덜 답답한 시야를 주는 부분이 있었다.

하지만 우리게임은 그런 추가 키를 바인딩할 여건은 안되고(조작키를 더 늘리고 싶지 않다)

‘알아서 적당히’ 캐릭터쪽으로 볼려고 노력하는, 시야제한을 조금 풀어주는 방법으로 접근해 보고 싶었다.

어짜피 구현은 머릿속으론 끝났고, 몇시간 뚝딱대면 정리도 끝날테니 강의실에서 작업 착수.

(그리고 집와서 원육 손질하다가 체력 다써서 잠들었다)

---

그리고 작성자는 카메라를 주말까지 잡게 되는데...

기본적인 개념은 카메라의 부모는 플레이어들의 무게중심을 바라보고,

카메라는 어느정도까지 플레이어를 쳐다본다.

그러나 기존에 만들어둔 줌과 포커싱PP적용들 때문에 내부식이 난잡하게 구성되어 있었다.

이때도 R&D명목으로 대충 짰던것 같다.

그래서 단어명칭을 통일하고, 각 컴포넌트에서 해야할 작업을 명확히 한 후 다시 작업을 하였다.

cameraFollow 컴포넌트에서 root와 LookAtOffset, mainCamera를 사용하고

Focus는 AutoFocus에서 사용하고,

Zoom에서 LookAtOffset의 갱신을 호출한다.

Untitled

사실 이제 lookAt을 캐릭터의 nect정도로 두게 된다면 head bobbing도 구현되지 않는가? 싶지만

실제 넣어보니 꽤나 흔들려서 제외

(보간처리해서 부드럽게 해볼까? 하지만 neck을 가져오는 구조가 더럽고, 귀찮다 *하기로 함)

그 이후 간단하게 거리 최대치두고, 관련해서 사망, 부활시, 연결, 바인딩에 따른 캐릭터 무게중심 계산해주는 서포터(프리팹의 의존성 약화를 꾀했다)를 작성하고 끝!

cameraMovement.gif

일단 임시로 이렇게 구성한 다음, 더미빌드에서 플레이를 확인하고 수정해야겠다.

캐릭터 적용 및 보잉 적용


캐릭터 적용 및 보잉 적용

브랜치 병합을 하며 그냥 적용해봄

rotation.gif

boingModelClient.gif

그냥… 함….

카메라 R&D 2차


요구사항:

보간처리해서 부드럽게.

neck을 바라봐서 이동할때 카메라가 약간씩 흔들리게 되어야함.


뷰가 살짝 바뀌었는데, FOV가 변경되어 (최대 축소 기준 10→45)

무언가 더 들어가면 더 재미있을 것 같았다.

카메라 버그수정 (ㅋ.ㅋ)

neck을 바라볼 수 있도록 replicated entity placeholder라는 구조 정의

관련하여 readonly 설정을 위한 r&d(대 실패)

아무튼 구현 아무튼 구현

줌레벨과 기타 포스트프로세싱 자동화 변수 수정이 필요

(끄덕끄덕) (끄덕끄덕)

구현1차. 구현1차.

보간과 보간, 그리고 부드러우면서도 부드럽게.

카메라 R&D 3차

여러플레이어가 있을때 카메라 줌 및 해제 구현

왼쪽아래 플레이어있음. 근데 뭔가 이상한듯. 나중에 수정해야지 왼쪽아래 플레이어있음. 근데 뭔가 이상한듯. 나중에 수정해야지

이동방식 카메라 공간으로 전환 테스트 (사유 : 다인플레이시 카메라 위치로 인한 비 - 직관적 이동)

(카메라고정 - d키만 누름) (카메라고정 - d키만 누름)

카메라 카메라 그리고 카메라 카메라 카메라 그리고 카메라

TODO : 달리기 애니메이션 적용 및 이펙트 적용


본 계층 구조 및 애니메이션 이슈에 의해 새로운 컨트롤러,마스킹,기타 작업 필요.

3월4주차 까지 신규 모델링 기준 애니메이션 리소스가 어느정도 나올지 알 수 없어,

후순위 작업으로 일정 지연

skinned mesh 대상 본 수정용 에디터 코드


익숙한 그것 익숙한 그것

bone Update Test.gif

신규 리소스에 적용되는 메시인 hair가,

적용 이후 레거시 fbx 본에서 정상 작동함을 확인

이펙트적용


매니저도 만들어야하고 리소스 나온거 파악도 해야하고 해야할게 산더미..

  • 설정 - 풀링

    일단 이펙트가 자동으로 풀에 들어갈 수 있도록 코드를 작성해줘야한다.

    대충 요로코롬하게

    Untitled


  • 설정 - 애니메이션 연동

    Untitled

    이펙트를 animation 이벤트에서 자동으로 처리할 수 있도록 몇가지 옵션을 설정

    사유 : 생산성(귀찮음)

이동 이펙트 적용하기

  • 이동

    사실 이거 말은 쉽지 생각보다 생각해야한다.

    플레이어가 어느정도 역치를 갖고 걸을 때 마다 이펙트를 생성해줘야한다.

    일단 더미에 맞게

    Untitled

    한 발이 최종적으로 공중에 뜰 때, 이펙트가 발생할 수 있도록 키를 설정하고, 이펙트를 설정해서 처리한다.

    Effect.gif

  • 부활

    Untitled

    riv.gif

  • 프로젝타일 폭발

    projectileExplosion.gif

결과물


슈팅테스트 (버그남) 슈팅테스트 (버그남)

2인플레이 카메라? 2인플레이 카메라?

아수라장. 난잡하고 역동적인 느낌이 카메라를 통해 잘 나타날 수 있었으면 좋겠다 무기버그는 8681d65에 잡음 ㅎ;;; 아수라장. 난잡하고 역동적인 느낌이 카메라를 통해 잘 나타날 수 있었으면 좋겠다 무기버그는 8681d65에 잡음 ㅎ;;;

이번주 작업물이 생각보다 적어서 일정이 지연될 수 있다는 느낌을 받음

키보드 AS 이슈로 하루 왕복 650km를 이동하고,

비맞으면서 다녔더니 감기에 걸려서 그만큼 작업이 안된듯.

커밋로그


Untitled

차주목표


쉐이더 R&D (구름 그림자)

스테이지 2 제작 (폴리 브러시)

몬스터 구현

데모 플레이 빌드

4주차(3월22일~)


해당주차는 코로나 바이러스로 인해 죽어가서, 작업량이 적습니다.

체력바 UI


Untitled

Untitled

hp.gif

1번 채택

폰트추가테스트 해달라해서 작업.

font3.gif

반짝반짝~ 반짝반짝~

Untitled

이뻐짐 이뻐짐(아마도)

근데 이것도 사실 좀 별로임. UI가 플레이어 애니와 상관없이 떠있다???

UItarget.gif

1차수정. 괜찮은 느낌인듯

프로젝타일 적용


projectile.gif

더미 레벨 약식 디자인


2스테이지의 핵심은 다리와 무덤.

무덤은 배경모델링을 통해 나타낼 수 있으니,

다리를 어떻게 잘 구성할 것인가가 중요하다고 생각.

큐브나 기본 도형으로 작업할까 하다가,

중간쯤 되어서 의도를 살리기 위해선 프로빌더가 필요하다고 판단,

프로빌더로 작업.

Untitled

이정도 거리면 대략 플레이어 속도 2 기준 2분정도 걸어야 할 것. (테스트 필요)

플레이어 배치 및 카메라를 보면서 작업

Untitled

다리 구성 변화

다리에 대해서 길게 하나로 구성한다면,

시각적 변화도 적고 조작방향도 단순해, 단조롭다는 느낌이 들 수 있다고 판단.

중간 중계섬을 추가하여 다른 이동 각도의 두개의 다리를 연결하여 구성함.

중계섬을 지나가는 동안 심심할 수 있으니 (^^)

원거리 공격을 할 수 있는 봇을 구성.

무기를 드랍하지만 드랍하는걸 먹을 수 없는 것 처럼 공간 단절

봇이 없으니 대충 터렛같은 원거리 공격 더미 봇 작업요청.

만약 무언가 처리를 해야한다면 ‘다리가 부셔진’ 봇이라고 하면 됨.

Untitled

젤다 야숨의 두가지 (이동/고정) 가디언 젤다 야숨의 두가지 (이동/고정) 가디언

오히려 봇을 안보여주기 위해서 중계섬 및 다리와의 거리를 약간 둬서

새로운 섬을 구성. 해당 섬은 찾아가서 무기를 주울 수 있도록 하지만

조금의 생각을 통해 돌아가야 발견할 수 있음.

Untitled

1번에 대한 배치사유 : 중계섬이 왜케 길쭉?

Untitled

진행을 하다보면 바로 다음 지역을 먼저 보여줘서,

탐색을 하고자 하는 플레이어만 추가 보상을 습득할 수 있도록 (우하단)

하지만 너무 단순하므로 드랍하는 무기는 매우 구림

2번에 대한 배치사유 : 왜 저곳은 파여있는가.

Untitled

이동할 수 없는 지역(단절된 지역)인 척 하기 위해

보이는 영역에서 끊기도록 처리

대충 렙디분에게 공유하고 끝

서버 구현 변경에 따른 클라이언트 구현 변경


부활시 - 정확히는 엔티티 생성시 오브젝트가 밀리는 현상 발생(버그)

녹화_2022_03_26_19_57_57_330.mp4

녹화_2022_03_26_20_04_21_652.mp4

이후 수정 후 서버구현변경에 따라 해당 수정부분을 필요없다고 판단, 수정

캐릭터ID 를 entityID로 변경하여 캐릭터를 선택하도록 변경

고정 오브젝트의 피격시 흔들림


커비에서의 오브젝트 흔들림 커비에서의 오브젝트 흔들림

로드리게스 회전을 통해 바닥 기준으로 살짝 흔들어 주면 될것으로 예측.

구조는 생각보다 복잡하지만, 식자체는 쉬우니

간단하게 구현

reactional tree.gif

Untitled

Untitled

결과물


프로젝트 소개 영상으로 대체합니다.

커밋로그


Untitled

차주목표


차주에는 추가개발보다는 내실 다지기에 들어갑니다.

실제 애니메이션 R&D 및 적용 (#33)

일부 그래픽적 표현 방법에 대한 R&D 진행

마일스톤 재설정 및 업무 재분담

업무 처리방식 변경안 작성

리팩토링

몹 구현

디버깅

5주차(3월29일~)


CCRC 작업환경 구성


청소하고, 셋팅하고, 다운하고 ..

회의하고 회의하고..

이펙트 테스트 환경 구성


effectTestScene2.gif

발사 - 투사체- 폭발의 테스트를 위해 이펙터쪽에서 테스트 할 수 있는 환경 요청.

런타임중에 인스펙터를 통해 뭐든 넣고, 뭐든 비우고, 속력,길이,반복에 대한 시각적 테스트를 할 수 있는 환경 구성.

사실 이정도 코드는 뚝-딱하면 나오죠 사실 이정도 코드는 뚝-딱하면 나오죠

실제 애니메이션 R&D 및 적용

#33


테스트구성


일단 서버까지 연결해서 테스트하는건 너무 이터레이션이 과하다고 생각,

다 뜯어버리고 휴리스틱-유닛테스트(농담)를 할 수 있는 구성작업

컨트롤러 구성


초기엔 상하체 나눔, 전체적용될 layer 하여

상체-하체-마스터 layer을 생각하고 작업.

문제 많음. 달리던 중에 무기를 쏘다가 멈추면 ???

다른 레이어가 다른 레이어의 상태에 의존하는 경우가 잦고, 블렌딩 문제가 자꾸 발생

그래서 난 미친 생각. 어 ? 하체만 override해서 layer weight로 블렌딩하면 안되나???

사망 이펙트 문제


Untitled

확인결과 skinnedMesh를 emit shape로 사용하고 있었음.

그러나 현재 범용적인 - 애니메이션이 이펙트를 생성하는 처리- 작업 시점에서 이를 알 수 없음

따라서 SkinnedMesh의 사망애니메이션 마지막 프레임에 해당하는 mesh를 구운 후,

해당 mesh를 fbx로 export처리하여 particle system의 shape를 mesh로 처리.

구워진 메쉬 구워진 메쉬

Untitled

실루엣상 유사성을 확인.

겸사겸사 위치좀 맞춰줌

dissolveConvertToMesh.gif

이제 다시 아티스트분에게 넘겨서 타이밍과 기타부분을 확답받으면 괜찮을 듯 합니다.

8방향 테스트 8방향 테스트

Input System


작업을 하다보니 LocalInput 재작업이 필요해졌다(#79)

컨트롤러 기준으로 작동할 수 있는 래핑된 구조 필요.MousePosition을 삭제하고 두가지 axis로 처리 필요.기존 인풋 설계였던 Base를 Local과 AI, Remote로 처리되던걸 이제 제거하며 레거시 LocalInput 제거 필요.

컨트롤러 및 키보드,마우스에서 작동 가능한 Input 혹은new InputSystem R&D 및 적용 테스트 필요

MousePosition은 최종적으로 사라져야할 데이터.

그러나 작업도중 CCRC와 집을 병행하다 브랜치 체크아웃중 작업사항을 청소해버리는 문제 발생.

레거시도 인풋바인딩이 생각보다 귀찮게 되어있었음(작업도중)

따라서 새로 input을 래핑하는 과정에서, 레거시를 사용하여 키보드와 마우스, 컨트롤러 여러대를 적용하기 어렵다 판단, new inputSystem을 R&D한다.

Fork Repository

Untitled

API 코드만으로는 R&D가 어렵다 판단, 신규 인풋 시스템을 포크하여 오가니제이션에 추가.

해당 포크된 리포를 기준으로 조사 시작

Untitled

이벤트단위로 바인딩

넣으면 알아서 unityEvent로 변환

Untitled

스키마는 Input에서 current를 사용하여 하나씩 가져오기.

Untitled

설정자체는 크게 다르지 않은데 TryGetFeatureUsage같은 형식으로 들고올 수는 없는듯?

하... 하…

현재 polling처럼 input.getKeyDown 을 검사하여 이벤트발생,

값은 notifier에 저장하고 있는데

이를 이제 new inputSystem에 맞춰 바꿔야함.

뭔소리? event base로 바꿔야한다고요.

설계해야함…

버튼은 일단 간단하게 down과 up을 받아야하는데,

value.started,

value.canceled로 판단하면 될듯.

이벤트가 중간에 하나 더 오는데 지금은 너무 귀찮으니 패스

그렇게 수정을하니 대공사.

일단 [System.Obsolete(“Not using. use Direction instead”, true)] 박아두고

나중에 처리예정.

인풋 리팩토링

여기는 중간과정을 정리하는게 더 문제라…

결론적으로 연결성을 약화하고, 모듈화하여 괴상한 참조를 하지 않도록 하는 작업중.


바인딩 구조 변경


데이터의 인풋 의존성 제거


인풋이 담당할 역할 변경 - 인풋의 바인딩 데이터 대상 의존성 분리


역할 변경에 따른 바인딩 데이터 대상 의존 상호작용 입력 처리부 추가


문제발생.

entity에 interactor가 붙고,

interactor에서 input에 의한 interaction을 관리하여 input형태로 취급되는데,

네트워크에 전송을 담당하는 모듈은 Rawinput과 Interactor을 모두 알고 있어야 하는 구조가 된다.

그런데 문제는 entity에 종속되기엔 entity는 부활하면 매번 생성과 사망이 되고, netModule에서

이를 관리하기 어렵다고 생각.

이 뒤로는 생각을 텍스트로 정리 안하고 막 작업함..

캐릭터에 관련된 정보가 필요한 interaction쪽 input과,

단순 키보드입력에 대응되는 PlayerInput을 나눠, 처리를 진행했다.

그런데 여기서 클로저가 생각나서 클로저테스트를 진행하였고,

클로저가 정상적으로 작동함을 확인하였지만 해제를 event remove 방식으로 할 수 없는 특성상,

(구조상 notifier에서 ‘직접’ invocation list를 검증하여 지우게 된다면

너무 많은 역할을 단순 객체가 하게된다.)

따라서 ‘캡처된 변수’를 들고 있을 수 있는 래핑된 클래스가 한번 핸들링하여,

이벤트를 라이징하는 container를 구성하고, 최종적으로 network module은 이 이벤트를 통해

‘함수 인자로 넘어온 데이터’만 가지고 모든 동작을 수행한다.

싱글턴이나 container 하위의 객체에 접근하기 때문에 Principle of least knowledge, 디미터의 법칙을 조금 위배하며, 약간의 의존성을 띄고있는 부분도 존재하지만,

현재단계에선 변경가능성을 이유로 이정도로 처리될 예정이다.

아직도 불편한 부분이 보인다. 아직도 불편한 부분이 보인다.

아무튼 일단 컨트롤러 및 키보드 조작(버그포함) 연결은 됨

결과물


Untitled

이걸 어떻게 보여드릴 수도 없고 하 참

대충 인풋쪽은 이렇게 감쌈.

RawInput

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using Utils;

public class BasePlayerInput : MonoBehaviour
{
    //Player ID
    public int PlayerID { get; private set; }

    [field: SerializeField]
    public PlayerInput playerInput { get; private set; }

    //Action Maps
    private const string actionMapPlayerControls = "Player Controls";
    private const string actionMapMenuControls = "Menu Controls";

    //Current Control Scheme
    private string currentControlScheme;

    //Get Data ----
    public InputActionAsset ActionAsset { get => playerInput.actions; }

    public void Initialize(in int id)
    {
        PlayerID = id;
        currentControlScheme = playerInput.currentControlScheme;
    }

    //INPUT SYSTEM ACTION METHODS --------------

    //This is called from PlayerInput; when a joystick or arrow keys has been pushed.
    //It stores the input Vector as a Vector3 to then be used by the smoothing function.
    public virtual void OnMovement(InputAction.CallbackContext value)
    {
    }

    public virtual void OnView(InputAction.CallbackContext value)
    {
    }

    //This is called from PlayerInput, when a button has been pushed, that corresponds with the 'Attack' action
    public virtual void OnAttack(InputAction.CallbackContext value)
    {
    }

    public virtual void OnRevive(InputAction.CallbackContext value)
    {
    }

    public virtual void OnInteraction(InputAction.CallbackContext value)
    {
    }

    //This is called from Player Input, when a button has been pushed, that correspons with the 'TogglePause' action
    public virtual void OnTogglePause(InputAction.CallbackContext value)
    {
    }

    //INPUT SYSTEM AUTOMATIC CALLBACKS --------------

    //This is automatically called from PlayerInput, when the input device has changed
    //(IE: Keyboard -> Xbox Controller)
    public virtual void OnControlsChanged()
    {
        if (playerInput.currentControlScheme != currentControlScheme)
        {
            currentControlScheme = playerInput.currentControlScheme;

            //UpdatePlayerVisuals();
            RemoveAllBindingOverrides();
        }
    }

    //This is automatically called from PlayerInput, when the input device has been disconnected and can not be identified
    //IE: Device unplugged or has run out of batteries
    public void OnDeviceLost()
    {
        //SetDisconnectedDeviceVisuals();
    }

    public void OnDeviceRegained()
    {
        StartCoroutine(WaitForDeviceToBeRegained());
    }

    IEnumerator WaitForDeviceToBeRegained()
    {
        yield return new WaitForSeconds(0.1f);
        //UpdatePlayerVisuals();
    }

    public void SetInputActiveState(bool gameIsPaused)
    {
        switch (gameIsPaused)
        {
            case true:
                playerInput.DeactivateInput();
                break;

            case false:
                playerInput.ActivateInput();
                break;
        }
    }

    void RemoveAllBindingOverrides()
    {
        InputActionRebindingExtensions.RemoveAllBindingOverrides(playerInput.currentActionMap);
    }

    //Switching Action Maps ----
    public void EnableGameplayControls()
    {
        playerInput.SwitchCurrentActionMap(actionMapPlayerControls);
    }

    public void EnablePauseMenuControls()
    {
        playerInput.SwitchCurrentActionMap(actionMapMenuControls);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class HumanoidPlayerInput : BasePlayerInput
{
    public readonly Notifier<Vector2> RawMovement = new();
    public readonly Notifier<Vector2> CameraSpaceMovement = new();
    public readonly Notifier<Vector2> View = new();
    public readonly Notifier<bool> Attack = new();
    public readonly Notifier<bool> Interaction = new();
    public readonly Notifier<bool> Revive = new();

    private void Awake()
    {
        ClientNetworkService.OnConnected += ClientNetworkService_OnConnected;
    }

    private void ClientNetworkService_OnConnected(int ClientID)
    {
        ClientNetworkService.OnConnected -= ClientNetworkService_OnConnected;

        Initialize(ClientID);
        PlayerInputNetworkManager.Instance.BindInput(ClientID, this);
    }

    //Override Input
    public override void OnMovement(InputAction.CallbackContext value)
    {
        RawMovement.Value = value.ReadValue<Vector2>();
        CameraSpaceMovement.Value = Camera.main.transform.TransformDirection(RawMovement.Value.ToVector3FromXZ());
    }

    public override void OnView(InputAction.CallbackContext value)
    {
        View.Value = value.ReadValue<Vector2>();
    }

    //This is called from PlayerInput, when a button has been pushed, that corresponds with the 'Attack' action
    public override void OnAttack(InputAction.CallbackContext value)
    {
        if (value.started)
            Attack.Value = true;
        if (value.canceled)
            Attack.Value = false;
    }

    public override void OnRevive(InputAction.CallbackContext value)
    {
        if (value.started)
            Revive.Value = true;
        if (value.canceled)
            Revive.Value = false;
    }

    public override void OnInteraction(InputAction.CallbackContext value)
    {
        if (value.started)
            Interaction.Value = true;
        if (value.canceled)
            Interaction.Value = false;
    }

    private void OnDestroy()
    {

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class InputContainer
{
    public HumanoidPlayerInput Input { get; private set; }
    public ReplicatedHumanoidEntityInteractor Interactor { get; private set; }

    public event Action<InputContainer, bool> OnAttack;
    public event Action<InputContainer, bool> OnRevive;
    public event Action<InputContainer, ReplicatedWeaponEntityData> OnWeaponSelected;

    public void BindInput(in HumanoidPlayerInput input)
    {
        if(Input != null)
        {
            Input.Attack.OnDataChanged -= Attack_Raiser;
            Input.Revive.OnDataChanged -= Revive_Raiser;
        }

        Input = input;
        Input.Attack.OnDataChanged += Attack_Raiser;
        Input.Revive.OnDataChanged += Revive_Raiser;
    }

    public bool BindInteractor(in ReplicatedHumanoidEntityInteractor interactor)
    {
        bool changed = EqualityComparer<ReplicatedHumanoidEntityInteractor>.Default.Equals(Interactor, interactor);

        if (Interactor != null)
            Interactor.OnWeaponSelected -= Interactor_Raiser;
        
        Interactor = interactor;

        if (Interactor != null)
            Interactor.OnWeaponSelected += Interactor_Raiser;

        return changed;
    }

    //raising Events

    private void Revive_Raiser(bool obj) => OnRevive?.Invoke(this, obj);

    private void Attack_Raiser(bool obj) => OnAttack?.Invoke(this, obj);

    private void Interactor_Raiser(ReplicatedWeaponEntityData obj) => OnWeaponSelected?.Invoke(this, obj);

    public void ReleaseInteractor()
    {
        if (Interactor != null)
            Interactor.OnWeaponSelected -= Interactor_Raiser;

        Interactor = null;
    }

    public void ReleaseEvent()
    {
        if (Input != null)
        {
            Input.Attack.OnDataChanged -= Attack_Raiser;
            Input.Revive.OnDataChanged -= Revive_Raiser;
        }

        if (Interactor != null)
        {
            Interactor.OnWeaponSelected -= Interactor_Raiser;
        }
    }
}

커밋로그


Untitled

차주목표


인풋 리팩토링 및 애니메이션 연결하여 리소스 적용 완료

애니메이션 로컬 테스트 가능한 환경 구성

깃허브 마일스톤(4)에 등록된 이슈들 처리

6주차(5강, 4월5일~)


추가 개발환경 설정


컴퓨터가 하나 남아서 개발 설정.

데이터저장소와 서버같은느낌으로 사용하려고 구성.

Untitled

내부망에 공유폴더를 설치하고, 원격 설정 진행

wsl를 통해 ubuntu를 설치, 도커 설치 진행.

windows 10 home은 원격 데스크톱 설정이 안됨

(사실 이걸 해결하는 방법이 있지만, 시도하니까 안됨)

Releases · stascorp/rdpwrap

다 밀고 윈도우 서버 설정 시작

윈도우 서버 2019의 경우, 180의 무료사용기간이 있어 설치 진행(약 10월까지 사용가능)

서버 특성상 잡다한것 하나도 없고 하나하나 설치 진행

원격설정, 공유네트워크폴더 설정완료.

도커를 windows server에서 제공하는걸 사용하다가 어 cli네 해서 그냥 데스크톱용 도커를 설치

데디케이트서버를 띄워 테스트하니 연결이 안됨.

핑 가고 인바운드 규칙 적용되어있는데 연결이 안됨.

어느쪽 문제인지 알 수 없음. 서버문제인가? 연결단 코드문제인가?

깃허브 이슈를 노션에 등록

갑자기 막 찾다가 어? 깃허브에 노션 웹후크가 달려있네?? 이게뭐지???

하다가 이슈를 노션에 등록하고 싶어졌습니다.

node.js를 사용하여 크롤링 한 후,

데이터를 이제 노션 데이터베이스에 넣어줍니다.

(제가 짰다는건 아니고요)

Untitled

Untitled

Untitled

디버깅을 해보니, 데이터를 꽤나 섬세하게 볼 수 있습니다.

여기서 가져온 데이터를 잘 정리해서

열린시간과 닫힌시간을 기준으로 무언가 타임라인을 구성할 수 있었으면 좋겠네요.

(해당부분은 영복님이 작업해주셨습니다)

이제 이걸 서버에서 스케쥴링해서 매 시간마다 처리할 것입니다.

Untitled

Untitled

하루1회는 좀 너무합니다.

10분당 1회로 스케쥴러를 조절합니다.

Untitled

부활된 캐릭터의 idle애니메이션 오류 #95 해결


idle 애니메이션이 사망 이후 캡처되어, idle이 죽은모션이 되는 것으로 추측.

https://user-images.githubusercontent.com/19338839/161765333-cd3d5d56-b688-46c5-9a9f-e422e81a52a2.gif

단순하게 Idle 애니메이션이 없는 문제여서, Idle 애니메이션 요청 후 받아서 처리

체력바가 동일하게 감소되는 버그는 #94번에 할당됨(작업자 : 위영복)

카메라 구성 테스트 #114


다양한 방식의 연출에 대한 테스트가 가능하도록 구성한 뒤 팀원들과 테스트해보기

  • 목 대신 고정된 본을 중심점으로 변경
  • 카메라 fov 변경
  • 카메라 각도 변경 수치
  • 기타 등등…

Untitled

Untitled

45도, fov35도, 길이 11.5, 오프셋 z 1.5로 일단 2번 셋팅 사용하도록 처리.

진짜 CCRC에서 이러고 다같이 봄 진짜 CCRC에서 이러고 다같이 봄

어셈블리 참조구성 작업 #120


네트워크 유닛 테스트를 위해 어셈블리를 분리하였는데,인풋과 클라이언트코드, 네트워크코드간의 의존이 발생하여 네트워크 유닛 테스트를 위한 분리가 불가능.

따라서 종속성 관계를 해결하여 assdef을 작성 필요

결론적으로 network는 utils만을 참조하며, 그에 맞지 않는

replicated entityData를 필요로하는 클라이언트 코드의 위치를

network 어셈블리에 묶이지 않게 구성함.

ClientNetworkServiceManager와 PlayerInputNetworkManager가 비-네트워크 모듈로 평가되었고,

아래 코드들도 비-네트워크 모듈로 평가됨.

Untitled

모노 풀링 매니저가 유틸로 평가되었고,

일부 코드의 구조가 변경됨.

최종적으로 몇가지 뻘짓 후 네트워크 및 유틸에 대한 어셈블리 정의만 추가되었으며,

해당사항은 아래와 같음.

Untitled

캐릭터 조작(방향) 수정 #111


  • 이동 : 이동방향으로 달리기
  • 줍기 및 공격에 대해서 시전시 마우스 방향을 바라봄
  • 자동발사 구현 - 마우스 누르고있는동안 마우스 방향을 바라봄

  • 아이템 줍기는 캐릭터 기준으로
  • 입력이 없다면 마지막으로 사용된 방향입력을 기준으로 돌아감

개념적으로 마우스방향은 추가적인 정보.사용할 때만 가져오도록 구성 필요

아무리 생각해도 네트워크랑 인풋을 그냥 막 짜기 어렵다고 판단.

몇가지 원칙을 세움.

  1. 비헤비어는 view가 zero인 상황에 대해 그냥 뻗는다고 가정한다. (서버에서 바라보는 방향이 0인 경우에 따로 대응해야하는가? 데이터는 초반에 걸러야한다)

Untitled

  1. 발생할 수 있는 몇가지 가능성을 짜서 나와야하는 결과물을 작성한다 (이때 발생한 몇가지 예외나 구상되지 않은걸 확립한다)

공통되는 몇가지 케이스는 그냥 지우고, 의미없는 데이터라면 any로 묶어버렸다 공통되는 몇가지 케이스는 그냥 지우고, 의미없는 데이터라면 any로 묶어버렸다

  1. 작성한다.

    lookat.gif

이걸 주말에 CCRC가 안열려서 개발셋팅이 비교적 덜 되어있는

(모니터가 한대인) 컴퓨터로 작업하니 이런꼴로 작업을 했다.

좀 화난다. 좀 화난다.

(미완)캐릭터 조작(방향) 보간 #127


162615809-19af97f8-2bb5-4369-8c0e-98c040b299ed.gif

회전시 8방향이 아닌 구처럼 돌기위한 작업.

다만 로컬테스트(서버와 인풋을 받는 클라이언트 1대)로 작업하여,

실제 지연과 타 플레이어의 회전이 적용되어 보간될때의 결과물을 확인하고 수정해야한다.

결과물


시각적 결과물 없음

(통합 테스트 연결단 작업으로 인하여 불가)

커밋로그


Untitled

차주목표


중간 시연 준비 집중 컨텐츠 개발

Untitled

7주차(6강, 4월12일~)


개발서버 외부 원격 홀펀칭


Untitled

외부에서 접근할 수 있도록 3389포트에 접속할 수 있는 연결을 설정.

학교내부에서 포트포워딩을 할 수 없으므로, 홀펀칭을 통해 연결하도록 처리.

Untitled

네트워크 디버깅


클라이언트 발신단 맨날 패킷뜯고있음 (찡찡) 클라이언트 발신단 맨날 패킷뜯고있음 (찡찡)

windows server 2019 수신단. 패킷 길이도 다르고 데이터가 하나 추가되서 옴 windows server 2019 수신단. 패킷 길이도 다르고 데이터가 하나 추가되서 옴

UDP 전송이 데이터가 이상함.

알고보니 다른문제.

로컬 IP 가져오기


연결을 위해서는 로컬IP가 필요하다

Untitled

여러 네트워크 인터페이스가 있을 때 어디를 기준으로 해야하는가를 고려해야하지만 일단 이정도만 (중간빌드)

볼류메트릭 라이트 초안


Untitled

Untitled

버그수정


Untitled

이번주는 업무가 너무 많아서 적기도 귀찮으니 대충 때우겠습니다. 궁금하면 이슈 보세요

로비 이동


GIF 2022-04-16 오후 10-46-24.gif

씬 용량 최적화


씬이 270메가라 커밋이 안된다는 소리를 듣고 다급하게 컴퓨터를 켰다.(LFS 안씀)

Untitled

대략적으로 확인해보니, 폴리브러쉬로 변경된 메쉬로 포함되어,

해당메쉬는 저장되어지지 않아 모두 씬에 각각의 새 메쉬를 저장하고 있음을 확인했다.

그래서 여러개 잡고 삭제를 해보려하니 에디터상의 다중 컴포넌트 삭제가 기능하지 않는다.

몇백개를 하나하나 버튼을 눌러서 지워준다? 프로그래머는 그런 단순 반복작업 절대불가능하다.

자 코드를 짜보자.

Untitled

보호수준때문에 접근을 못한단다

Untitled

프라이빗 클래스다.

어림도없다. 리플렉션은 모든것을 알고있다.

삭제코드부터 확인한다.

Untitled

대충보니 pMesh.Setmesh(pMesh.source) → destroy(pMesh) 다.

Untitled

타입을 사용할 수 없으니, 가져와서 비교하고,

함수랑 오브젝트 가져와서 쓴다.

Untitled

빵-긋

결과물


GIF 2022-04-16 오후 10-46-24.gif

커밋로그


Untitled

Untitled

차주목표


“컨텐츠”

프로젝트 재정리 및 리플리케이션 구조 수정

몬스터 디테일

무기 추가

8주차(7강, 4월19일~)


재미란 무엇인가


중간발표에서 다른 게임들은 하나의 코어 재미 기믹을 기반으로 시스템을 짯었다.

하지만 우리팀은 PD를 할 때, 시스템을 우선적으로 구현하고, 게임에 대한 코어 기믹을 추후로 적용하고자 하였다.

그래서 평가는 좋지 못했다. 차이를 보여주지 못했다.

최근 한 게임이 언제인가, 무엇을 했는가 생각해보았더니, 게임을 한지 얼마 안되었다.

그래서 뽑아올만한 게임의 재미를 찾기 위해 떠나기로 했다.

리그오브레전드

테라리아

다양한 무기를 사용해보기 위해 에디팅하여 테스트맵을 만들고, 테스트를 했다.

Untitled

엔터더 건전

https://youtu.be/IvaRsBs166c

젤다의 전설 야생의 숨결

퍼즐과 전투+모험을 분리

별의커비 디스커버리

이게임은 그냥 레벨디자인이 모두 의도로만 구성되어 있다.

그냥 미쳤다. UX란 무엇인가 라는 교과서로 만들어야한다.

트레저 로드라는 별개의 스테이지를 구성해

학습과 숙련을 목적을 변경하여 분리함으로써 유저가 숙달될 수 있도록 꾀한다.

피드백 리스트에 대해 정리하며 별의커비에 대한 일부 머릿속으로 생각한 분석을 첨부한다.

피드백


  • 물 너무 반짝인다

물이 현재 10이상의 HDR값을 뱉는 경우가 있어서,

그부분만 보완해 준다면 괜찮다고 생각

  • 오브젝트 뒤 가려지는 캐릭터 실루엣 그레이 말고 그냥 실루엣은 어떤가?

잘 못들었습니다? 렌더파이프라인 뜯어고쳐야함. 디졸브된 실루엣 문제와 동일.

실루엣 처리 시점에서의 메쉬의 색상값을 알 수 없음. mesh에 vertexcolor를 수정한 후 다시 가져와야 할지도?

…현재 depth 검사를 실패한 …. 잠깐 이거 할 수 있을지도??

  • 게임의 목적이 눈에 잘 띄지 않는점,

  • 따라서 무엇을 해야할지, 무엇을 해야하는지 알 수 없음

동의. 젤다 야숨에서도 나왔던 말인데, 게임플레이에 익숙하다보니 유저는 이 게임은 이렇게 해야한다를 이미 학습하고 와서 플레이가 가능한 것.

초심자유저는 게임의 진행 방향을 인지하는것도 어려울 수 있음.

목적을 어떻게 시각화 할 것인지는 고민이 조금 필요.

평범한 Quest UI 평범한 Quest UI

  • 길이 여러갈래일 때 플레이어가 방향 놓치면 힌트를 알려줘야 하지 않나?

위와 동일. 플레이어 진행 방향 인지에 대한 정보가 필요함.

아주 직접적으로 접근한다면 표지판 등으로 꾸밀 수 있으며, 동상이 위치를 가르키거나, 선이나 뾰족한 무언가를 배치해 진행방향을 표기할 수 있음

Untitled

Untitled

혹은 움직이는 물체 혹은 동물로 표현하는것 역시 존재

뭔게임인지 이름은 기억안나는데 도마뱀이 지나가는 길이 가야할 방향인 게임도 존재하고, 만약 허허벌판이라면 길의 명도차이로 방향을 표현하는 방식도 존재한다고 생각.

Untitled

Untitled

  • 플레이어가 계속 플레이 할 수 있도록 궁금증을 계속 제시해줘야 한다
  • ( 직관적이거나 힌트)

맨날 어려운것만 시키시는 것 같은데 (궁시렁)

이거 정말 어렵다.

저번 퍼즐 스테이지 추가고려사항때 말을 넣었지만,

원경에 다음 지역이나 숨겨진 지역이 보이는게 좋을 것이라고 생각한다.

(좌측 : 다음스테이지) 엥 오른쪽에 저 상자와 섬은 뭐지? 전신주로 막혀있는데? (좌측 : 다음스테이지) 엥 오른쪽에 저 상자와 섬은 뭐지? 전신주로 막혀있는데?

넘어진 전신주와 올라와 있는듯한 땅으로 이곳 또한 ‘길’임을 인지시키며 유도한다 넘어진 전신주와 올라와 있는듯한 땅으로 이곳 또한 ‘길’임을 인지시키며 유도한다

돌아올 때의 부정적 피드백을 개선하기 위해 기존 스테이지 위치로 돌아가는 붉은 별을 배치한다. 돌아올 때의 부정적 피드백을 개선하기 위해 기존 스테이지 위치로 돌아가는 붉은 별을 배치한다.

커비는 의도하고자 하는 화면의 모든 구성을 ‘카메라를 제약함’으로써 구현해냈는데,

아이템을 적절하게 카메라의 최대각도에 둬서 다른방향으로 이동하지 않으면 보이지않는 기믹들이 존재한다. 그러면 유저는 그 위치를 어떻게 알 것인가?

답은 『볼 수 있는 장소로 1차적인 캐릭터 이동을 유도한다.』 이다.

Untitled

Untitled

이렇게 플레이어는 같은 공간을 설계해놓은 의도대로 행하며,

단순하게 의도대로 플레이하면서 ‘스스로 눈치를 챘다고 느끼며’ 성취감을 느끼게 할 수 있다.

  • 준비하기를 가운데에 배치하는 것도 괜찮을 것 같음

← 좋은 것 같은데 사실 옆스테이지로 이동하며 카메라 워킹이 들어가서 게임과 자연스럽게 맞물리게 한다면 의미없는게 아닌가. 중앙에 배치하였을때 게임플레이와 연결할 수 있는 방법이 있는가.

  • 준비하기로 이동할 때 캐릭터들이 다 뒤돌아있는게 안예쁨
  • 출구로 빠져도 안예쁠 것 같음.

아마 이쪽에서 부터 준비하기를 가운데에 배치하여 캐릭터를 이쁘게 보여질 수 있게 풀어내는걸 의도하시는 것 같은데 고민이 조금 필요.

  • 갈 수 있는 곳과 없는 곳의 차이/ 경로 유도는 UI/ 기획 쪽에서

이부분은 이제 커비 디스커버리를 해보면 교과서처럼 박혀있는 부분들이 있는데,

갈 수 있는 곳과 없는 곳의 차이를 특정 오브젝트(물에잠긴 전선주, 스태틱한 물체, 고정된 동적 물체(반응성 있는)로 1회 막아둔 후 지나간다면 아무것도 없는 등)로 가려두는 작업이 필요. 부술 수 있는 벽과 부술 수 없는 벽의 차이를 둬서 기본적으로 숨어있지만, 부셔서 생기는 길도 좋다고 생각.

  • VR 만들어보는건 어떨까?

네?


생각난 것들


맵에 배치된 고정형 무기(대포/발리스타)

무기를 통한 퍼즐

추가 무기


부메랑

랜덤 투사체 무기

리코더 (횟수제한 반사)

표지판 (패링되는 근접무기)

공격시 돌진하는 무기

무기를 통한 퍼즐

Untitled

스테이지 위치 및 배치

퍼즐 스테이지(작은 섬)를 원경에 배치하여 작은 섬 스테이지에 대한 흥미를 유도

Untitled

텔레포트 장치 혹은 마법진을 통해 소형 섬으로 이동(원경에 존재하던 스테이지) : LOD 필요

퍼즐 스테이지 세부 고려사항

시작 위치에 해당 퍼즐 스테이지를 클리어 할 수 있는 무기를 준다.

해당 무기를 들고 있다면, 출입구로 나갈 수 없고, 탈출구(스테이지 클리어 후 지역)로만 나갈 수 있다. 무기를 버리면 다시 출입구로 나갈 수 있다.

퍼즐 스테이지는 약간 고대의, 비 자연물이 배치된 젤다 야생의숨결의 사당같은 스테이지를 이미지하고 있습니다.

목적

추가적인 무기의 사용법을 학습하며,

게임진행과 별개로 스테이지를 분리해서 전투와 분리한다(스테이지간 통일성을 위해).

주 스테이지(2,3,4)는 모험과 전투, 즉 육체 - 조작에 대한 성장을

퍼즐 스테이지는 기믹과 퍼즐, 퍼즐에 대한 성취를 주고싶습니다.

젤다 야생의 숨결 및 커비 디스커버리를 플레이하다보면 잘 느낄 수 있는 부분인데,

다른 플레이 숙련도를 요구할 때에는 확실하게 분리한 공간을 사용해야 한다고 생각합니다.

상점

스피릿(골렘) 앞에 무기가 나열되어있고, 주우면 공격한다.

살(buy) 수 있는 방법은 없음.

결과물


없음

커밋로그


이번주차는 작업 X (팀 내 재정비기간)

차주목표


게임의 재미중 맛보기를 넣어보기

맵 정리하기

9주차(7강, 4월26일~)


임시최적화

단일기기에서 단 한대를 켰는데 프레임이 60이 나온다.

이상태로 개발 못한다. 최적화 진행

Untitled

난리다

ShadowMask로 굽고있는데 제대로 된 기능을 사용하지 않고 있고(realtime light 1개)

그에 따른 cascade, lightmap setting에 따라 또 배칭이 깨지고 있다.

일단 기본적인 오클루전 컬링과 일부 점검만 하고 패스.

쉐이더 R&D


Untitled

교수님이 이상한걸 말씀하신다.

어쩌겠습니까 까라면까야지 (한숨)

이 단순 텍스쳐 한장을 바르기 위한 노력을 기술하고자 한다.

실루엣이란 어떻게 그려지고 있는것인가?

실루엣은 뎁스값이 great인 대상에 대해 새로운 material로 ‘다시’ 그린다.

그렇다면 해당값을 그릴때 특정 데이터를 가져올 수 있는가? → 아니오.

범용적인 데이터를 가져올 수 있는 건 버텍스 정보 밖에 없다.

그럼 어떻게해야할까요?

답은 버텍스컬러를 찍는다 입니다.

Untitled

그런데 이걸 사용해도 되는걸까요?

Untitled

된다고 합니다. (뭐요)

그러면 컬러는 어떻게 넣을 수 있을까요?

일일히 모델링을 수정해야하나?

프로그래머는 그런거 모릅니다.

Untitled

약식으로 넣어봅니다.

어짜피 구워서 적용하는거야 나중에 하면 되니까요.

Untitled

색이 탑니다. 색상영역이 조금 다른 것 같네요.

그걸 넣을 때 처리하긴 귀찮으니 쉐이더를 바꿉니다.

Untitled

Untitled

Untitled

굳? 굳

그래서 이게 이쁘냐!!!

Untitled

뎁스테스트도 개판이고 이질감 잔뜩입니다.

다른 게임들에서 실루엣을 실루엣으로 표현하는데에는…(끄덕끄덕)

디벨롭을 더 해보자.

Untitled

완벽하게 뒤집어진 그림.

Untitled

(미침)

테스트용 개발셋팅


Untitled

대충 데디서버 빌드해서 몬스터 스폰안하게 띄워뒀다.

콜라이더 테스트용으로 처리해뒀는데 데브옵스가 있었다면 커밋 자동으로 흡수해서 빌드해줬으면 좋겠다 젠장

추후 업무로 미뤄둘까? 젠킨스 세팅을 해서 빌드까지 돌릴까??? 고민중

테스트용 개발셋팅 2


시스템 갈아엎는다고 클라이언트 플머는 조금 시간이 남았다.

든든-한 젠킨스 든든-한 젠킨스

구성은 간단하다.

git에서 push event가 발생하면 discord에 웹훅을 보내는것과 같이 젠킨스로 웹훅을 보낸다.

하지만 젠킨스가 동작하는 컴퓨터는 현재 내부망을 사용하기 때문에 홀펀칭을 해줘야한다.

ngrok으로

Untitled

8080포트 (젠킨스 웹) 에 연결을 한 후,

Untitled

웹 후크 연결을 한다.

해당 웹후크 이벤트가 발생하면, 특정 브랜치일 때, 빌드를 진행한다.

Untitled

이제 이때 빌드를 진행해야하는데, 유니티 배치모드 빌드를 사용한다.

Untitled

Untitled

아직 문제가 있다.

BuildDedicatedServer.BuildGame은 Call했을 경우 최종적으로 discord에 메시지를 보내도록 구성했는데,

Untitled

중간에 문제가 발생한게 틀림없다.

해당함수만 따로 떼서 테스트.

Untitled

Untitled

잘 동작

왜 젠킨스에서만 안되는걸까…

그래서 3가지로 분리

1
2
3
4
5
taskkill /f /t /im CKC2022TestServer.exe

"C:\Program Files\Unity\Hub\Editor\2021.2.17f1\Editor\Unity.exe" -quit -batchmode -projectPath "C:\ProgramData\Jenkins\.jenkins\workspace\CKC2022 TestServerBuild" -executeMethod BuildDedicatedServer.BuildGame -logFile "C:\ProgramData\Jenkins\.jenkins\workspace\CKC2022 TestServerBuild\Logs\Editor.log"

"C:\Dev\Build\RunTestServer.bat"

Untitled

Untitled

프로세스 킬, 빌드, 실행 모두 성공.

하지만 일부 여전히 문제 발생.

바로 젠킨스의 빌드가 끝나지않았다고 판단함.

Untitled

서버 로그까지 뿌려버리는 젠킨스!

일단 테스트는 되니까 나중에 고쳐야지

P.S

https://wiki.jenkins.io/display/JENKINS/Spawning+processes+from+build

코드 커버리지


이상원교수님 과제에서 그래픽 에뮬레이션 세팅을 찾던 도중, 재미있는걸 봤다

코드커버리지.

돌려볼 수 없는 마력에 빠져 간단하게 3분간 1인 멀티플레이를 돌려보았다.

Untitled

Untitled

어셈블리단위로 코드가 어디어디 지나쳤는지를 확인할 수 있고, 그 횟수또한 알 수 있다.

테스트러너와 같이 동작한다면 테스트에서 어떤 구문이 동작하지 않았는지, 즉 커버리지를 확인할 수 있으므로 조금 더 코드 정리 및 분석에 도움이 될 것이라 생각한다.

에디터 오브젝트 정렬 코드


테스트 씬을 구성하다보니 정렬해주는 툴이 너무 필요했다

이것.

이것.

GIF 2022-05-01 오후 7-05-14.gif

만들고 나니까 undo가 안되길래 undo도 추가.

최종본

GIF 2022-05-01 오후 7-20-12.gif

뷰 기준에서 처리하기 위해 좌표변환좀 하고 그랬다.

서버 및 클라이언트 구현 회의


기존 변경하고자 했던 구조로 변경에 더 많은 리소스가 할애되어,

1학기 개발은 기존 구조에서 추가하는것으로 변경.

테스트 씬 개발


아 이제 노션 렉걸린다 진짜 하 인생

Untitled

사실 이게 제일 급하다.

50000번에 바인딩, 실제 리소스 테스트는 50005번에 바인딩하여 서버를 2개 실행중.


여기부터는 엄청 바빠서 일지 적을 시간도 없습니다 (작성일 : 일요일 20시)


결과물


커밋로그


Untitled

Untitled

차주목표


더이상 컨텐츠 개발을 미룰 수 없다.

내부시스템 수정은 멈추고 여기부터는 온전히 보여줄 수 있는 것 만을 위해 작업하고싶다.

10주차(8강, 5월3일~)


무기구현 - 1


기존만들어진 방식을 통해 몇초간 지속적으로 공격할 수있는 레이형식의 무기를 구현함

GIF 2022-05-08 오후 4-38-11.gif

무기구현 - 2


무기구현 - 1을 통해 몇가지 확인사항을 확인 후, 근거리공격(투사체 튕겨내기)를 구현해봄

GIF 2022-05-03 오후 7-52-32.gif

:: 이때, Projectile 의 LifeTime을 조정할 수 있도록 추가 처리해야함

조준문제


Untitled

입력의 종속성을 해결하기 위해 짠 식이 오히려 조준점이 정확하지 않게 됨.

기존에는 그냥 단순하게 Ray로 땅을 찍던걸

Interactor의 위치를 화면좌표계로 변경해서 바라보는 방향을 화면좌표계상으로 처리했는데,

사실 이렇게짜면 안된다.

어짜피 뚝딱하면 고쳐질 코드 고침. 종속성을 다른쪽에서 풀었기 때문에 어짜피 막써도 되서…

투영해서 해결.

Untitled

1
2
3
var ray = Camera.main.ScreenPointToRay(position);
var worldPosition = VectorExtension.ProjectionToYAxis(ray.origin + ray.direction * 1000, ray.origin, Interactor.BindingTarget.Position.Value.y);
RawViewDirection.Value = (worldPosition - Interactor.BindingTarget.Position.Value).ToXZ().normalized;

애니메이션 작업


애니메이션이 공격이 1타,2타로 분리되도록 왔다.

Untitled

공격 하위 스테이트를 구성해서 이것저것 셋팅하고

첫타격에 태그박아서 태그비교로 검사한다

1
2
StateIsFirstShot = animator.GetCurrentAnimatorStateInfo(MasterLayerIndex).IsTag(FirstAttackTag); 
animator.SetBool("continuousAttack", StateIsFirstShot);

GIF 2022-05-08 오후 8-45-58.gif

연타공격 완료.

결과물


GIF 2022-05-08 오후 8-45-58.gif

GIF 2022-05-08 오후 8-53-30.gif

GIF 2022-05-08 오후 4-38-11.gif

GIF 2022-05-03 오후 7-52-32.gif

커밋로그


Untitled

차주목표


애니메이션 + 서버 레이턴시 관련해서 타이밍맞추는 작업들

11주차(9강, 5월10일~)


소프트 파티클을 위한 SubShader 작성


Untitled

일단 깊이부터 대충 가져올 수 있게 처리

Untitled

작성

GIF 2022-05-09 오후 12-42-02.gif

결과물


이하 여백

커밋로그


Untitled

차주목표


이하 여백

12주차(10강, 5월17일~)


SRP batcher + geometry shader 오류해결


https://github.com/daniel-ilett/shaders-botw-grass

GIF 2022-05-16 오후 4-41-58.gif

지오메트리 쉐이더를 사용하는 풀 쉐이더의 위치가 이상함.

Untitled

SRP 배처를 끄면 위치만 조금 다른것을 확인.

코드에서 무언가 공간변환이 잘못됨을 인지.

Untitled

input의 vertexPosition을 가져와 사용하는데, 해당 position은 world변환된 좌표.

하지만 TransformGeomToClip에서 world를 다시 modelToWorld로 재변환.

야매해결


Untitled

월드포지션 기준이 아닌 모델링 공간 기준으로 작동하도록 변경

Untitled

SRP 배처의 경우는 알 수 없으므로, 단순하게 SRP배처가 동작하지 않도록 작업.

UnityPerDraw로 구성되도록 하여 정보를 공유하지 않게 처리.

비교적 정상적 해결


최종적으로 TransformGeomToClip에 modeling space의 vertexPosition을 넣어주면 해결되는 문제.

msPos를 추가하여 해당데이터를 넣어줌.

Untitled

추가 수정

c버퍼 공간최적화를 위해 변수 순서 변경

Untitled

포그 적용


아무래도 기존 버텍스-프래그먼트 쉐이더가 아니다 보니 조금 애로사항이 있음.

또한 CGPROGRAM이 아니라 HLSL이다 보니 문법 변경사항이 조금 있음.

포그의 개념자체는 아주 단순

픽셀의 거리값을 기준으로 linear 혹은 exp로 최대 최소치를 설정한 0-1의 값을 구해낸 다음,

fogcolor랑 linear interpolation 처리하면 됨.

멀티컴파일 처리를 한 후

Untitled

포그의 값을 설정

Untitled

최종 fragment 단으로 넘어가는 데이터에서 fogCoordination에 추가

ComputeFogFactor의 인자는 clipSpace Position Z. 그러면 포그설정에 따라 0-1의 값으로 변환해줌

Untitled

Untitled

내부적으론

ComputeFogIntensity를 통해 exp 처리한 값으로 처리해주거나 하는데

Linear는 단순히 값을 반환하며, 이를 Lerp하여 뱉음.

최종적으로 포그를 처리해서 뱉으면 완료

Untitled

화면 캡처 2022-05-17 125541.png

적용완료.

라이트닝 무기 구현


GIF_2022-05-17_7-17-15.gif

디텍터 구조 개선


중복코드가 많아서 몇가지 방식으로 수정

  1. 콜라이더를 통해 Hit과 Info를 Generation
  2. 이미 존재하는 hit정보를 통해 Info를 Generation
  • Info 를 적용
  • 디텍터 종료

Untitled

다음과 같은 형식으로 사용할 수 있도록 처리.

카메라 스냅핑 구현


3미터 이상일 경우 보간이 아닌 텔레포트하도록 적용.

외부에서 콜할 수 있도록 글로벌에서 접근할 수 있게 처리, 접근하여 콜할 수 있도록 처리

카메라 쉐이킹 구현


Untitled

폭발공격 구현


(엥 뭐야 gif 어디갔어요 -2024년 포스트옮기며 발견-)

결과물


(엥 뭐야 gif 어디갔어요 -2024년 포스트옮기며 발견-)

커밋로그


Untitled

차주목표


무기 아이템화 관련 클라이언트 코드 분석 및 변경

13주차(11강, 5월24일~)

풀 상호작용 쉐이더 작업


풀 지오메트리 쉐이더

GIF 2022-05-26 오후 3-31-58.gif

서버 구조 변경에 따른 인풋 수정

ClientSessionManager.Instance.IsReadyToUpdateGame 가 이제 사용되지 않고,

ClientNetworkManager.OnSessionConnected 가 처리되지 않기때문에 그에 따라 구조를 수정

무기 구조 변경 - 데이터 통합

Untitled

기존 Entity로써 처리되던 구조를 단순 데이터로 변환.

Equip의 type이 추가되었으며, 변경시 소지한 무기의 모델링 인스턴스를 가져올 수 있도록 처리.

근거리 디더 처리


최적화를 위해 주 함수를 HLSL로 작성

Untitled

Untitled

index / 17을 미리 구워두고, const 배열을 통해 매 fragment shader 콜마다 발생하는 재생성 부하를 처리.

KakaoTalk_20220524_134010936.gif

근거리 디더처리 2


Untitled

clipping 값에따라, 기존의 alpha값에 따라, 디더가 정확히 처리되지 않는,

예를들어 너무 멀어도 이미 디더가 처리되는 불상사 발생

Untitled

식을 찬찬히 음미하며 다시 작성.

DIther연산은 최종적으로 in - TableValue 이므로,

시작거리 이상의 값일 경우 사실 처리되면 안된다는점에서 1 - t를, 1 - t에서 lerp를 착안하여 작성

Untitled

DitherTest.gif

알파 0.8, 클립핑 값이 다른 세 객체에 대해 동일하게 잘 처리됨을 확인.

커밋로그


Untitled

차주목표


무기줍기 버리기 구조 변경 완료시 신규무기 - 곡사범위포격 구현

14주차(12강, 5월31일~)

무기버리기

사운드 매니저

데이터 구성

Untitled

세팅노가다 귀찮으니 대충 긁어서 처리하도록 처리

Untitled

Untitled

함수 호출시 구성해서 처리하도록 처리

동일사운드 반복재생시 어색함을 줄이기 위해 피치 변조 사용

Untitled

BGM 사운드 페이드인/아웃 구성

Untitled

파일설정

Untitled

Untitled

이동 발자국소리

대충 애니메이션 프레임에 맞춰 이동속력([0,1])을 볼륨으로 하는 사운드를 발생하게 처리

Untitled

공간음향

기본적으로 카메라와의 거리가 꽤 있기 때문에

30미터에서 사운드가 거의 들리지 않도록 custom rolloff로 구성

Untitled

신규무기 - key of wisdom

디텍터는 단순 x초 후 검사하도록 처리

클라이언트 사이드에서 기타 처리하도록 구성

GIF 2022-06-03 오후 8-41-53.gif

Untitled

단순하게 시작 - 진행중 - 종료 에 대한 이벤트를 받아,

클라이언트에서 추가 처리를 하도록 프리팹-스크립트 구성

Untitled

커밋로그


Untitled

Untitled

차주목표


15주차 (13강, 6월7~)


커밋로그

Untitled

최종


This post is licensed under CC BY 4.0 by the author.
Contents