메모리 게임 데모

메모리 데모는 플레이어 두명이 비동기적으로 게임하는 것을 보여주는 간단한 예제로 완벽하게 동작합니다.
매치 메이킹 기능을 가지고 있으며 누구 차례인지를 "저장된 게임들"에서 보여주고 현재 참여 하고 있지 않은 플레이어에게 푸시 알림 기능을 지원 합니다.

Memory Main Menu

메모리 메인 메뉴

이 클라이언트는 Unity SDK 안에 들어 있습니다.
서버 측의 구현 내용은 비동기 게임의 구현에 참고 할 수 있습니다.
관리화면을 통하여 활성화 시킬 수 있으며 GitHub에서 소스 다운르도에서 다운로드 할 수 있습니다.

##클라이언트 준비하기

클라이언트는 이미 실행할 준비가 되어 있습니다.
MemoryDemoScene 을 로드 후 에디터에서 AppId 만 추가해주면 완료 됩니다.

무료 가입 후에 Realtime 관리화면에서 AppId 를 얻습니다.

관리화면에서 AppId 를 복사하여 MemoryDemoScene 을 오픈 합니다.
"Scripts" 게임 오브젝트를 찾아 MemoryGui 컴포넌트의 "App Id" 를 설정 해 줍니다.

MemoryGui Component

MemoryGui 컴포넌트

Realtime Dashboard "Manage" 를 클릭하여 어플리케이션 관리 페이지로 이동 합니다.

Manage Application

Realtime Dashboard 에서 보여지는 "MemoryDemo" 예제 어플리케이션

관리화면에서 AppId 를 복사 후 MemoryDemoScene 을 오픈 합니다.
"Scripts" 게임 오브젝트를 찾아서 MemoryGui 컴포넌트에 "App Id" 를 설정 합니다.

MemoryGui Component

MemoryGui Component

서버 준비하기

Realtime Dashboard 에서 "Manage"를 클릭하여 어플리케이션 관리 페이지로 이동 합니다.

Manage Application

Realtime Dashboard 에서 보여지는 "MemoryDemo" 예제 어플리케이션
그리고 아래의 Webhooks 섹션에서 "Create a new Webhook" 버튼을 이용하여 web hooks 설정을 생성 해야 합니다.

Webhooks section

설정된 webhooks 이 없는 Webhooks 섹션

드롭다운 목록에서 "WebHooks 1.2 Demo" 을 선택 합니다.
만약 나의 웹서비스가 있다면 "WebHooks 1.2" 를 선택 할 수 있습니다.
이 데모를 위해서 중요한 파라미터만 아래 스크린 샷에 표시 하였습니다.

스크린 샷에 표시된 BaseUrl 은 기본값으로 귀하의 URL 로 변경 되어야 합니다.

Webhooks 의 상세 정보는 이 페이지를 보시기 바랍니다.

Webhooks example setup

MemoryDemo의 web hooks 설정 예제

코드 살펴 보기

Memory 데모를 최대한 활용하려면 코드를 살펴봐야 합니다.
유니티 Inspector 설정은 모양과 옵션들을 정의 하지만 로직은 코드내에 있습니다.
이 데모에서 중요한 클래스들은 MemoryGui, MemoryBoard, MemoryGameClient and NamePickerGui 들 입니다.

인증

턴기반 게임에서는 사용자들이 중요한 역할을 담당 합니다:
사용자들에 대해서 게임 목록을 관리해야 하며 userID 로 접근 하는 것이 가장 좋습니다.

편의상 이 데모에서는 패스워드는 필요하지 않으며 모든 userID를 수용하고 있습니다.

Photond의 커스텀 인증 기능은 실제 사용자 계정이 진짜인지를 밝히는 데 사용 될 수 있습니다.
커스텀 인증 문서 를 더 읽어 보세요.

패키지에는 두 번째 scene 인 "CustomAuthDemo"가 포함되어 있습니다.
이 Scene 은 클라이언트에서 인증을 어떻게 구현하지는 보여 줍니다.

매치 메이킹

이 데모에서는 간단한 매치메이킹 흐름을 이용 합니다:
무작위로 룸에 참가하려다 실패했을 경우에는 새로운 룸을 생성합니다.

추가 정보는 매치메이킹과 로비에 대한 참조 문서 에 있습니다.

매치메이킹은 룸안에 최소 한명의 플레이어가 참가하고 있을 때만 작동 됩니다.
플레이어 한명으로는 할 수 있는것이 없으므로 룸의 매치메이킹 시간이 매우 짧아집니다.

GUI 요소가 매치메이킹을 위해 NewGameMsg()을 호출하고 이어서 OpJoinRandomRoom()을 호출 합니다. 다른 작업에 대한 응답처럼 이 호출에 대한 응답은 OnOperationResponse 가 호출 될 것입니다. 상황에 따라 필요시 MemoryGameClient 는 MemoryGameClient.CreateTurnbasedRoom() 로 실제 룸 생성 코드를 호출 합니다.

상태 저장

모든 게임은 명시적으로 종료하지 않는 한 나중에 다시 계속 할 수 있습니다.
클라이언트가 게임 중간에 폐쇄되거나 연결이 끊어 졌을 경우들도 포함 됩니다.

Photon Realtime은 자동적으로 버퍼화된 이벤트들, 모든 룸, 모든 플레이어 속성들을 저장 합니다.

플레이어가 룸에 다시 참여 했을 때 방에 참가하고 있었던 플레이어들의 속성(활성과 비활성)들과 버퍼에 있는 모든 이벤트를 수신 하게 됩니다.
이 데이터를 이용하여 상태를 재생하고 플레이를 계속 할 수 있습니다.

메모리 게임에서는 보드의 타일 정보를 추적 관리 합니다.

Memory Board

Memory Board

캐시된 이벤트

룸 내의 액티브 플레이어에게 이벤트를 보낼 뿐 만 아니라, 참여 또는 "복귀"하는 플레이어를 위해 의도적으로 이벤트를 캐시 할 수 있습니다. 룸은 이벤트 도착 순서에 따라 이벤트를 캐시하고 참여한 플레이어들이 "라이브" 이벤트를 수신 전에 캐시된 이벤트를 전송합니다.

Photon Realtime에서는 캐시된 이벤트들을 저장하여 나중에 게임에 다시 참가하는 플레이어에게 언제 든지 전송하게 됩니다.

이 데모에서는 캐시된 이벤트를 사용하지 않지만 아래의 코드에서 어떻게 OpRaiseEvent 호출 하는지 볼 수 있습니다:

C#

public void CachedRaiseEvent(byte evCode, object content)
{
    // the content can be anything Photon-serializable. Most often a Hashtable is used.
    RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.AddToRoomCache };
    this.OpRaiseEvent(evCode, content, true, options);  // cached events should be sent reliable
}  

일반적으로 턴 기반 게임에서 저장된 이벤트들은 OnEvent() 가 호출시 코드에 전달 됩니다.
만약 장기간의 턴이 필요하지 않으면(리플레이를 위하여) 사용되지 않는 이벤트 캐시를 삭제하여 게임 로딩 속도를 향상 시켜야 합니다.
CachingOption 을 EventCaching.RemoveFromRoomCache 로 설정 후 OpRaiseEvent 를 다시 호출하여 수행됩니다.

프로퍼티

메모리 게임은 룸 프로퍼티 집합으로 완전한 게임 상태를 저장 합니다.
프로퍼티는 자주 변하지 않고 현재의 값 만을 저장 할 때 매우 유용하게 사용 됩니다.

최고로 좋은 방식은 룸 프로퍼티 들 중 일부를 선별하여 "saved games" 리스트에서 이용 할 수 있도록 하는 것입니다.

Photon Realtime에서는 모든 플레이어들이 비활성 되었을 때 모든 프로퍼티들이 저장 됩니다.
관리화면 에서 "IsPersistent" 를 "true" 로 설정 하였기 때문 입니다.

이 데모에서는 tile id 의 문자열 키로 개별 타일에 대한 프로퍼티를 저장 합니다.
이렇게 하면 각 타일이 개별적으로 갱신 될 수 있습니다.
데모에서는 턴이 끝날 때 마다 모든 게임의 상태가 항상 저장 됩니다.

메모리 게임의 중요한 요소는 타일이 일치하지 않은 경우에 상대방이 뒤집은 타일을 볼 수 있다는 것입니다.

이것을 구현하기 위해서 플레이어들이 타일을 뒤집었을 때 턴을 넘기지 않아야 합니다.
대신, 두 개의 뒤집혀진 타일을 저장하고 뒤집혀진 것을 제외한 타일을 선택하도록 해야 합니다.
상대방은 타일들을 보아야 하고 준비가 되면 턴을 내줍니다.

점수 및 턴수 또한 저장된 프로퍼티들의 일부 입니다.
MemoryGameClient.cs 소스에서 SaveBoardToPropertiesLoadBoardFromProperties를 확인 해 보세요.

저장된 게임

Photon Realtime 은 각 룸의 상태 뿐만 아니라 각 사용자의 게임 리스트도 저장합니다.
사용자가 만약 고정된 계정으로 로그인 하였다면 사용자가 단말을 변경 하여도 게임리스트를 사용할 수 있습니다.

저장된 게임 얻기

클라이언트는 WebRPC 호출을 통하여 저장된 게임 목록에 접근 합니다.
WebRPCs 는 귀하의 웹 서비스에 의하여 실행되는 단순한 오퍼레이션 입니다.

WebRPCs는 클라이언트에서 호출 하기 매우 쉽습니다:

C#

    Dictionary<string, object>() jsonParameters = new Dictionary<string, object>();
    this.GameClientInstance.OpWebRpc("GetGameList", jsonParameters);

Photon 은 Webhooks 용으로 설정Base Path 를 사용하며 끝에 "GetGameList" 가 추가됩니다.

물론 Base Path로 설정된 이 서버는 이 패스 상에서 플레이어 마다 게임 리스트를 제공해야 합니다.

이 경우에 jsonParameters 딕셔너리는 실제로 필요하지는 않지만 필요에 의해서 웹 서버로 어떻게 파라미터를 전달하는지 보여주고 있습니다.
Photon 은 자동적으로 사용자 정보(UserID 와 같은)를 웹 서비스에게 제공 합니다.

리턴 된 저장 게임 목록에는 플레이어가 다시 참여 할 수 있는 룸의 이름이 들어 있습니다.
서버는 각각의 룸 안에서 사용자가 가지고 있었던 actorNumber 도 전송 합니다.
마지막으로 로비에서 이용할 수 있는 룸 프로퍼티 목록을 제공하는 경우 기본적인 구현 안에 있는 GetGameList 에 의하여 전송 됩니다.

MemoryGameClient 는 List<SaveGameInfo> SavedGames 로 변환하여 룸의 목록을 표시합니다.
이 데모에서는 게임마다 누가 할 차례이고 게임에서 어떤 역할을 하는지 알 수 있도록 충분한 데이터를 전송합니다.
여기에서 룸 이름은 중요하지 않습니다.

참고: 전송되는 데이터를 최소화 하여 플레이어의 부담을 줄여 주시기 바랍니다.

저장된 게임 열기

플레이어는 "OpJoinRoom"을 통하여 저장된 게임에 되돌아 올 수 있습니다.
플레이어가 알아야 하는 것은 오픈 할 룸의 이름과 그 방에 있었을 때 가지고 있었던 플레이어 번호입니다.
MemoryGui.LoadGameMsg() 에서 수행 됩니다.

C#

    this.GameClientInstance.OpJoinRoom(roomName, actorNumber);

roomName 은 'OpJoinRoom' 에서 참여하려는 룸의 이름을 정의 합니다. actorNumber 는 플레이어 목록에서의 플레이어 특정 스폿을 대신 합니다.

푸시 알림

알림 서비스로는 PushWoosh 가 좋습니다.
예로 SDK에 PushWoosh 의 안드로이드용 클라이언트 라이브러리가 포함되어 있습니다.

Photon 에서는 게임의 멀티플레이어/네트워킹에 초점을 맞추고 있습니다. 기존의 기능을 모두 구현하는 것이 아니라 필요에 따라 타사의 서비스를 이용하기로 의사결정을 했으며 그 중의 하나가 푸시알림 입니다.

일반적으로 Remote API (실제 푸시 전송)가 웹 서비스에 구현 됩니다. 클라이언트는 필요에 따라 푸시를 트리거하는 방법과 서버에 누가 푸시 했는지 알려 주는 방법이 필요합니다. 클라이언트는 현재 다음 두개 태그(UID2 와 AppId)를 설정하여 각 사용자를 개별적으로 타켓을 하도록 합니다.
이 두가지를 통하여 하나의 앱에서 사용자를 식별 합니다.

푸시를 트리거 하기 위하여 요구할 때 (턴이 종료) "web forward" 로 SetProperties 를 사용하기로 결정 하였습니다.
이것은 "turn" 을 찾는 새로운 룸 프로퍼티를 웹 서비스로 포워드 해줍니다.
"turn" 에는 푸시를 받는 플레이어의 ID가 포함 되어 있습니다.
웹서비스는 관련된 userID 를 찾아서 "UID2" 와 AppId 를 이용하여 직접 푸시를 보냅니다.

웹 서비스에서 각 사용자의 PushWoosh Device ID를 저장 할 때 태그를 이용하는 방법이 있습니다.
또는 그 deviceId를 각 방에 보낼 수 있습니다 (플레이어 프로퍼티로).

또는 다른 방식으로 할 수 도 있습니다.

확장 해야 할 것들

이 데모는 아직 완벽하지 않습니다.
이 중에서 조정하고 싶은 것을 시도 해 보세요...

  • 이 게임은 Webhooks가 설정 되지 않은 것을 인지 하지 못합니다.
    참고 사항을 보여 주어야 합니다.
  • 연결이 끊어 졌을 때 시각적인 피드백이 없습니다.
  • 대기 하고 있을 때 상대 플레이어가 활성상태인지 아닌지에 대해서 보여 주세요.
  • 몇명이 온라인 상태인지 보여 주세요.
  • ...

게임을 즐겨 보세요!

Back to top