
TileMap 기초 + TileMap Layer

갈 수 없는 영역 세팅 Tilemap Collider 2D 컴포넌트를 추가하면 자동으로 스프라이트마다 collider 영역을 정해주는데 상황에 맞게 영역을 조정하는데 한계가 있기 때문에 해당 컴포넌트를 쓰기 보다는 레이어를 하나 더 만들어서 직접 충돌 영역을 정해주는게 좋다고 한다. 해당 강의에서는 rock 스프라이트를 이용해 갈 수 없는 영역이라는 것...

맵툴 유니티에서 예약된 폴더인 Editor를 생성하고 MapEditor.cs을 생성한다. MapEditor에서 작성될 코드는 개발 중에만 컴파일되어야 하기 때문에 다음과 같이 UNITY_EDITOR로 감싸준다. 간단한 예제 위 코드는 유니티 에디터의 메뉴에 Item을 추가하고 사용자가 버튼을 누르면 다이얼로그가 생성되도록 하며 "응"을 선택한다면 tr...

플레이어 이동 플레이어를 소수점 단위로 연산해서 이동시키면 이동할 때마다 플레이어가 인접 영역에서 못가는 영역이 있는지 체크해줘야 해서 서버쪽 컴퓨터에 부하가 심해진다. 따라서 유닛 단위로 플레이어를 움직이되 툭툭 끊기는 모습이 아닌 자연스럽게 이동하는 것처럼 보이게 해보자 Grid grid 변수는 임시로 유니티 상에서 Grid 컴포넌트를 가지고 있는 ...

세팅 먼저 Player에 Animator 컴포넌트를 추가하고 Animator Controller를 Resources->Animations->Player 폴더에 추가한 후 Animator 컴포넌트에 등록해준다. 그리고 Tiny RPG Forest -> Artwork -> sprites -> hero에 있는 애니메이션의 Pixels per unit을 20으로...

수정사항 PlayerController에서 Grid를 public으로 둬서 유니티 에디터에서 직접 드래그 앤 드롭으로 그리드를 등록해주었었는데 MapManager라는 새로운 클래스를 만들고 그 안에서 Grid 컴포넌트를 생성하고 어디서든 필요한 곳에서 쓸 수 있도록 Managers 클래스에서 Contents region에서 등록을 해주었다. Collis...
CreatureController 생성 적 캐릭터를 하나 생성하고 MonsterController를 붙여주었다. 따라서 공통된 부분은 부모클래스로 올려주는 등 코드 정리를 수행하였다. 크리쳐 상태 정의 보통 초보들이 개발을 할 때 플레이어의 상태를 bool 변수를 선언하는 경향이 강하다. 현재 이동하는 중인지, 점프 상태인지, 시네마틱 영상을 보고 있는...
맵 Creature 관리 맵 상에 존재하는 크리쳐(몬스터, 플레이어 등)들도 플레이어가 갈 수 있는 곳에 존재하는지 체크하기 위해 ObjectManager클래스를 만들고 그 안에 List 자료구조를 사용해 넣어주었다. 이렇게 하면 CreatureController의 UpdateMoving() 함수에서 갈 수 있는지 여부를 판단하기 위해 코드를 추가로 넣...
스킬 쓰는 동안 플레이어 움직임 제한 위 코드에서 플레이어가 Idle인 상태에서 방향을 업데이트하고 GetIdleInput() 함수를 호출하여 코루틴 함수를 호출시켜준다. 만약 플레이어의 State가 Idle인 상태에서 스페이스바를 누르면 State를 Skill로 바꿔주고 (CreatureController::UpdateController의 switch ...
목표 화살은 움직이기도 하고 어떤 물체에 닿으면 사라지며 데미지를 입히는 효과를 적용시켜야 하기 때문에 컨트롤러가 필요하다. 그래서 ArrowController를 만들고 Arrow 스프라이트에 붙여주었다. UpdateAnimation() 함수 재정의 CreatureController에서 가상함수로 정의된 UpdateAnimation이 있었다. 플레이어...
화살을 맞으면 사망 이펙트 화살을 맞은 적이 바로 사망 이펙트를 재생하도록 만들어보자 소멸 이펙트가 있는 스프라이트 중 첫번째 모션을 가져와서 Animator 컴포넌트를 붙인다. (Sprite Renderer의 order in layer는 높은 숫자로) Animator controller를 만들고 소멸 이펙트를 전부 드래그 앱 드롭해서 붙여주고 Reso...
코드 몬스터가 생성되고 CreatureState가 Idle일 때 코루틴 함수 CoPatrol이 실행되고 _coPatrol에 코루틴이 반환된다. 그러면 1~4초 마다 for문의 로직이 실행되는데 현재 위치에서 x,y 각각 -5~6이 더해진 위치가 갈 수 있는지 여부를 체크하고 만약 갈 수 있으면 도착 위치를 갱신하고 yield break 명령어를 통해 코루...

주변 플레이어 검색 ObjectManager MonsterController 몬스터가 플레이어를 찾기 위해 CoSearch() 코루틴 함수를 만들고 1초마다 검색하도록 한다. 플레이어를 찾기 위해 GameObject 타입의 _target 변수를 선언해주고 아직 타겟을 찾지 못했으면 ObjectManager의 Find()함수를 호출해주는데 매개변수는 G...

Protoc 깃허브 링크 구글 튜토리얼 배치파일 만들기 이전 시간에서 GenPacket.bat을 만든 것처럼 GenProto.bat을 만들어 줄 것이다. 이전에 PDL를 만들어준 것처럼 Protocol.proto를 protoc.exe가 있는 폴더에 넣어줘야 한다. 구글 문서에 안내한대로 다음과 같이 example 코드를 작성했다. GenProto...

코드 수정 지난 시간에 sendBuffer를 만들어서 클라 측으로 보냈던 코드를 Send() 함수를 새로 정의해서 그 안에 옮겨놓았다. Server::ClientSession ServerCore의 보안 유니티 프로젝트의 Assets->Libs 폴더에 ServerCore.dll을 넣어두었는데 이는 ServerCore의 실제 cs 코드들이 들어있기 때문...
Protocol.proto 수정 플레이어 입장 EnterGame() S_EnterGame 패킷을 만들고 새로 들어온 플레이어의 정보를 넣어준 후 새로 들어온 플레이어 입장에서 패킷을 서버로 보내준다. 그리고 SSpawn 패킷을 만들고 현재 GameRoom에 참가 중인 자신을 제외한 모든 플레이어들을 뽑아와서 spawnPacket 내부에 Players ...
내가 조종하는 플레이어 분리 PlayerController 하나만 만들고 Player 프리팹에 컴포넌트를 추가하는 식으로 구현을 했었다. 싱글 플레이에서는 상관없지만 그 안에 키보드 입력을 받는 코드가 들어있기 때문에 멀티 플레이에서 문제가 될 수 있다. 즉 내가 위로 가는 버튼을 눌렀는데 그 맵에 존재하는 플레이어 전부가 영향을 받아버리는 것이다. 따...
이동 동기화를 구현하는 방법은 두 가지가 있다. 클라이언트에서 이동한다는 요청을 서버에 보내고 서버의 응답을 기다린 후 움직이는 방법. 일반적인 MMORPG에서 많이 사용된다. 하지만 서버의 응답을 기다려야 하기 때문에 렉이 걸릴 수 있다. 먼저 플레이어가 이동하고 서버에 통보하는 방식. 뒤늦게 통보받은 서버가 다른 클라들에게 이동 패킷을 뿌려주는 방식...
이동 패킷 서버로 전송 MyPlayerController NetworkManager ServerSession MyPlayerController에서 현재 플레이어의 상태 또는 위치가 변경되었다면 이동 패킷을 만들고 Send해준다. 그 패킷은 NetworkManager의 Send 함수로 받아와서 ServerSession의 Send로 넘어가는데 이곳에서...
버그 수정 시작하자마자 제자리 걸음을 하는 버그 벽 바로 옆에서 이동하다가 방향을 벽쪽으로 틀어버리면 다른 클라이언트에서 계속 이동하던 방향으로 이동 위 두가지 버그를 수정하고자 한다. 두번째 버그 먼저 두번째 버그는 계속 Moving 상태이면서 CellPos가 변하지 않았기 때문에 if(prevState != State || CellPos != p...
목표 이번 시간에는 스킬을 쓰면 서버와 동기화를 시켜서 다른 플레이어에게도 보이게 작업을 해보자. 구현 스킬 같은 경우는 이동과는 달리 가끔 사용하는 것이기 때문에 클라이언트에서 먼저 선처리를 해줄 이유가 없다. 스페이스바를 누르면 서버 쪽에 스킬을 썼다는 패킷을 보내게 되는데 서버쪽에서 검증을 한 후 주변 플레이어들에게 브로드캐스팅을 해주는 방식으로...
스킬 서버 연동 PacketHandler PlayerController MyPlayerController 먼저 클라이언트에서 스페이스 바를 누르면 스킬 패킷을 생성하고 서버로 전송한 후 코루틴 함수를 호출하여 0.2초마다 스킬 패킷을 보내도록 로직을 짜주었다. 서버에서 스킬 패킷을 받고 검증 후 해당 룸에 존재하는 모든 클라이언트 들에게 다시 브로드캐...

목표 서버 쪽에서 mapId를 알면 맵 파일을 읽어와서 collision 판단을 할 수 있도록 구현하고 어떤 좌표를 기준으로 플레이어의 존재 유무를 판단하여 스킬 hit 판정을 해보자. 맵 정보를 서버에서도 가지도록 변경 Client::MapEditor 유니티 에디터에서 Tools->GenerateMap을 클릭하면 생성되는 맵 파일 경로를 추가하였다....
Server::Map 실제 좌표를 이동하기 전에 받아온 플레이어 유효한 영역 안에 있는지, 또 가고 싶은 좌표에 갈 수는 있는지, 현재 위치가 내 위치가 맞는지 체크해서 다른 플레이어 좌표를 null로 만드는 것을 방지하고, 목적지에 도착지 좌표를 갱신한 다음, 목적지 좌표를 player의 PosInfo에 갱신하도록 하였다. Server::Player...
화살 스킬 같은 경우 클라이언트에서 화살을 생성해서 날린다고 해도 서버에서 굳이 화살 좌표를 맞춰줘야 할지 선택을 해야하는데 와우 같은 게임의 경우 A플레이어가 몬스터를 대상으로 스킬을 쓴 후 바로 다른 지역으로 이동해서 사라지더라도 B플레이어가 뒤늦게 들어왔을 때 스킬만 덩그러니 발동되는 것을 볼 수 있다. 따라서 스킬도 서버에서 어느정도 관리를 해주...
로직 분석 Client::MyPlayerController Server::PacketHandler Server::GameRoom 플레이어가 스페이스 바를 누르면 스킬 패킷을 만들어 서버로 보내주게 된다. 서버는 스킬 패킷을 클라이언트 측으로부터 받으면 C_SkillHandler에서 처리를 해주게 되는데 클라이언트가 속해있는 게임 룸의 HandleSk...

Newtonsoft.Json Server프로젝트 우클릭 후 Manage NuGet Packages 클릭. 그리고 Newtonsoft.Json 설치 분석 Protocol.proto StatData.json SkillData.json Server::Data.Contents Server::ConfigManager config.json 처음 서버를...
목표 서버에서 받아온 정보를 가지고 플레이어, 화살 등 속도를 결정하도록 함 Protocol.proto 서버에서 S_EnterGame 패킷을 클라이언트에게 보낼때 ObjectInfo를 보내는데 이곳에 StatInfo를 추가해주었다. Server::Player Server::GameObject Client::CreatureController Cl...
Protocol.proto
사망 패킷 만들기 누군가 죽었으면 누가 죽었는지, 또 누구에게 죽었는지 정보를 담는 S_Die 패킷을 하나 만들어준다. Server::GameObject Leave 패킷을 날리면 플레이어의 ObjectManager에서 모든 게임 오브젝트들을 담아놓은 것을 clear해주기 때문에, 다시 부활하여 게임 룸에 Enter할때 다시 게임룸에 존재하는 오브젝트를...
Command 패턴 ClientSession에서 온 요청을 바로 실행하는 것이 아니라 job이라는 개념으로 캡슐화한 후 나중에 처리하는 방식으로 lock을 최소화 할 수 있다. Server::Job Server::JobSerializer Push를 하면서 jobQueue에 일감을 넣어줄 수 있다. 맨 처음 jobQueue에 일감을 넣어주는 경우, _...