친구들과 함께 [APEX Legend]를 하면 꼭 한 라운드에 한번씩 하는 말이 있다.
친구 1: "아 또 순간이동하네..."
친구 2: "아니 분명 숨었는데 왜 또 맞아!"
나:"아 서버문제만 아니였으면 이겼다.."
원래 APEX Legend는 20hz로 구동되지만 서버의 각종 처리가 50ms 이상 걸리면 말그대로 슬로우 서버가 되어 우리가 보는 화면이 느리게 보인다.
참고 영상: https://youtu.be/w_YEyxBgy8Y
요즘엔 많이 줄어들긴 했지만 초기에는 정말 문열고 집에 들어갔는데 죽는경우가 꽤 있었다.
반대로 분명 제대로 조준을 해서 맞추었는데도 안 맞는 경우도 꽤 많았다.
크게 보면 이렇게 2가지가 있는데 사실 대부분의 FPS게임에서 가지는 문제점으로 보인다.
평소에도 FPS,TPS 슈터를 즐겨하는 사람으로서 궁금하지 않을 수가 없었다.
"왜? 저런 문제가 생길까?"
친구1: "컴공이라는 녀석이 이런것도 모르냐!"
어처피 게임 하나 새로 만들때가 됬는데 겸사겸사 하나 만들어보며 어떤문제가 있는지 알아보기로 했다.
다행히 서버는 바닥부터 새로 만드는것이 아니라 저번에 들었던 인프런 강의 중
_[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버_
와
[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part7: MMO 컨텐츠 구현 (Unity + C# 서버 연동 기초)
를
기반으로 조금 수정을 하고 클라이언트는 작년 겨울에 잠깐 본 고박사의 유니티 채널: FPS Prototype
을 기반으로 수정을 하면 금방 만들 수 있을거라 생각했다.
위에서 말했던 "조금 수정"은 생각보다 많은 것을 들어내고 바꿔야하는데... 다행히 서버쪽에서 소켓 연결 및 각종 자료구조들은 그대로 재사용이 가능하지만 서버 내 모든 처리(packet handler, object state control)등등 따로 만들어야 됬다.
클라이언트(유니티)쪽에서는 예전에 에셋번들로 샀던 Character Movement Fundamental
스크립트 일부(이것도 추가적인 액션 때문에 엄청 고치긴했다..)로 기본적인 부드러운 이동제어를 하고 나머지는 직접 짰다.
참고자료:
ROOKIES님의 강의: https://www.inflearn.com/course/%EC%9C%A0%EB%8B%88%ED%8B%B0-mmorpg-%EA%B0%9C%EB%B0%9C-part4/dashboard
고박사의 유니티 노트 채널: https://www.youtube.com/c/%EA%B3%A0%EB%B0%95%EC%82%AC%EC%9D%98%EC%9C%A0%EB%8B%88%ED%8B%B0%EB%85%B8%ED%8A%B8/videos
character movement fundamental 에셋: https://assetstore.unity.com/packages/tools/physics/character-movement-fundamentals-144966
목표
- FPS일것 - TPS는 추후 지원여부 판단
- 캐릭터 액션에는 점프, 달리기, 슬라이딩, 조준, 사격이 존재 - 스킬이 추후 지원여부 판단
- 무기는 1~4번까지 - 1: 주무기 2: 보조무기 3: 근접 4: 폭탄
- 오버워치의 힐팩같은 힐팩 스폰, 탄약 스폰이 있을 것 -
콜오브듀티
시리즈처럼 벽뒤에 가만히 있으면 체력차는건 너무 게임의 템포를 떨어트림- 데스매치 타입의 게임 - 개인적으로 가장 좋아하는 타입. 옛날 서든 어택에서도 웨어하우스만 했었다...
- 최소 3:3에서 최대 8:8까지 지원
- APEX Legend 처럼 스킬도 지원했으면 좋겠다. - 위를 먼저 만들고 후에 제작
일반적인 구현 코드는 생략하겠습니다.
CameraRoot
아래 Camera
는 Weapon
과 투명객체외 모든 Layer
을 랜더링하고 WeaponCamera
는 오직 Weapon
렌더링하여 구현한다."이렇게 하는 이유는 하나의 카메라만 사용시
weapon
부분이 벽을 통과하여 보이거나 시점을 위 아래로 바꿀때 따로 애니메이션구현이 없기 때문에weapon Arm
이 보이지않는데 총알이 조준점으로 나가는 이상한 모습을 보게된다."
Lctrl
를 눌러 미끄러지게 하고, 슬라이딩 중에 점프를 하면 슬라이딩 속도의 momentum
(힘)을 받아 좀 더 멀리 나가게 되어 스피드한 감각을 살렸다.1번 주무기: AK-47 로우 폴리가 무료 에셋으로 있어서 사용하였다.
2번 보조무기: 평범한 권총 로우 폴리가 무료 에셋으로 있어서 사용하였다.
3번 근접무기: 딱히 맞는 에셋이 없다... 모델찾아 리깅하고 애니메이션 만드는데 시간이 걸리니 나중에 만들려고 한다.
4번 투척무기: 현재 쓰고있는 무료 로우폴리 에셋에는 투척물이 Hand_Grenade
밖에 없지만 수류탄 하나라도 구현하였다.
(3,4번 무기는 따로 애니메이션이 없다... 따로 1번과 같은 포즈에 총이 안들고있는게 디폴트 모션이되었다.)
목표
- 지연보정으로 인한 자잘한 렉 줄이기 (어디까지 가능한지가 사실 이번 프로젝트로 얻으려는 것)
- 데디케이트 서버로 해당 라운드만 관장하는 방식, 따라서 최대 접속자 8:8 = 16인
- 데드레커닝 적용
- 위와 비슷한 말이긴하지만 패킷전송양(대역폭) 줄일 수 있을만큼 줄여보기
- 피격, 충돌, 보간등은 일단 유니티 내부적으로 컨트롤하는 것으로 - 현실적인 목표
- 서버 내부에서 물리적 판단까지 하여 클라에서 보낸 충돌 및 히트 판정에 대한 진위 판별하기 - 최종 목표...
- 클린코드를 지향하자
일반적인 구현 코드는 생략하겠습니다.
ConfigManager
에서 config.json
을 불러오고, 불러온 config
파일에 기반하여 Data
를 불러온다.config
파일과 Data
파일에는 대단한게 들어있지는 않다. config
에는 data path
정도 들어가 있으며 data
파일에는 플레이어들의 초기값 세팅정도와 맵의 사이즈와 연관된 minX
,maxX
,etc
와 RespawnPoint
정도 밖에 없다.ver.1.0.0
이 완성되면 한번에 summary
형식으로 정리를 해야한다.AWS EC2 프리티어 사용이 이미 끝나서 서버를 올릴때가 마땅치 않아 찾은 ngrok라는 앱이 있다. 따로 어떤 포트포워딩이나 방화벽 설정이 없이 ngrok 엔드포인트에 데이터를 전송하면 내가 열어둔 포트로 포워딩이 된다. ngrok에서는 터널링 시스템이라 부른다.
서버와 클라이언트 사이의 공통된 패킷규약을 만들기 위해 구글이 만든 Protobuf
라는 데이터포맷을 사용하였다.
직접 packet generator
를 만들어서 하는 것보다 훨씬 이것저것 지원되는 것들이 많아서 사용하였다.
이때, 가장 많이 전달되는 Keyboard입력은 int32
타입 안에 BitFlag
를 이용하여 큰 폭으로 대역폭을 줄였다.
또한, transform 데이터로 position을 계속 보내는 것이 아니라 Input
값을 BitFlag
로 입력되었을 때만 보내고 버튼에서 손을 뗐을때 보내는 방식으로 패킷2번으로 Movement
를 제어한다.
(물론 일정시간마다 실제 position을 보내어 서버와의 오차를 체크하고 싱크를 맞추는 부분도 있다.)
ClientSession
에서 들어온 패킷들은 해당 패킷에 맞는 핸들러로 간 뒤에 Job에다가 넣어준다. 보통 일반패킷들은 몆초후에 처리할 일이 없으니 따로 예약시간은 두지 않는다.
위의 Main Program
에서도 말했듯이 Job은 50ms(20hz)마다 한번씩 돌아간다.
링크: https://youtu.be/krIg4MJ12zc
"현재 비디오 편집의 오류로 초반부 이후 음소거가 되어있습니다.
몇몇 수정 사항을 고친 뒤 새로운 플레이 영상을 올리겠습니다."
C# socket과 Timer.timer로 간단한 TCP기반 서버와 서버에서 돌아가는 Job Scheduler
구현
position
과 rotation
값을 60hz 로 보내는 것이 아닌 입력 값이 있을 때 보내는 Input
패킷을 통해 상대 클라이언트에서 이동방향을 추측하고 이동시키는 방법.KeyboardInput
패킷은 BitFlag
방식을 통해 7개의 입력을 int
하나로 보내어 대역폭을 낮출 수 있었다.KeyboardInput
값을 받아도 지연차이가 생긴다. 따라서 일정 시간마다 한번씩 position을 동기화 하는 작업이 있다.
인상깊게 봤습니다!! input을 비트플래그로 한 번에 보내는 건 정말 좋은 방법인거같아요! 괜찮으시다면 코드가 궁금한데 깃허브 링크같은 것이 있을까요??