# game

[게임 개발] Tiny 2D RPG: 2 - 플레이어 이동, 공격
Tiny 2D RPG 📖 본격적으로 구현하기에 앞서 이번 프로젝트를 어떤 방식의 게임으로 만들어야 할지 정해야 한다. 예를들면 2D RPG여도 '바람의나라'처럼 격자형식으로 만들 수 있고 아니면 점프와 낙하가 존재하는 '메이플스토리'처럼 만들 수 있다. 이미 격자형식은 한 번 다루어 봤으니 이번 프로젝트는 자유형식으로 진행해볼 예정이다. 1. 캐릭터 캐릭터 리소스는 이전에도 말했듯이 SPUM이라는 2D 캐릭터 생성 툴을 사용할 것이다. 인게임에 SPUM을 적용하는 것이 아닌 고정적인 캐릭터 모습을 만들기 위해서 사용할 것이다. SPUM을 이용해 만든 캐릭터는 아래와 같다. 한손에는 방패를 다른

[게임 개발] Tiny 2D RPG: 1 - 프로젝트 설정
Tiny 2D RPG 📖 NodeJS와 TypeScript를 공부하면서 소규모 온라인 2D RPG게임을 만들어보고자 작은 토이프로젝트로 'Tiny 2D RPG'라는 프로젝트를 시작하려고 한다. 우선 클라이언트로는 Unity, 서버로는 NodeJS를 사용할건데 소켓통신을 위해 SocketIO를 사용하고자 한다. NodeJS에는 그냥 SocketIO를 설치해서 사용하면 되지만 아쉽게도 유니티에는 SocketIO에셋을 유로로 구매해야한다 ㅠㅠ SocketIO에셋으로는 'Socket.IO V3/V4 Client Basic'을 사용할 예정이고 다른 프로젝트에서는 'Google ProtuBuf'를 사용했었는데 일단 클라이언트부분을 어느정도 구현하고 이후에 고민해봐야 할 것 같다.

싱글톤
FE이던, 클라이언트 개발이던... 저장, 관리와 관련된 디자인 패턴이 꼭 있다. 그중에서 게임 디자인 패턴에서 자주 보이는 싱글톤 패턴에 대해서 알아보려고 한다. 접근성이 좋아짐 게임 내에서는, 각각의 노드에 할당되어있는 컴포넌트에 접근하는 방식이 다양하다. 직접 Find하거나, Property로 참조하거나 여러 방법이 있지만, 이런 과정은 코드가 많이 더러워지거나 유지보수 관리하기 어려운 경우가 많다. 경로로 찾거나 이름으로 찾는 경우라면, 노드의 이름이나 경로가 변경되면 그에따라 스크립트도 변경해야하기 때문이다. Scene보다 상위 단위 Scene1에서 Scene2로 넘어가는 과정에서는, 데이터가 파괴되고 서로 참조할 수 없는 상태가 되는것이 일반적이지만, 싱글톤 패턴을 사용하면 Scene을 넘어가더라도, 여전히 데이터들이 유지가 된다. 보통 다음 씬에서 이전 씬의 데이터를 받아오는 형식으로 스크립트를 작성한다. GameManager(에디터, 게임 내에서

[게임 서버] 서버 구조
게임 서버 보통 게임을 시작할 때 로그인을 먼저하고 그 다음에는 서버를 선택하는 화면이 나온다. 서버를 선택하는 구조는 보통 메이플, 던파, 로아와 같은 대형 RPG게임에서 주로 사용한다. 물론 한 서버 내에서 채널을 사용하기도 하지만 RPG게임에서는 보통 거래와 공격같은 상호작용은 같은 서버내에서만 이뤄지기 때문에 게임을 나누는 가장 큰 단위는 서버라고 할 수 있다. RPG게임 특성상 사람이 많으면 많을수록 커뮤니케이션이 활발해져 '서버를 하나만 운영하고 지역 단위로 서버 머신을 둘 수 없는가?'에 대한 생각이 들 수 있다. 물론 지역마다 포탈이나 순간이동으로만 이동할 수 있다는 전제가 있다면 가능할 수도 있다. 하지만 특정 지역에 거의 모든 유저가 한번에 몰릴수도 있고 만약 게임이 심리스게임이라면 지역이동을 처리할 때 지역을 담당하는 서버 머신간의 통신시간은 곧 사용자의 입력 반응속도에 영향을 미칠수 있다. 이용하는 사람이 많아질수로 서버에 가해지는 부하가 크게 증가한
[게임 서버] 게임 해킹
게임 해킹 게임을 하다보면 흔히 '핵'이라고 말하는 게임 해킹 프로그램을 사용하는 유저들을 볼 수 있다. FPS의 월핵, RPG의 쿨타임 핵, 레이싱 게임의 스피드 핵, 어렸을 때 리그오브레전드의 '무한 몰락 핵'등이 게임 해킹의 예시 중 하나이다. 보통 게임 해킹은 게임과 로직을 처리하는 서버의 취약점을 이용해 의도적으로 비정상적인 기능을 작동 시킨다. 해커에게 이로운 기능(ex. 무한 게임재화)으로 사용할 수 있지만 다른 사용자에게 해로운 기능(ex. 강제 PK)으로 사용하기도 한다. 1. 메모리 조작 게임 해킹 방법으로 '메모리 조작'을 할 수 있다. 기본적으로 클라이언트에는 현재 플레이 중인 상황에 대한 데이터가 담겨있다. 바꾸고자 하는 데이터가 들어있는 메모리주소를 알고 있다면 여기의 데이터를 변경해 인게임 내의 값을 바꿀 수 있다. 메모리 조작에 사용되는 프로그램이 따로 존재한다. 어릴때 유행했던 '치트 오매틱'이나 **'치트 엔진'
[게임 서버] 연결 종료 처리
연결종료 플레이어가 게임을 종료할 때 항상 정상적인 방법으로 종료한다는 보장은 없다. Alt+F4로 프로그램을 강제종료할 수도 있고 컴퓨터 전원이 나가거나 비정상적으로 종료할 수 있다. 정상적인 종료는 한 쪽이 통신 연결 종료 요청을 보내고 이에 대한 응답이 오가면서 연결을 종료하는데 서버쪽 입장에서는 아무런 정보가 오지않을 때 연결이 종료된것인지 실제로 아무것도 입력을 안하는 것인지 구분하기가 쉽지 않다. 이를 위해 아래 그림과 같이 주기적으로 클라이언트의 살아있는지(연결이 되어있는지)확인하는 패킷을 보내는 방법이 있다. 패킷의 내용에 들어갈 정보는 없다. 그저 상대방의 연결여부를 확인하기 위함으로 보낼 정보는 상대방이 패킷종류를 구분하기 위한 PacketID 뿐이다. <img src="https://velog.velcdn.com/images/pkoi5088/post/ee38aaff-7398-4c13-a958-e09c571cdb04/
[게임 서버] Zone
Zone 대형 구조에 대해서 다뤘을 때 오픈월드 환경에서 Zone을 나누어 같은 Zone에 있는 다른 플레이어들에게만 패킷을 전송하는 구조를 아래 그림과 함께 이야기를 했었다. 하지만, 굳이 오픈월드가 아니어도 매우 넓은 맵에서 Zone의 개념을 사용할 수 있다. 물론 사용자가 입장, 퇴장, 이동 할 때마다 해당 정보를 플레이어가 포함된 Zone을 찾아 해당 Zone에 있는 모든 플레이어에
[게임 서버] 대형 구조 관리
대형구조 MMORPG에서는 한 공간에 얼마나 많은 유저가 모여있는지가 관건이다. 대표적인 문제는 패킷을 Broadcast하는 문제인데 사람이 늘어날수록 보내야 하는 패킷의 양은 점점 더 많아지게 된다. 사람이 N명이 있을 때, 사람 한명의 움직임은 N명에게 해당 정보를 보내야 하며 몬스터나 NPC와 같은 NonPlayer Object에 대한 움직임에 대한 정보를 N명의 사람에게 전송해야한다. MMORPG의 경우 여러 플레이어들을 하나의 Room에 넣어 관리하는 구조를 가질 수 있는데 Room은 각 플레이어의 이동정보와 같은 Broadcast해야 할 요소들을 다른 플레이어들에게 전달하는 PlayerManage를 수행한다. <img src="https://velog.velcdn.com/images/pkoi5088/post/56813878-ca66-467f-8b3f-79c9659a7ff8/image.png" width="70%" height
[게임 서버] 아이템 사용, 장착 처리
아이템 사용 플레이어가 아이템을 사용하고자 할 때 서버는 이를 어떻게 처리해야 할까? 첫번째로 플레이어는 서버에 어떤 아이템을 사용할 것인지에 대한 요청을 보내야할 것이다. 요청을 받은 서버는 요청한 플레이어가 실제로 사용이 가능한 상황인지 확인할 것이다. 여기서 '실제로 사용이 가능한 상황'은 정말 아이템을 가지고 있는지, 스턴이나 그로기 같은 플레이어가 아이템을 사용할 수 없는 상태인지 등 여러가지 상황을 의미한다. 아이템을 사용하는데 다른 플레이어에서 Broadcast를 하는 이유는 플레이어가 아이템을 사용했을 때 발생하는 이펙트(ex. 회복 이펙트, 투척모션)과 같은 애니메이션을 다른 플

[Virtual World] Modeling
3D models 3차원 모델이란? 3차원 공간 상의 객체이다 . 이를 수치적인 표현을 한 것을 3차원 모델이라고 한다. 수치적으로 접근한 모델은 Polygon Model 이 있다. 이뿐만 아니라 컨트롤 point로 수학적 곡면을 재현하는 것이 가능하다. 기본적인 형상들을 더하고 뺌으로써 하나의 복잡한 모양을 만들 수있다. 우리가 자주 보게되는 건 ploygon mash일 뿐이고 세상엔 표현이 있다 정도로 기억하길 바란다. Coordinate System 우리는 가운데에 있는 데카르트의 좌표계를 주로 사용한다.

Game Engine
교재 게임 엔진에 대한 내용을 가지고 있는 jason Gregory 의 Game Engine Architecture Engine Architecture 오늘날 Unity 와 unreal angine 이렇게 두 가지로 크게 양분된다. 언리얼의 경우 엔진으로 시작하기 보다는 게임을 만드는 과정에서 파생된 소프트웨어이다. 유니티의 경우 늦게 등장했지만 사용이 용이하게 만들어졌다. 최적화적인 부분 등에서는 언리얼에 비해 떨어진다. 언리얼은 open source 이다. 유니티 에셋스토어. 게임 엔진이라고 하는 것은 결국 비디오 게임을 만들기 위함인데, 이에 필요한 기술들은 아래와 같다. Architecture Overview 
[게임 서버] 아이템 처리
아이템 서버에서 아이템을 구현하려면 데이터베이스에 아이템 테이블을 정의해야 한다. 하지만 데이터베이스에는 아이템의 모든 정보를 담고 있을 필요는 없다. 아이템의 이름이나 기본공격력같은 기본정보는 클라이언트에게 데이터시트를 참고하라고 하고 서버는 클라이언트에게 데이터시트의 식별번호만 넘겨줌으로 클라이언트에게 보낼 정보를 최소화 시킬 수 있다. 데이터 시트에는 서버와 클라이언트가 공통으로 가져도 괜찮은 정보를 저장하는 것이 좋다. 게임마다 다르겠지만 아이템의 이름, 기본 수치와 같은 정보가 이에 해당한다. 물론 강화수치나 추가 스텟과 같은 정보는 서버의 데이터베이스에 저장해 놓고 클라이언트에 전달하는 구조가 되어야 한다. 물론 게임도 하나의 동기화 시켜야할 오브젝트로 서버가 알고있는 플레이어의 아이템과 클라이언트가 가지고 있는 아이템의 오차가 없어야 한다. 1. 게임 입장 RPG게임의 경우 플레이어가 게임에 입장할 때 서버는 해당 플레이어의 정보와 가지고 있는
[게임 서버] DataBase Queue
DataBase Queue lock과 데이터베이스에 접근하는 기능을 동시에 사용하면 시스템 성능이 떨어지는 상황이 발생할 수 있는데 그림으로 나타내면 아래와 같다. PlayerB와 PlayerC의 요청을 처리하는 쓰레드들이 오랜시간동안 대기하게 된다. 이러한 문제는 단위시간동안 요청이 많아질수록 심각한 성능저하를 야기한다. 이러한 문제가 발생한 원인은 여러 쓰레드가 데이터베이스에 접근하는 기능을 실행하려고 할 때 접근하는 코드가 연산 순서상 lock으로 형성된 임계구역에 있음으로 인한 쓰레드 대기현상이다. 즉 위 그림에서 PlayerA, PlayerB, PlayerC가 게임을 떠나 각 플레
[게임 서버] 로그인 처리
로그인 처리 로그인을 처리를 구현할 때 서버는 클라이언트가 넘긴 정보에 대한 검증과 실제 데이터베이스에 존재한 정보인지 확인을 해야한다. 물론 데이터베이스에는 사용자의 정보(아이디, 비밀번호)에 대한 테이블이 존재해야 하고 사용자의 식별을 위해 클라이언트는 PK로 사용되거나 UNIQUE속성이 있는 정보를 서버로 넘겨줘야 한다. 1. 사용자 검증 및 확인 사용자 검증에 해당되는 내용은 '정말로 사용자가 로그인 요청을 보낼 수 있는 상황인가?'와 같은 내용이 해당된다. 사용자가 연속으로 로그인 요청을 보낼 수도 있고 악의적인 사용자가 이미 로그인이 되어 있을 때 의도적으로 로그인 요청을 보낼 수도

컴퓨터가 길을 찾는 더 빠른 방법(JPS알고리즘의 작동방식)
RTS, AOS장르의 게임들에서 플레이어가 목적지를 지정하면 캐릭터들은 목적지까지 “알아서” 장애물을 피하고 “최단거리”로 목적지에 도착한다. 오늘은 캐릭터들이 어떻게 목적지에 알아서 도착하는지에 대한 알고리즘에 대해 배워보자. > 눈을감고 길을 찾아봅시다 컴퓨터가 길을 찾는 과정은 눈을감고 길을 찾아보는 것과 똑같습니다. 내 주위에 어떤 사물이 있는지 볼 수 없는 상황에서 길을 찾으려면 어떻게 해야 할까요? 주위를 손으로 더듬거리며 장애물이 존재하는지를 찾는 방법이 제일 흔히 사용할 수 있는 방법일 겁니다. 실제 컴퓨터가 길을 찾는 것은 결국 장애물이 있는지 없는지를 한 칸, 한 칸 뛰어넘어가면서 확인해는 프로세스입니다. 해당 과정에서 어느 방향으로 한 칸을 뛰어넘을지에 대한 규칙을 잘 만들어내면 빠른 속도로 길을 찾을 수 있겠죠? 컴퓨터가 길을 찾는 방법 다익스트라 알고리즘 다익스트라 알고리즘은 컴퓨터가 길, 최단경로를 찾을 때 사용
[게임 서버] 몬스터 AI
몬스터 AI 싱글플레이게임에서의 몬스터 AI는 몬스터의 기능에 대한 연산을 몬스터 GameObject의 컴포넌트로 붙여 현재 상태를 계산함으로 구현할 수 있다. 스킬쿨타임이나 애니메이션같은 경우 코루틴을 이용한 시간계산으로 구현하였는데 온라인게임같은 경우 서버로부터 몬스터의 상태에 대한 패킷을 클라이언트에게 전송해 몬스터의 상태를 받은 클라이언트는 그저 랜더링만 하면 된다. > 싱클플레이게임의 몬스터 AI는 유니티시리즈에서 다루었다. 1. Update 몬스터의 상태변화나 판정은 플레이어 공격의 투사체를 구현했을 때와
[게임 서버] 플레이어 상태변화
플레이어 상태 플레이어의 상태정보는 서버가 가지고 있고 클라이언트는 서버로부터 상태정보를 받아 화면에 표시하는 구조를 가진다. 플레이어의 상태로는 플레이어의 위치, 체력, 마나와 같은 정보나 스텟과 관련된 정보가 될 수 있다. 서버에서는 플레이어의 정보를 Character와 같은 객체로 만들어 나타낼 수 있고 데미지를 받거나 버프를 받는상황 죽는 상황에 대한 반응을 함수로 나타낼 수 있다. 1. 패킷 서버는 클라이언트에게 '상태를 변화시키는 패킷'이나 '플레이어가 죽었음을 알리는 패킷'과 같은 상태변화를 알리는 패킷을 보내야 한다. 하지만, '~한 상태로 바꿔라'라는 패킷은
[게임 서버] 플레이어 공격
플레이어 공격 멀티게임에서 플레이어 공격을 구현할 때 어디까지 클라이언트가 담당하고 서버가 어디까지 처리해야 안정적인 공격환경을 만들 수 있을까? 가장 이상적인 방법은 클라이언트를 완전히 신뢰하고 클라이언트가 보낸 정보를 바탕으로 서버에서 처리하는 방법일 것이다. 하지만 서버는 클라이언트를 항상 의심해야 한다. 클라이언트가 보낸 정보(패킷)가 조작된것일수도 있다. 그렇기 때문에 서버는 플레이어들의 정보를 항상 가지고 있어야 하며 플레이어가 각자 가지고 있는 자신만의 정보와 동기화가 되어 있어야 한다. 플레이어의 공격을 구현할 때는 플레이어 이동을 구현할 때와 달리 서버에게 공격 요청을 보내고 서버가 공격을 허용하면 클라이언트가 공격 모션을 취하는 방식을 사용한다. 아래 그림은 PlayerA가 공격을 하는 상황을 나타낸 그림이며 PlayerA가 받는 OK응답에도 애니메이션을 재생하라는 정보가 포함되어 있다. <img src="http
[게임 서버] 플레이어 이동
플레이어 이동 이동기능을 구현할 때 나의 이동방식과 다른 사람의 이동방식은 비슷하지만 다른 사람의 이동방식은 서버의 정보를 바탕으로 움직인다는 것이 다른점이다. 만약, 싱글게임을 먼저 구현한 후 멀티게임으로 이식하는 과정을 거친다면 플레이어 이동을 구현하기 위해 가장 먼저 해야할 일은 나와 다른 플레이어를 구분하는 것이다. 내 플레이어의 이동방식은 주로 사용자의 입력값이다. 게임의 종류에 따라 다르겠지만 FPS의 경우는 WASD일 것이고 RPG인 경우는 마우스, 방향기가 이동을 위한 입력값이 될 것이다. 1. 패킷 이동을 위한 패킷을 설계할 때는 플레이어의 정보와 위치 정보를 분리 시키는 방법이 있다. 이동패킷은 총 두 종류로 클라이언트가 서버에게, 서버가 클라이언트에게 보내는 패킷이 존재한다. 클라이언트 --> 서버 클라이언트가 서버로 보내는 패킷은 '내가 [X,Y]로 이동함'을 의미한다. 그렇기 때문에 패킷에 포함
[게임 서버] 게임 입장
게임입장 한 플레이어가 게임에 입장할 때 클라이언트와 서버 사이에는 입장요청부터 다른 플레이어의 정보까지 여러가지 정보를 주고받는다. 새로운 플레이어가 게임에 입장하는 상황을 나타낸 그림은 아래와 같다. New Player는 서버에 게임에 입장한다는 요청을 보낸다. 서버는 기존에 있던 Player들에게 새로운 플레이어가 입장했다는 사실과 New Player에 대한 정보를 전송한다. New Player는 기존에 있던 Player의 정보들을 받는데 서버가 가지고 있는 Player Info를 받는다. New Player가 정보를 받는 상황을 나타낸 그림은 아래와 같다. <p align="