언리얼 엔진 - 네트워크 Player Index 실습

ThirdPerson 튜토리얼을 실행한다.

그리고 2명이상의 플레이어는 Listen Server로 게임 구동 시 캐릭터가 플레이어수**2 제곱만큼 인스턴스를 생성한다. (3명인 경우 9개 캐릭터 인스턴스가 있음)

3명의 플레이시 각각의 인스턴스

Server          Client1         Client2
+-------------+ +-------------+ +-------------+
| +---------+ | | +---------+ | | +---------+ |
| | server  | | | | server  | | | | server  | |
| +---------+ | | +---------+ | | +---------+ |
|             | |             | |             |
| +---------+ | | +---------+ | | +---------+ |
| | client1 | | | | client1 | | | | client1 | | 
| +---------+ | | +---------+ | | +---------+ |
|             | |             | |             |
| +---------+ | | +---------+ | | +---------+ |
| | client2 | | | | client2 | | | | client2 | |
| +---------+ | | +---------+ | | +---------+ |
+-------------+ +-------------+ +-------------+

싱글게임에서는 이러한 클래스 관리가 필요 없었으나, 멀티게임에서는 누구로 선택할 때에는 예상치 못한 개발 사항이 생긴다.

게임모드에서 자주 관리하는 클래스는 다음과 같다.

게임모드

  • Default Pawn Class
    • 컨트롤하고 아바타 되는 폰 클래스
  • Player Controller Class
    • 마우스, 키보드, 조이스틱 인풋 클래스 용도로 사용
    • 네트워크 통신과 관련된 코드로 활용함
  • Player State Class
    • Pawn 클래스보다 생명주기가 길다.
    • Pawn 클래스에 사용할 수 없는 지속형 변수를 관리할 수 있다.

Character 블루프린트

이미 생성된 BP_ThirdPersonCharacter 블루프린트는 Parent class가 Character 일 뿐 아니라 Pawn에게 상속 받고 있다.

신규로 노드를 추가하자.

  • Game > Get Player Controller 노드
  • Game > Get Player Pawn 노드
  • Game > Get Player Character 노드

Player Index 로 0번 플레이어의 정보를 가져와 조회하는 노드이다.
Pawn 노드가 Character, Controller 캐스팅으로 서로의 정보를 조회할 수 있다.

스태틱이나 싱글턴을 이용하듯 싱글게임에서는 자유롭게 사용했으나, Listen Server, Dedicated Server 에서 잘못 사용하면 블루프린트가 없는 것처럼 동작하기도 하다.

Listen Server 다행히 이 노드들을 사용 가능한데, 0번 대상이 서버이자 로컬플레이어로 직접 조종하므로 서버는 잘 동작한다. 하지만 클라이언트 입장이 되는 플레이어는 동작하지 않는 상황이 발생할 수 있으므로 클래스 관계를 잘 살펴봐야한다.

처음 접속하는 사용자에게 초기화 용도로 사용하고 0번 인덱스만 사용하는 하드코드이므로 확장이 필요한 코드를 작성에는 사용해서는 안된다.


Player Index 노드 대체하기

그렇다면 앞에서 설명한 Player Index 로 사용하는 노드 말고 어떤 노드를 사용해야할까?

다른 클래스의 정보를 갖고 오는 것은 불편한 작업이다. 싱글게임은 Player Index 편리하게 이용할 수 있었으나, 이제는 정석대로 사용해야 한다.

자신의 블루프린트 부모 클래스가 Character 인 경우

  • Pawn > Get Controller 노드 추가

노드 Input 핀이 Target(Self) 로 되어있다. 이는 블루프린트 자신의 상속에서 찾아 노드를 추가할 수 있다. 노드의 Getter 호출하고 캐스트를 해주어야한다.

Get Controller 로 자신의 컨트롤러를 가져와 Player Controller 캐스트하고 PlayerController 에서 사용하는 변수와 멤버함수들을 호출해 사용한다.

보다시피 노드의 Target(Self) 인풋으로 사용하므로 자신의 클래스 관계를 알고 있어야한다.


Role

게임 구동시 생성되는 플레이어의 인스턴스 에서 본인이 조종하는 Pawn, Controller 를 필요한 상황이 있다.

예를 들어, UI 코드같이 무관한 코드나 블루프린트에서 Player Controller 를 사용하거나 본인의 로컬로 조종하는 Pawn, Player Character 가 필요할 수 있다.

ENetRole 에뮬레이터를 사용해 로컬의 인스턴스를 찾을 수 있다.

Role 관련 함수

  • GetLocalRole
  • GetRemoteRole

ENetRole 종류

  • None
  • Autonomous Proxy
  • Simulated Proxy
  • Authority

세부적으로 상대방을 찾을 수 있다.

또는 오로지 자신의 로컬 컨트롤러를 찾겠다면 IsLocallyController 같은 함수도 이용 할 수 있다.

  • IsLocallyController
    • 자신의 컨트롤러인지 반환한다.
  • 각자 자신의 로컬 플레이어를 찾아내 화면에 메시지로 뿌려준다.