개인 학습용으로 번역을 했으며, 파파고와 구글번역을 많이 사용했습니다. 

Google Play Games plugin for Unity

유니티용 구글 플레이 게임 플러그인

Copyright (c) 2014 Google Inc. All rights reserved.

구글에게 저작권이 있습니다..

 

The Google Play Games plugin for Unity® is an open-source project whose goal is to provide a plugin that allows game developers to integrate with the Google Play Games API from a game written in Unity®.

이 유니티용 구글 플레이 게임 플러그인은 오픈소스 프로젝트다. 프로젝트의 목적은 플러그인 제공입니다. 플러그인은 게임 개발자가 유니티로 작성한 게임에 구글 플레이 게임즈 API를 통합할 수 있게합니다.

However, this project is not in any way endorsed or supervised by Unity Technologies.

그러나, 이 프로젝트는 어떤식으로든 유니티로부터 관리되거나 지원되지 않습니다.

 

Unity® is a trademark of Unity Technologies.

Unity®은 Unity Technologies의 상표입니다.

 

iOS is a trademark of Apple, Inc.

iOS는 애플사의 상표입니다.

 

Overview 개요

The Google Play Games plugin for Unity allows you to access the Google Play Games API through Unity's social interface.

이 유니티용 구글 플레이 게임 플러그인은 유니티의 소셜 인터페이스를 통해서 구글 플레이 게임 API에 접근할 수 있게 합니다.

The plugin provides support for the following features of the Google Play Games API:

이 플러그인은 구글 플레이 게임 API의 아래와 같은 기능을 지원합니다.

 

  • sign in
  • 로그인
  • unlock/reveal/increment achievement
  • 업적 해제, 업적 공개, 업적 증가
  • post score to leaderboard
  • 리더보드에 점수 게시
  • cloud save read/write
  • 클라우드 저장 읽고 쓰기
  • show built-in achievement/leaderboards UI
  • 기본 제공 성과/리더보드 UI 보여주기
  • events
  • 이벤트
  • video recording of gameplay
  • 게임 녹화
  • nearby connections
  • turn-based multiplayer
  • real-time multiplayer

NOTICE: This version of the plugin no longer supports iOS.

주의: 이버전은 더이상 IOS를 지원하지 않습니다. 

Google Play games services for iOS is deprecated, and is not likely to function as expected.

IOS용 구글 플레이 게임 서비스는 더이상 지원되지 않습니다. 그리고 예상대로 작동하지 않을 가능성이 있습니다.

Do not use Google Play games services for iOS in new apps.

새로운 앱에서 IOS용 구글 플레이 게임 서비스를 사용하지 마세요.

See the deprecation announcement blog post for more details.

자세한 사항은 지원 중단 발표 포스트에서 확인하세요.

 

Features:

특징:

  • easy GUI-oriented project setup (integrated into the Unity GUI)
  • 쉬운 GUI기반 프로젝트 설정 (유니티 GUI에 통합되었습니다)
  • no need to override/customize the player Activity
  • 플레이어 활동을 재정의 하거나 커스터마이즈할 필요가 없습니다.
  • no need to override/customize AndroidManifest.xml
  • AndroidManifest.xml를 재정의 하거나 커스터마이즈할 필요가 없습니다.

System requirements:

시스템 요구사항:

  • Unity® 5 or above.

  • 유니티5 이상
  • To deploy on Android:

  • 안드로이드에 배포하기 위해
    • Android SDK
    • 안드로이드 SDK 필요
    • Android v4.0 or higher
    • 안드로이드 버전 4 이상
    • Google Play Services library, version 11.6 or above
    • 구글 플레이 서비스 라이브러리 버전 11.6 이상

Upgrading 업그레이드

 

If you have already integrated your project with a previous version of the plugin and wish to upgrade to a new version, please refer to the upgrade instructions.

만약 당신이 프로젝트에 이전 버전의 플러그인을 이미 통합했지만 새로운 버전으로 업그레이드하길 원한다면 업그레이드 안내서를 참고하세요.

Configure Your Game 게임 설정하기

 

To use the plugin, you must first configure your game in the Google Play Developer Console.

플러그인을 사용하기 위해서, 당신은 먼저 구글 플레이 개발자 콘솔에서 당신의 게임 환경을 설정 해야합니다.

Follow the instructions on creating a client ID.

클라이언트 ID 생성에 관한 안내를 따르세요.

Be particularly careful when entering your package name and your certificate fingerprints, since mistakes on those screens can be difficult to recover from.

당신의 패키지 이름과 당신의 인증서 지문을 입력할 때 특별히 주의하세요. 이러한 실수들은 복구하기 어려울 수 있습니다.

 

Copy the game resources from the console

콘솔로부터 게임 리소스들을 복사하세요.

 

Once you configure at least one resource (event, achievement, or leaderboard), copy the resource configuration from the Google Play Developer Console, and paste it into the setup configuration in Unity.

일단 당신이 하나 이상의 리소스(이벤트, 업적, 리더보드)를 구성하면, 리소스 구성을 구글 플레이 개발자 콘솔에서 복사하세요. 그리고 유니티의 설정 구성에 이것을 붙여 넣으세요.

To get the resources go to the Achievements tab, then click on "Get resources" on the bottom of the list.

자원을 얻으려면 업적 탭으로 가서, 목록 아래의 리소스 얻기를 누르세요.

Then click the "Android section".

그 다음 안드로이드 영역을 누르세요.

Select all the contents of the resources window, and copy them to the clipboard.

리소스 창의 모든 내용을 선택하고 클립보드에 복사하세요.

 

Paste the game resources into the plugin setup dialog

게임 리소스들을 플러그인 설정 다이얼로그에 붙여넣으세요.

 

Back in Unity, open the setup dialog Window > Google Play Games > Setup... > Android Setup

유니티로 돌아가서, 설정 다이얼로그를 여세요.

  • Enter the directory to save constants - Enter the folder for the constants file.
  • 상수들을 저장할 디렉터리를 입력하세요 - 상수 파일을 위한 폴더를 입력하세요.
  • Constants class name - this is the name of the C# class to create, including namespace.
  • 상수 클래스 이름 -  이것은 만들 C# 클래스의 이름입니다.
  • Resources Definition - paste the resource data from the Play Games console here.
  • 리소스 정의 - 플레이 게임 콘솔에서 가져온 리소스 데이터를 여기에 붙여넣으세요.
  • Web client ID - this is the client ID of the linked web app. It is only needed if you have a web-based backend for your game and need a server auth code to be exchanged for an access token by the backend server, or if you need an id token for the player to make other, non-game, API calls.
  • 웹 클라이언트 ID - 이것은 연결된 웹 앱의 클라이언트 아이디입니다. 이건 당신이 게임을 위한 웹기반 백엔드를 가지고 있고 백엔드 서버와 엑세스 토큰을 교환하기 위한 서버 인증 코드가 필요한 경우, 또는 당신이 게임 외의 다른 API호출을 만드는 경우에 필요합니다.

The setup process will configure your game with the client id and generate a C# class that contains constants for each of your resources.

이 설정 과정은 클라이언트 아이디로 게임을 구성하고, 각 리소스의 상수를 포함하는 C#클래스를 생성합니다.

Setup Checklist 설정 체크리스트

 

Make sure to do the following if they are relevant to your game:

당신 게임과 관련이 있는경우 다음 작업을 수행하세요.

 

1. Add tester email addresses to the testing section of your game on the Play Games Console.

1. 당신의 플레이 게임 콘솔 테스팅 영역에 테스터 이메일 주소를 입력하세요.

2. The SHA1 fingerprint used to create the linked Android app is from the keystore used to sign the Unity application.

2. 연결된 안드로이드 앱을 만들기 위해 사용된 SHA1 지문은 유니티 앱에 서명하는데 사용되는 키스토어로부터 왔습니다.

 

Add Achievements and Leaderboards

업적과 리더보드 추가

 

Add achievements and leaderboards to your game in the Google Play Developer Console.

구글 플레이 개발자 콘솔에 있는 당신의 게임에 업적과 리더보드를 추가하세요.

For each achievement and leaderboard you configure, make sure to note the corresponding achievement ID or leaderboard ID, as those will be needed when making the API calls.

구성하는 업적과 리더보드를 위해, 업적 ID나 리더보드 ID를 적어두세요. 이것들은 API 호출을 작성할 때 필요합니다.

Achievement and leaderboard IDs are alphanumeric strings (e.g. "Cgkx9eiuwi8_AQ").

업적, 리더보드 아이디는 영문과 숫자의 조합으로 이루어져 있습니다.

 

Add Events

이벤트 추가

 

Events allow you to track user actions in your game and report on them with Analytics.

이벤트는 당신이 게임 속 유저의 활동을 추적할 수 있게 해줍니다. 그리고 그것들의 분석 자료를 만들 수 있게 해줍니다.

Read more about how to configure and use Events on Game Concepts - Events

이벤트를 어떻게 설정하고 사용하는지는 게임 개념의 이벤트 에서 확인하세요.

 

Load Your Game Project

당신의 게임 프로젝트 불러오기

 

Next, load your game project into the Unity editor.

다음, 유니티에디터에서 당신의 게임프로젝트를 불러오세요.

 

If you do not have a game project to work with, you can use the Minimal sample available in the samples directory.

당신이 작업할 게임프로젝트가 없다면, 샘플 디렉터리에서 사용가능한 작은 샘플을 사용할 수 있습니다.

Using that sample will allow you to quickly test your setup and make sure you can access the API.

이 샘플을 사용해서 당신은 빠르게 설정을 테스트할 수 있고, API에 접근할 수 있습니다.

 

If you want to test a larger sample after you are familiar with the plugin, try the CubicPilot game.

당신이 플러그인에 익숙해진 뒤 큰 샘플에서 테스트하기 원한다면, CubicPilot 게임을 사용하세요.

More information about building the samples can be found in the samples README file.

샘플 빌드에 대한 더많은 정보는 샘플 README 파일에 있습니다.

 

Plugin Installation

플러그인 설치

 

To download the plugin, clone this Git repository into your file system (or download it as a ZIP file and unpack it).

플러그인을 다운로드하기 위해, 당신의 파일 시스템에 Git 저장소를 클론하세요(혹은 압축파일을 받아 압축해제하세요)

Then, look for the unitypackage file in the current-build directory:

그리고, current-build 디렉토리에서 unitypackage파일을 찾으세요

current-build/GooglePlayGamesPluginForUnity-X.YY.ZZ.unitypackage

To install the plugin, simply open your game project in Unity and import that file into your project's assets, as you would any other Unity package.

플러그인을 설치하기 위해서, 유니티에서 당신의 게임 프로젝트를 불러오고 저 파일을 당신의 프로젝트 에셋에 임포트 하세요. 다른 유니티 패키지처럼 임포트하면 됩니다.

This is accomplished through the Assets > Import Package > Custom Package menu item (you can also reach this menu it by right-clicking the Assets folder).

Assets > Import Package > Custom Package을 이용해 임포트 하면 됩니다. (당신은 이 메뉴를 에셋폴더에 우클릭해서 접근할 수도 있습니다.)

Next, make sure your current build platform is set to Android.

다음, 현재 빌드 플랫폼이 안드로이드로 되어있는지 확인하세요.

From File > Build Settings… select Android and click Switch Platform.

File > Build Settings에서 안드로이드를 선택하고 Switch Platform을 누르세요.

You should now see a new menu item was added under Window > Google Play Games.

이제 당신은 Window > Google Play Games에 새 메뉴 아이템이 추가된걸 확인할 수 있습니다.

If you don't see the new menu items, refresh the assets by clicking Assets > Refresh and try again.

이 새로운 메뉴 아이템을 확인할 수 없다면, Assets > Refresh 를 눌러 에셋을 새로고침하고 다시 시도해보세요.

Android Setup

안드로이드 설정

 

Next, set up the path to your Android SDK installation in Unity.

다음, 안드로이드 SDK가 설치 경로를 유니티에 설정하세요.

This is located in the preferences menu, under the External Tools section.

이것은 환경설정 메뉴의 External Tools 아래에 있습니다.

 

To configure your Unity game to run with Google Play Games on Android, first open the Android SDK manager and verify that you have downloaded the following packages.

당신의 유니티 게임을 안드로이드에서 구글 플레이 게임즈와 함께 실행시키기 위해 설정하려면, 먼저 안드로이드 SDK매니저를 열고 다음과 같은 패키지를 다운로드 했는지 확인하세요.

Depending on if you are using the SDK manager from Android Studio, or using the standalone SDK manager, the name of the components may be different.

안드로이드 스튜디오의 SDK매니저를 사용하는지, 독립형 SDK 매니저를 사용하는지에 따라 컴포넌트의 이름이 다를 수 있습니다.

 

  • Google Play Services
  • 구글 플레이 서비스
  • Android Support Library
  • 안드로이드 지원 라이브러리
  • Local Maven repository for Support Libraries (Also known as Android Support Repository)
  • 지원 라이브러리를 위한 로컬 메이븐 저장소 (안드로이드 지원 저장소로도 불린다.)
  • Google Repository
  • 구글 저장소
  • Android 6.0 (API 23) (this does not affect the min SDK version).
  • 안드로이드 6.0 (최소 SDK버전에는 이것이 영향을 주지 않습니다.)

Next, configure your game's package name.

그 다음, 당신 게임의 패키지 이름을 구성하세요.

To do this, click File > Build Settings, select the Android platform and click Player Settings to show Unity's Player Settings window.

구성하기 위해서 File > Build Settings을 클릭하고 안드로이드 플랫폼을 선택한 뒤 유니티의 플레이어 세팅 창을 보기위해 Player Settings를 누르세요.

In that window, look for the Bundle Identifier setting under Other Settings.

이 창에서, Other Settings 아래 Bundle Identifier을 찾으세요.      

Enter your package name there (for example com.example.my.awesome.game).

그곳에 당신의 패키지 이름을 넣으세요.

 

In order to sign in to Play Game Services, you need to sign your APK file, make sure that you are signing it with the correct certificate, that is, the one that corresponds to the SHA1 certificate fingerprint you entered in the Developer Console during the setup.

플레이 게임 서비스에 로그인하기 위해서, 당신은 당신의 APK에 서명해야 합니다. 당신이 올바른 인증서로 서명하고 있는지 확인해야한다. 올바른 인증서란 설정 중에 개발자 콘솔에 입력된 SHA1인증서 지문을 말한다.

 

Next, click the Window |Google Play Games|Setup - Android setup menu item.

그 다음, Window |Google Play Games|Setup - Android setup 메뉴 아이템을 누르세요. 

This will display the Android setup screen.

그러면 안드로이드 설정 화면이 보일 것 입니다.

 

Enter the Constants class name.

상수 클래스 이름을 입력하세요.

This is the name of the fully qualified class that will be updated (or created) which contains the IDs of the game resources.

이것은 충분한 권한을 가진 클래스의 이름입니다. 게임 리소스의 아이디가 포함된 이 클래스는 업데이트되거나 혹은 생성 될 것입니다.

The format of the name is .. For example, AwesomeGame.GPGSIds

그 이름의 형식은 다음과 같습니다. AwesomeGame.GPGSIds

 

Paste the resource definition data.

리소스 정의 데이터를 붙여넣으세요.

This is the XML data from the Google Play Developer Console which contains the resource IDs as well as the Application ID for Android.

이것은 XML 데이터 입니다. 이 데이터는 구글 플레이 개발자 콘솔에서 왔습니다. 이 데이터는 리소스 아이디와 안드로이드를 위한 앱 ID를 포함합니다.

 

This data is found in the Google Play Developer Console by clicking "Get resources" on any of the resource pages (e.g. Achievements or Leaderboards), then clicking Android.

구글 개발자 콘솔의 리소스페이지에서 Get resources를 누른뒤 안드로이드를 누르면 이 데이터를 볼 수 있습니다.

 

After pasting the data into the text area, click the Setup button.

이 데이터를 텍스트 영역에 붙여넣은 후 설정 버튼을 누르세요.

 

Note: If you are using a web application or backend server with your game, you can link the web application to the game to enable getting the player's id token and/or email address.

주의: 만약 당신이 웹 애플리케이션이나 백엔드 서버를 게임에서 사용하고 있다면, 당신은 플레이어의 ID토큰이나 플레이어의 이메일 주소를 가져올 수 있도록 웹 애플리케이션을 게임과 연결할 수 있습니다.

To do this, link a web application to the game in the Google Play Developer Console, and enter the client id for the web application into the setup dialog.

그렇게 하기 위해, 구글 플레이 개발자 콘솔의 게임에 웹 애플리케이션을 연결하세요. 그리고 웹 애플리케이션의 클라이언트 ID를 설정 다이얼로그에 입력하세요.

Additional instructions on building for Android on Windows

윈도우에서 안드로이드용으로 빌드하기 위한 추가적 안내.

 

If you are using Windows, you must make sure that your Java SDK installation can be accessed by Unity. To do this:

당신이 윈도우를 사용하고 있다면, 당신은 자바 SDK에 유니티가 접근할 수 있는지 확인해야 합니다. 다음과 같이 하세요.

 

1.Set the JAVA_HOME environment variable to your Java SDK installation path (for example, C:\Program Files\Java\jdk1.7.0_45).

1. JAVA_HOME 환경 변수를 자바 설치 경로로 설정하세요.

2.Add the Java SDK's bin folder to your PATH environment variable (for example, C:\Program Files\Java\jdk1.7.0_45\bin)

2. 자바 SDK의 bin폴더를 PATH 환경 변수에 추가하세요.

3.Reboot.

3. 재부팅 하세요.

 

How to edit environment variables: 

환경변수를 수정하는 방법:

In Windows 2000/XP/Vista/7, right-click My Computer, then Properties, then go to Advanced System Properties (or System Properties and then click the Advanced tab), then click Environment Variables.

윈도우 7이하 에서는 내 컴퓨터를 우클릭한 후 설정에 들어가서 고급 시스템 설정으로 가서 환경변수를 클릭합니다.

On Windows 8, press Windows Key + W and search for environment variables

윈도우 8에서는 윈도우키와 W를 함께 누르고 환경변수를 검색하세요.

For more information, consult the documentation for your version of Windows.

더 많은 정보는 윈도우 버전별 문서를 참고하세요.

Run the Project

프로젝트 실행

 

If you are working with the Minimal sample, you should be able to build and run the project at this point.

만약 최소 샘플로 작업하고 있다면, 지금부터 빌드와 실행이 가능합니다.

You will see a screen with an Authenticate button, and you should be able to sign in when you click it.

당신은 인증 버튼을 화면에서 볼 수 있을 것입니다. 그리고 그 버튼을 클릭했을 때 로그인이 가능합니다.

 

To build and run on Android, click File > Build Settings, select the Android platform, then Switch to Platform, then Build and Run.

안드로이드에서 빌드하고 실행시키기 위해서, 파일 > 빌드 설정을 클릭하고 안드로이드 플랫폼을 선택하세요. 그리고 플랫폼을 변경하고 빌드하고 실행시키세요.

ISocialPlatform Compliance

ISocialPlatform 준수

 

The Google Play Games plugin implements Unity's social interface, for compatibility with games that already use that interface when integrating with other platforms.

구글 플레이 게임 플러그인은 이미 다른 플랫폼과 통합된 게임들과의 호환성을 위해 유니티의 소셜 인터페이스를 구현했습니다. 

However, some features are unique to Play Games and are offered as extensions to the standard social interface provided by Unity.

그러나 몇몇 기능들은 플레이 게임에서만 존재하며 유니티가 제공한 표준 소셜 인터페이스의 확장으로 제공됩니다.

 

The standard API calls can be accessed through the Social.Active object, which is a reference to an ISocialPlatform interface.

표준 API 호출은 Social.Active 객체를 통해서 접근이 가능합니다. 이 객체는 ISocialPlatform 인터페이스의 참조입니다.

The non-standard Google Play Games extensions can be accessed by casting the Social.Active object to the PlayGamesPlatform class, where the additional methods are available.

비 표준 구글 플레이 게임 확장들은 Social.Active객체를 PlayGamesPlatform 클래스로 캐스팅 하여 접근할 수 있습니다. PlayGamesPlatform 클래스는 추가 메소드 사용이 가능합니다.

Nearby Connections Configuration

근접 통신 설정

 

In order to use nearby connections, a service id which uniquely identifies the set of applications that can interact needs to be configured.

근접 통신을 사용하기 위해서, 상호 작용이 가능한 어플리케이션의 유일한 서비스 아이디가 설정되어야 합니다.

This is done by clicking the Window > Google Play Games > Nearby Connections setup... menu item.

Window > Google Play Games > Nearby Connections setup을 눌러서 설정이 가능합니다.

This will display the nearby connections setup screen.

그럼 근접 통신 설정 화면이 보일 것 입니다.

On this screen enter the service ID you want to use.

이 화면에서 사용할 서비스 ID를 입력하세요.

It should be something that identifies your application, and follows the same rules as the bundle id (for example: com.example.myawesomegame.nearby).

이 아이디는 당신의 어플리케이션을 식별할 수 있게 해야 합니다. 그리고 번들 ID와 같은 룰을 따라야 합니다.

Once you enter the id, press Setup.

아이디를 입력하고 설정을 누르세요.

To use nearby connections, the player does not need to be authenticated, and no Google Play Developer Console configuration is needed.

근접 통신을 사용하기 위해서, 플레이어는 인증이 필요하지 않습니다. 그리고 구글 플레이 개발자 콘솔 설정도 필요하지 않습니다.

For detailed information on nearby connection usage, please refer to nearby connections.

더 자세한 정보는 근접통신 링크를 참조하세요.

Configuration & Initialization Play Game Services

플레이 게임 서비스 구성 및 초기화

 

In order to save game progress, handle multiplayer invitations and turn notifications, or require access to a player's Google+ social graph, the default configuration needs to be replaced with a custom configuration.

게임 진행을 저장하고, 플레이어를 초대하고 알림을 보내려면 또는 플레이어의 구글 소셜 그래프에 접근 권한을 얻으려면, 기본 설정을 맞춤 구성으로 바꿔야 합니다.

To do this use the PlayGamesClientConfiguration.

그러기 위해서 PlayGamesClientConfiguration을 사용하세요.

If your game does not use these features, then there is no need to initialize the platform configuration.

당신의 게임이 이러한 기능을 사용하지 않는다면, 플랫폼 구성이 필요하지 않습니다.

Once the instance is initialized, make it your default social platform by calling PlayGamesPlatform.Activate:

이 인스턴스가 초기화 되면, PlayGamesPlatform.Activatef를 호출해서 이것을 기본 소셜 플랫폼으로 만듭니다:

 

    using GooglePlayGames;
    using GooglePlayGames.BasicApi;
    using UnityEngine.SocialPlatforms;

    PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder()
        // enables saving game progress.
        //게임 진행상황 저장기능 활성화
        .EnableSavedGames()
        // registers a callback to handle game invitations received while the game is not running.
        //콜백 등록. 게임 실행중이 아닌경우 게임 초대 처리하기 위함.
        .WithInvitationDelegate(<callback method>)
        // registers a callback for turn based match notifications received while the
        // game is not running.
        //콜백 등록. 게임이 실행되지 않는동안 수신한 턴기반 게임을 위한 콜백.
        .WithMatchDelegate(<callback method>)
        // requests the email address of the player be available.
        // Will bring up a prompt for consent.
        //플레이어의 이메일 주소를 사용할 수 있도록 요청한다.
        //동의를 위한 메시지가 나타난다.
        .RequestEmail()
        // requests a server auth code be generated so it can be passed to an
        //  associated back end server application and exchanged for an OAuth token.
        //서버 인증 코드가 백엔드 서버 애플리케이션으로 전달되고
        //OAuth token을 교환할 수 있도록 서버 인증 코드 생성을 요청합니다.
        .RequestServerAuthCode(false)
        // requests an ID token be generated.  This OAuth token can be used to
        //  identify the player to other services such as Firebase.
        //아이디 토큰이 생성되도록 요청합니다. 이 OAuth 토큰은 파이어베이스 같은 다른 서비스에서
        //사용자를 식별하기 위해 사용됩니다.
        .RequestIdToken()
        .Build();

    PlayGamesPlatform.InitializeInstance(config);
    // recommended for debugging:
    //디버깅을 위해 추천됩니다.
    PlayGamesPlatform.DebugLogEnabled = true;
    // Activate the Google Play Games platform
    // 구글 플레이 게임 플랫폼을 활성화 합니다.
    PlayGamesPlatform.Activate();

After activated, you can access the Play Games platform through Social.Active.

활성화 한뒤, 당신은 Social.Active를 통해서 플레이 게임 플랫폼에 접근할 수 있습니다.

You should only call PlayGamesPlatform.Activate once in your application.

당신은 애플리케이션에서 PlayGamesPlatform.Activate를 한번만 호출해야 합니다.

Making this call will not display anything on the screen and will not interact with the user in any way.

이 호출을 만드는 것은 화면에 어떤것도 출력하지 않습니다. 그리고 어떤 식으로든 유저와 상호작용 하지 않습니다.

Adding additional Scopes

추가 영역 추가하기

 

You can add additional scopes to the authentication process by calling PlayGamesClientConfiguration.Builder().AddOauthScope(scope).

당신은 인증 과정에 추가적인 영역을 추가할 수 있습니다.

PlayGamesClientConfiguration.Builder().AddOauthScope(scope)을 호출함 으로써.

 

Note: adding additional scopes with most likely require user consent when starting your game.

주의: 추가적인 영역을 추가하면 게임 시작시 사용자 동의가 요구됩니다.

Sign in

로그인

 

To sign in, call Social.localUser.Authenticate, which is part of the standard Unity social platform interface.

로그인 하기위해, Social.localUser.Authenticate을 호출하세요. 이것은 표준 유니티 소셜 플랫폼 인터페이스의 일부입니다.

    using GooglePlayGames;
    using UnityEngine.SocialPlatforms;
    ...
    // authenticate user:
    //유저 인증
    Social.localUser.Authenticate((bool success) => {
        // handle success or failure
        //성공이나 실패 처리
    });

Authentication will show the required consent dialogs.

인증에 필요한 동의 다이얼로그가 표시됩니다.

If the user has already signed into the game in the past, this process will be silent and the user will not have to interact with any dialogs.

// 유저가 이미 과거에 게임에 가입했다면, 이 절차는 생략될 것입니다. 그리고 유저는 어떤 다이얼로그와도 상호작용하지 않아도 됩니다.

 

Note that you cannot make any games API calls (unlock achievements, post scores, etc) until you get a successful return value from Authenticate, so it is good practice to put up a standby screen until the callback is called, to make sure the user can't start playing the game until the authentication process completes.

당신이 인증으로부터 성공 리턴값을 받기 전까지 당신은 게임 API 호출을 할 수 없음을 기억하세요.

그래서 콜백이 호출 될때까지 대기화면을 띄워두는 것이 좋습니다.

유저는 게임을 시작할 수 없습니다. 인증 절차가 완료될때까지

Player Statistics

플레이어 통계

 

The Player Stats API let you tailor game experiences to specific segments of players and different stages of the player lifecycle.

플레이어 통계 API는 당신이 재단할 수 있게 해줍니다. 게임 경험을 사용자별 분류에 따라 그리고 플레이어 수명주기에 따라 다른 스테이지로 나눌 수 있습니다.

You can build tailored experiences for each player segment based on how players are progressing, spending, and engaging.

당신은 맞춤형 경험을 구축할 수 잇습니다. 각각의 플레이어 분류에 따라, 얼마나 플레이어가 진행했는지, 소모했는지, 참여했는지 기준으로.

For example, you can use this API to take proactive actions to encourage a less active player to re-engage with your game, such as by displaying and promoting new in-game items when the player signs in.

예를 들어, 당신은 이 API를 사용할 수 있습니다. 능동적 액션을 취하는데 사용할 수 있습니다. 적은 활동 플레이어가 게임에 다시 참여할 수 있도록. 사용자가 로그인 할 때 새로운 게임아이템을 보여주고 프로모션함으로 써.

 

The callback takes two parameters:

콜백에는 두가지 파라미터가 필요합니다.

 

1.The result code less than or equal to zero is success. See CommonStatusCodes for all values.

1.결과 코드가 0보다 작거나 같으면 성공입니다. CommonStatusCodes에서 전체 값을 확인하세요.

2.The PlayerStats object of type GooglePlayGames.PlayGamesLocalUser.PlayerStats

2.GooglePlayGames.PlayGamesLocalUser.PlayerStats유형의 사용자 통계객체

 

For more information see Player Stats.

더 많은 정보는 Player Stats를 참고하세요.

The player stats are available after authenticating:

인증 후 사용자 통계를 사용할 수 있습니다.

    ((PlayGamesLocalUser)Social.localUser).GetStats((rc, stats) =>
        {
            // -1 means cached stats, 0 is succeess
            //-1은 캐시된 상태를 의미한다. 0은 성공이다.
            // see  CommonStatusCodes for all values.
            //CommonStatusCodes를 보라 전체 값을 위해.
            if (rc <= 0 && stats.HasDaysSinceLastPlayed()) {
                Debug.Log("It has been " + stats.DaysSinceLastPlayed + " days");
            }
        });

Setting popup gravity

설정 팝업 중력 설정

 

You can set the gravity used by popups when showing game services elements such as achievement notificartions.

업적이나 알림같은 게임서비스 요소를 팝업으로 띄울 때 사용되는 중력을 설정할 수 있습니다.

The default is TOP.

기본값은 TOP입니다.

This can only be set after authentication. For example:

이것은 인증 후 설정될 수 있습니다. 예를 들어:

    Social.localUser.Authenticate((bool success) =>
                {
                    if (success)
                    {
                        ((GooglePlayGames.PlayGamesPlatform)Social.Active).SetGravityForPopups(Gravity.BOTTOM);
                    }
                });

Revealing/Unlocking an Achievement

업적 공개/ 해제

 

To unlock an achievement, use the Social.ReportProgress method with a progress value of 100.0f:

업적을 해제하기위해, Social.ReportProgress 메소드를 사용하세요. 진행 값 100.0f가 되면 업적이 해제됩니다.

 

    using GooglePlayGames;
    using UnityEngine.SocialPlatforms;
    ...
    // unlock achievement (achievement ID "Cfjewijawiu_QA")
    // 업적 언락( 업적 아이디 입력)
    Social.ReportProgress("Cfjewijawiu_QA", 100.0f, (bool success) => {
      // handle success or failure
      //성공, 실패 처리
    });

Notice that according to the expected behavior of Social.ReportProgress, a progress of 0.0f means revealing the achievement and a progress of 100.0f means unlocking the achievement.

Social.ReportProgress의 예상되는 행동에 따르면, 0.0의 진행이 의미하는 것은 업적을 공개하는 것이고, 100.0f의 의미는 업적을 해제하는 것이다.

Therefore, to reveal an achievement (that was previously hidden) without unlocking it, simply call Social.ReportProgress with a progress of 0.0f.

그러므로, 숨겨져있던 업적을 공개하기 위해서, 0.0f로 호출하면 된다.

Incrementing an Achievement

업적 증가

 

If your achievement is incremental, the Play Games implementation of Social.ReportProgress will try to behave as closely as possible to the expected behavior according to Unity's social API, but may not be exact.

당신의 업적이 증가하면, Social.ReportProgress의 플레이 게임 구현은 유니티의 소셜 API에 따라 가능한 예상대로 작동하려 합니다. 그러나 정확하지 않을 수 있습니다.

For this reason, we recommend that you do not use Social.ReportProgress for incremental achievements.

이러한 이유로, 우리는 다음을 추천합니다. 당신이 Social.ReportProgress를 사용하지 않기를.. 업적 증가를 위해

Instead, use the PlayGamesPlatform.IncrementAchievement method, which is a Play Games extension.

대신, 사용하세요 PlayGamesPlatform.IncrementAchivement 함수를. 이것은 플레이 게임이 만든 확장입니다.

    using GooglePlayGames;
    using UnityEngine.SocialPlatforms;
    ...
    // increment achievement (achievement ID "Cfjewijawiu_QA") by 5 steps
    //업적 5 상승
    PlayGamesPlatform.Instance.IncrementAchievement(
        "Cfjewijawiu_QA", 5, (bool success) => {
            // handle success or failure
            //성공 실패 처리
    });

Posting a Score to a Leaderboard

리더보드에 점수 포스트하기

 

To post a score to a leaderboard, call Social.ReportScore.

리더보드에 점수를 포스트하기 위해. Social.ReportScore를 호출하세요.

    using GooglePlayGames;
    using UnityEngine.SocialPlatforms;
    ...
    // post score 12345 to leaderboard ID "Cfji293fjsie_QA")
    //리더보드에 12345 점수를 포스트 합니다.
    Social.ReportScore(12345, "Cfji293fjsie_QA", (bool success) => {
        // handle success or failure
        // 결과 처리합니다.
    });

To post a score and include a metadata tag use the Play Game Services instance directly:

점수를 포스팅하고 메타 태그를 포함하려면, 직접 플레이 게임 서비스 인스턴스를 사용하세요:

    using GooglePlayGames;
    using UnityEngine.SocialPlatforms;
    ...
    // post score 12345 to leaderboard ID "Cfji293fjsie_QA" and tag "FirstDaily")
    // 점수를 포스팅하고 태그합니다.
    Social.ReportScore(12345, "Cfji293fjsie_QA", "FirstDaily", (bool success) => {
        // handle success or failure
    });

Note that the platform and the server will automatically discard scores that are lower than the player's existing high score, so you can submit scores freely without any checks to test whether or not the score is greater than the player's existing score.

플랫폼과 서버는 자동적으로 과거의 낮은 점수를 삭제합니다. 그래서 당신은 점수를 자유롭게 제출할 수 있습니다. 점수가 기존에비해 높은지 낮은지에 대한 어떤 검사도 필요없습니다.

Showing the Achievements UI

업적 UI 보여주기

 

To show the built-in UI for all achievements, call Social.ShowAchievementsUI.

모든 업적을 위해 기본제공 UI를 보여주려면, Social.ShowAchievementsUI를 호출하세요.

    using GooglePlayGames;
    using UnityEngine.SocialPlatforms;
    ...
    // show achievements UI
    Social.ShowAchievementsUI();

Showing the Leaderboard UI

리더보드 UI 보여주기

 

To show the built-in UI for all leaderboards, call Social.ShowLeaderboardUI.

기본제공 리더보드UI를 보여주기 위해서, Social.ShowLeaderboardUI를 호출하세요.

    using GooglePlayGames;
    using UnityEngine.SocialPlatforms;
    ...
    // show leaderboard UI
    Social.ShowLeaderboardUI();

If you wish to show a particular leaderboard instead of all leaderboards, you can pass a leaderboard ID to the method.

당신이 전체 리더보드가 아닌 특정 리더보드를 보여주길 원한다면, 당신은 메소드에 리더보드 아이디를 보낼 수 있습니다.

This, however, is a Play Games extension, so the Social.Active object needs to be cast to a PlayGamesPlatform object firs:

그러나, 이것은 플레이 게임 확장입니다. 그래서 Social.Active 객체를 PlayGamesPlatform 객체로 먼저 캐스팅하는 것이 필요합니다.:

    using GooglePlayGames;
    using UnityEngine.SocialPlatforms;
    ...
    // show leaderboard UI
    PlayGamesPlatform.Instance.ShowLeaderboardUI("Cfji293fjsie_QA");

Accessing Leaderboard data

리더보드 데이터 접근

 

There are 2 methods to retrieving the leaderboard score data.

리더보드 점수 데이터 검색을 위한 두가지 메소드가 있습니다. 

 

Using Social.ILeaderboard

Social.ILeaderboard 사용

This method uses the ILeaderboard interface to define the scope and filters for getting the data.

이 메소드는 데이터를 얻기 위한 범위와 필터를 정의하기 위해 ILeaderboard 인터페이스를 사용합니다.

This approach allows you to configure:

이 방법은 당신이 구성하도록 합니다:

  1. The leaderboard Id
  2. The collection (social or public)
  3. The timeframe (daily, weekly, all-time)
  4. The rank position to start retrieving scores.
  5. The number of scores (the default is 25).
  6. Filter by user id.

 

  1. 리더보드 ID
  2. 콜렉션(소셜, 오픈)
  3. 시간대
  4. 점수 검색 시작을 위한 위치
  5. 점수 값
  6. 유저 ID 필터

If the from parameter is non-positive, then the results returned are player-centered, meaning the scores around the current player's score are returned.

파라미터가 음수라면, 결과는 플레이어 중심이며, 현재 플레이어 점수와 가까운 점수가 표시됩니다.

    ILeaderboard lb = PlayGamesPlatform.Instance.CreateLeaderboard();
    lb.id = "MY_LEADERBOARD_ID";
    lb.LoadScores(ok =>
        {
            if (ok) {
                LoadUsersAndDisplay(lb);
            }
            else {
                Debug.Log("Error retrieving leaderboardi");
            }
        });

Using PlayGamesPlatform.LoadScores()

PlayGamesPlatform.LoadScores() 사용하기

 

This method uses the PlayGamesPlatform directly. This approach provides additional flexibility and information when accessing the leaderboard data.

이 메소드는 PlayGamesPlatform을 직접 사용합니다. 이 접근법은 추가적인 유연성과 정보를 제공합니다. 리더보드 데이터에 접근할 때

 

    PlayGamesPlatform.Instance.LoadScores(
            GPGSIds.leaderboard_leaders_in_smoketesting,
            LeaderboardStart.PlayerCentered,
            100,
            LeaderboardCollection.Public,
            LeaderboardTimeSpan.AllTime,
            (data) =>
            {
                mStatus = "Leaderboard data valid: " + data.Valid;
                mStatus += "\n approx:" +data.ApproximateCount + " have " + data.Scores.Length;
            });

The parameters for LoadScores() are:

LoadScores()를 위한 파라미터는:

  1. leaderboardId
  2. start position (top scores or player centered)
  3. row count
  4. leaderboard collection (social or public)
  5. time span (daily, weekly, all-time)
  6. callback accepting a LeaderboardScoreData object.

 

  1. 리더보드 ID
  2. 시작 위치
  3. 열 갯수
  4. 리더보드 콜렉션
  5. 시간대
  6. LeaderboardScoreData를 받는 콜백

The LeaderboardScoreData class is used to return information back to the caller when loading scores.

LeaderboardScoreData 클래스는 점수를 불러올 때 호출자에게 정보를 반환하기 위해 사용됩니다.

The members are:

그 멤버는:

1. Id - the leaderboard id

1. Id - 리더보드 아이디

2. Valid - true if the returned data is valid (the call was successful)

2. 유효성 - 반환데이터가 유효하면 트루

3. Status - the ResponseStatus of the call

3. 상태 - 호출의 응답상태

4. ApproximateCount - the approximate number of scores in the leaderboard

4. 근접갯수 = 리더보드의 점수에 근접한 수

5. Title - the title of the leaderboard

5. 제목 - 리더보드의 제목

6. PlayerScore - the score of the current player

6. 플레이어 점수 - 현재 플레이어의 점수

7. Scores - the list of scores

7. 점수- 점수 리스트

8. PrevPageToken - a token that can be used to call LoadMoreScores() to get the previous page of scores.

8. 이전 페이지 토큰 - 이전 페이지 점수로 돌아가는데 사용되는 토큰

9. NextPageToken - a token that can be used to call LoadMoreScores() to get the next page of scores.

9.다음페이지 토큰 - 점수의 다음 페이지로 가는데 사용되는 토큰

    void GetNextPage(LeaderboardScoreData data)
    {
        PlayGamesPlatform.Instance.LoadMoreScores(data.NextPageToken, 10,
            (results) =>
            {
                mStatus = "Leaderboard data valid: " + data.Valid;
                mStatus += "\n approx:" +data.ApproximateCount + " have " + data.Scores.Length;
            });
    }

Getting player names

플레이어 이름 얻기

 

Each score has the userId of the player that made the score.

각 점수는 점수를 만든 플레이어의 아이디를 가지고 있다.

You can use Social.LoadUsers() to load the player profile.

당신은 플레이어의 프로필을 불러오기위해 Social.LoadUsers()를 사용할 수 있다.

Remember that the contents of the player profile are subject to privacy settings of the players.

플레이어 프로필의 내용은 플레이어 개인 설정에 따르는 것을 기억하세요.

    internal void LoadUsersAndDisplay(ILeaderboard lb)
    {
        // get the user ids
        // 유저의 아이디들을 얻으세요
        List<string> userIds = new List<string>();

        foreach(IScore score in lb.scores) {
            userIds.Add(score.userID);
        }
        // load the profiles and display (or in this case, log)
        // 프로필들을 불러오고 보여주세요.
        Social.LoadUsers(userIds.ToArray(), (users) =>
            {
                string status = "Leaderboard loading: " + lb.title + " count = " +
                    lb.scores.Length;
                foreach(IScore score in lb.scores) {
                    IUserProfile user = FindUser(users, score.userID);
                    status += "\n" + score.formattedValue + " by " +
                        (string)(
                            (user != null) ? user.userName : "**unk_" + score.userID + "**");
                }
                Debug.log(status);
            });
    }

Recording Events

이벤트 기록하기

 

Incrementing an event is very simple, just call the following method:

이벤트를 증가시키는 것은 매우 쉽다. 단지 아래의 메소드를 호출하면 된다.

    using GooglePlayGames;
    ...
    // Increments the event with Id "YOUR_EVENT_ID" by 1
    //이벤트를 1만큼 증가시킨다.
    PlayGamesPlatform.Instance.Events.IncrementEvent("YOUR_EVENT_ID", 1);

This call is "fire and forget", it will handle batching and execution for you in the background.

이것은 "불내고 잊는다"로 불립니다. 이것은 백그라운드에서 배치하고 실행하는 것을 다룹니다.

Saving Game State to the Cloud

클라우드에 게임 상태 저장

 

For details on saved games concepts and APIs please refer to the documentation.

게임 저장 개념과 API에 대한 자세한 정보는 이 문서를 참고하세요.

 

To enable support for saved games, the plugin must be initialized with saved games enabled by calling PlayGamesPlatform.InitializeInstance:

게임 저장 지원을 활성화 하기 위해, 플러그인은 PlayGamesPlatform.InitializeInstance을 호출하여 활성화하고 초기화되어야 합니다.

 

    PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder()
        // enables saving game progress.
        // 게임 진행 저장 활성화
        .EnableSavedGames()
        .Build();
    PlayGamesPlatform.InitializeInstance(config);

Displaying saved games UI

저장된 게임 UI 표시하기

 

The standard UI for selecting or creating a saved game entry is displayed by calling:

저장된 게임을 만들거나 선택할 표준 UI는 호출로 나타납니다:

    void ShowSelectUI() {
        uint maxNumToDisplay = 5;
        bool allowCreateNew = false;
        bool allowDelete = true;

        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        savedGameClient.ShowSelectSavedGameUI("Select saved game",
            maxNumToDisplay,
            allowCreateNew,
            allowDelete,
            OnSavedGameSelected);
    }


    public void OnSavedGameSelected (SelectUIStatus status, ISavedGameMetadata game) {
        if (status == SelectUIStatus.SavedGameSelected) {
            // handle selected game save
        } else {
            // handle cancel or error
        }
    }

Opening a saved game

In order to read or write data to a saved game, the saved game needs to be opened.

저장된 게임의 데이터를 읽거나 쓰기 위해서, 저장된 게임이 열려야합니다.

Since the saved game state is cached locally on the device and saved to the cloud, it is possible to encounter conflicts in the state of the saved data.

저장된 데이터의 상태는 디바이스에 캐쉬되어있고, 클라우드에 저장되어 있기에, 저장된 데이터의 상태가 충돌하는 것이 가능하다.

A conflict happens when a device attempts to save state to the cloud but the data currently on the cloud was written by a different device.

충돌은 디바이스가 클라우드에 저장하려고 시도하는데 현재 데이터는 다른 디바이스에서 기록되었을 때 발생합니다.

These conflicts need to be resolved when opening the saved game data.

이 충돌은 저장된 게임 데이터를 열 때 해결이 필요합니다.

There are 2 open methods that handle conflict resolution, the first OpenWithAutomaticConflictResolution accepts a standard resolution strategy type and automatically resolves the conflicts.

충돌 해결할 두가지 오픈 메소드가 있습니다. 먼저 OpenWithAutomaticConflictResolution는 표준 해결 전략 유형을 받아들입니다. 그리고 자동적으로 충돌을 해결합니다.

The other method, OpenWithManualConflictResolution accepts a callback method to allow the manual resolution of the conflict.

다른 메소드OpenWithManualConflictResolution는 수동으로 충돌을 해결할 콜백 메소드를 수용합니다.

 

See GooglePlayGames/BasicApi/SavedGame/ISavedGameClient.cs for more details on these methods.

이 메소드들의 더 자세한 정보는 GooglePlayGames/BasicApi/SavedGame/ISavedGameClient.cs를 참고하세요.

    void OpenSavedGame(string filename) {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        savedGameClient.OpenWithAutomaticConflictResolution(filename, DataSource.ReadCacheOrNetwork,
            ConflictResolutionStrategy.UseLongestPlaytime, OnSavedGameOpened);
    }

    public void OnSavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game) {
        if (status == SavedGameRequestStatus.Success) {
            // handle reading or writing of saved game.
        } else {
            // handle error
        }
    }

Writing a saved game

저장된 게임 쓰기

 

Once the saved game file is opened, it can be written to save the game state.

저장된 게임 파일이 열리면, 게임 상태를 저장하는 것이 가능합니다.

This is done by calling CommitUpdate.

CommitUpdate을 호출함으로써 이것을 할 수 있습니다.

There are four parameters to CommitUpdate:

CommitUpdate를 위한 파라미터가 4개 있습니다:

  1. the saved game metadata passed to the callback passed to one of the Open calls.
  2. the updates to make to the metadata.
  3. the actual byte array of data
  4. a callback to call when the commit is complete.

 

  1. 콜백에 전달된 저장된 게임 메타데이터
  2. 메타데이터를 만드는 업데이트들
  3. 데이터의 실제 바이트 배열
  4. 커밋이 완료되었을 때 호출할 콜백
    void SaveGame (ISavedGameMetadata game, byte[] savedData, TimeSpan totalPlaytime) {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;

        SavedGameMetadataUpdate.Builder builder = new SavedGameMetadataUpdate.Builder();
        builder = builder
            .WithUpdatedPlayedTime(totalPlaytime)
            .WithUpdatedDescription("Saved game at " + DateTime.Now());
        if (savedImage != null) {
            // This assumes that savedImage is an instance of Texture2D
            // and that you have already called a function equivalent to
            // getScreenshot() to set savedImage
            // NOTE: see sample definition of getScreenshot() method below
            byte[] pngData = savedImage.EncodeToPNG();
            builder = builder.WithUpdatedPngCoverImage(pngData);
        }
        SavedGameMetadataUpdate updatedMetadata = builder.Build();
        savedGameClient.CommitUpdate(game, updatedMetadata, savedData, OnSavedGameWritten);
    }

    public void OnSavedGameWritten (SavedGameRequestStatus status, ISavedGameMetadata game) {
        if (status == SavedGameRequestStatus.Success) {
            // handle reading or writing of saved game.
        } else {
            // handle error
        }
    }

    public Texture2D getScreenshot() {
        // Create a 2D texture that is 1024x700 pixels from which the PNG will be
        // extracted
        Texture2D screenShot = new Texture2D(1024, 700);

        // Takes the screenshot from top left hand corner of screen and maps to top
        // left hand corner of screenShot texture
        screenShot.ReadPixels(
            new Rect(0, 0, Screen.width, (Screen.width/1024)*700), 0, 0);
        return screenShot;
    }

Reading a saved game

저장된 게임 읽기

 

Once the saved game file is opened, it can be read to load the game state. This is done by calling ReadBinaryData.

저장된 게임을 열면, 게임상태를 불러오기 위해 읽을 수 있습니다. ReadBinaryData을 호출해서 이것을 할 수 있습니다.

    void LoadGameData (ISavedGameMetadata game) {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        savedGameClient.ReadBinaryData(game, OnSavedGameDataRead);
    }

    public void OnSavedGameDataRead (SavedGameRequestStatus status, byte[] data) {
        if (status == SavedGameRequestStatus.Success) {
            // handle processing the byte array data
        } else {
            // handle error
        }
    }

Deleting a saved game

저장된 게임 삭제하기

 

Once the saved game file is opened, it can be deleted. This is done by calling Delete.

저장된 게임이 열린 상태에서, 삭제될 수 있습니다. Delete를 호출해서 수행됩니다.

    void DeleteGameData (string filename) {
        // Open the file to get the metadata.
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        savedGameClient.OpenWithAutomaticConflictResolution(filename, DataSource.ReadCacheOrNetwork,
            ConflictResolutionStrategy.UseLongestPlaytime, DeleteSavedGame);
    }

    public void DeleteSavedGame(SavedGameRequestStatus status, ISavedGameMetadata game) {
        if (status == SavedGameRequestStatus.Success) {
            ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
            savedGameClient.Delete(game);
        } else {
            // handle error
        }
    }

Retrieving server authentication codes

서버 인증 코드 받기

 

In order to access Google APIs on a backend web server on behalf of the current player, you need to get an authentication code from the client application and pass this to your web server application.

현재 플레이어 대신 백엔드 웹서버에서 구글 API에 접근하려면, 당신은 클라이언트 애플리케이션에서 인증코드를 받아오고 이것을 웹서버 애플리케이션에 전송해야한다.

This code can then be exchanged for an access token to make calls to the various APIs.

그다음 다른 API들을 호출하기위해 access token이 교환될 수 있다.

For more details on this flow see: Google Sign-In for Websites.

흐름에 대한 더 자세한 정보는 여기를 참조하세요:

 

To get the Server Auth code:

서버 인증 코드를 얻기 위해:

  1. Configure the web client Id of the web application linked to your game in the Play Game Console.
  2. Call PlayGamesClientConfiguration.Builder.RequestServerAuthCode(false) when creating the configuration.
  3. Call PlayGamesPlatform.Instance.GetServerAuthCode() once the player is authenticated.
  4. Pass this code to your server application.

 

  1. 웹 애플리케이션의 웹 클라이언트 아이디를 설정해야합니다. 웹 클라이언트 아이디는 플레이 게임 콘솔에서 당신의 게임에 연결된 것을 말합니다.
  2. 그 구성을 만들때 PlayGamesClientConfiguration.Builder.RequestServerAuthCode(false)을 호출하세요.
  3. 플레이어가 인증되면 PlayGamesPlatform.Instance.GetServerAuthCode()를 호출하세요
  4. 이 코드를 당신의 서버로 보내세요

Getting another server auth code after exchanging the first code

처음 코드를 교환한 후 다른 서버 인증 코드를 받아오기

 

If your back end server interactions requires you to send a server auth code more than once per authenticated session, you can call PlaPlayGamesPlatform.Instance.GetAnotherServerAuthCode(Action<string> callback)

당신의 백엔드 서버가 인증된 세션당 두번 이상 서버에 보내는 것이 필요하다면, 당신은 PlaPlayGamesPlatform.Instance.GetAnotherServerAuthCode(Action<string> callback)를 호출할 수 있습니다.

This method requires the player to be aready authenticated and correctly configured to request server auth codes on this client.

이 메소드는 플레이어를 인증하고 클라이언트에서 서버 인증 코드를 요청하도록 올바르게 구성되어야 합니다.

This method is implemented by calling Google Sign-in silently which returns a new server auth code when already signed in.

이 메소드는 구글 로그인을 호출함으로 구현됩니다. 이미 로그인 되어있을 때 새로운 서버 인증 코드를 구글 로그인은 반환합니다. 

Retrieving player's email

플레이어 이메일 조회

 

In order to access the player's email address:

플레이어의 이메일에 접근하기 위해서:

  1. Call PlayGamesClientConfiguration.Builder.RequestEmail() when creating the configuration.
  2. Access the email property ((PlayGamesLocalUser) Social.localUser).Email after the player is authenticated.

 

  1. 구성을 만들 때 PlayGamesClientConfiguration.Builder.RequestEmail()를 호출해야 합니다.
  2. 플레이어가 이메일을 인증한 뒤, 이메일 설정에 접근하세요

Note: If all that is needed is a persistent unique identifier for the player, then you should use the player's id.

주의: 필요한 모든것이 플레이어의 영구적인 유일 식별자인 경우, 플레이어의 아이디를 사용해야합니다.

This is a unique ID specific to that player and is the same value all the time.

이것은 유일한 ID입니다. 그리고 플레이어를 특정하고 항상 같은 값입니다.

Retrieving player's ID Token

플레이어 ID 토큰 조회

 

To get the player's OAuth ID token:

플레이어의 OAuth ID 토큰을 얻기 위해:

  1. Call PlayGamesClientConfiguration.Builder.RequestIdToken() when creating the configuration.
  2. Access the idtoken property ((PlayGamesLocalUser) Social.localUser).GetIdToken() after the player is authenticated.

 

  1. 구성을 생성할 때 PlayGamesClientConfiguration.Builder.RequestIdToken()를 호출하세요
  2. 플레이어가 인증한 뒤 id 토큰 속성에 접근하세요.

Note: The ID Token can be used to identify the real player identity.

주의: 아이디 토큰은 실제 플레이어 식별에 사용될 수 있습니다. 

As a result requesting the ID Token will cause a consent screen to be presented to the user during login.

아이디 토큰을 요청하면 로그인 하고있는 유저에게 승인 화면을 보여줍니다.

Loading Friends

친구 가져오기

 

To load the friends of the current player, you can use the ISocial framework. This call is asynchronous, so the friends need to be processed in the callback.

현재 플레이어의 친구를 가져오기위해, 당신은 ISocial framework를 사용할 수 있다. 이 호출은 비동기이다. 그래서 친구는 콜백에서 처리가 필요하다.

Social.localUser.LoadFriends((ok) =>  {
    Debug.Log("Friends loaded OK: " + ok));
    foreach(IUserProfile p in Social.localUser.friends) {
         Debug.Log(p.userName + " is a friend");
    }
});

Multiplayer

멀티 플레이

 

If you wish to integrate turn-based multiplayer in your game, refer to the Getting Started with Turn-Based Multiplayer.

당신이 턴 기반 멀티플레이어를 당신 게임에 통합하고 싶다면 다음 링크를 참조하세요.

If you wish to integrate real-time multiplayer in your game, refer to the Getting Started with Real-Time Multiplayer.

만약 실시간 멀티플레이어를 당신 게임과 통합하고 싶다면 다음 링크를 참조하세요.

Video Recording

비디오 녹화

 

생략

Sign out

로그 아웃

 

To sign the user out, use the PlayGamesPlatform.SignOut method.

유저를 로그아웃 하기 위해서, PlayGamesPlatform.SignOut 메소드를 사용하세요.

    using GooglePlayGames;
    using UnityEngine.SocialPlatforms;

    // sign out
    PlayGamesPlatform.Instance.SignOut();

After signing out, no further API calls can be made until the user authenticates again.

로그아웃 한뒤, 더이상의 API 호출은 다시 유저가 인증하기전에 생기지 않는다.

Decreasing apk size

앱 사이즈 줄이기

 

It is possible to decrease the size of the Play Games Services Unity Plugin by removing code for the Play Games Services features that your game doesn’t use by using Proguard. Proguard will remove the Play Games Unity plugin code for features that are not used in your game, so your game ships with only the code that is needed and minimizes the size impact of using Play Games Services.

Additionally, it is possible to reduce the size of the entire Unity project using Unity’s Managed Code Stripping, which will compress your entire project. This can be used in conjunction with Proguard.

 

Play Games Services Proguard configuration

  1. Go to File > Build Settings > Player Settings and click Publishing Settings section. Choose Proguard for Minify > Release. Then, enable User Proguard File. If you want the plugin to be proguarded for debug apks as well, you can choose Proguard for Minify > Debug.
  2. Copy the content of the proguard configuration into Assets/Plugins/Android/proguard-user.txt.

(Advanced) Using the Plugin Without Overriding the Default Social Platform

When you call PlayGamesPlatform.Activate, Google Play Games becomes your default social platform implementation, which means that static calls to methods in Social and Social.Active will be carried out by the Google Play Games plugin. This is the desired behavior for most games using the plugin.

However, if for some reason you wish to keep the default implementation accessible (for example, to use it to submit achievements and leaderboards to a different social platform), you can use the Google Play Games plugin without overriding the default one. To do this:

  1. Do not call PlayGamesPlatform.Activate
  2. If Xyz is the name of a method you wish to call on the Social class, do not call Social.Xyz. Instead, call PlayGamesPlatform.Instance.Xyz
  3. Do not use Social.Active when interacting with Google Play Games. Instead, use PlayGamesPlatform.Instance.

That way, you can even submit scores and achievements simultaneously to two or more social platforms:

// Submit achievement to original default social platform Social.ReportProgress("MyAchievementIdHere", 100.0f, callback); // Submit achievement to Google Play PlayGamesPlatform.Instance.ReportProgress("MyGooglePlayAchievementIdHere", 100.0f, callback);

Special Thanks

This section lists people who have contributed to this project by writing code, improving documentation or fixing bugs.

  • Dgizusse for figuring out that setting JAVA_HOME is necessary on Windows.
  • antonlicht for fixing a bug with the parameter type of showErrorDialog on the support library.
  • pR0Ps for fixing an issue where OnAchievementsLoaded was not accepting an OPERATION_DEFERRED result code as a success.
  • friikyeu for helping debug an issue that caused API calls to be queued up rather than executed even when connected.

 

 

 

'영어' 카테고리의 다른 글

[100단어 영어회화의 기적] 1~7 day (2회)  (0) 2020.01.03
[100단어 영어회화의 기적] 읽는 이유와 생각 정리  (0) 2020.01.03
알면서 모르는 것  (0) 2020.01.02
[100단어 영어회화의 기적] 복습  (0) 2019.12.30
Shall  (0) 2019.12.29

V하자

Let's V

 

우리 빵집에 가자.

Let's go to the bakery

우리 집에 가자

Let's go to the home

우리 뭐좀 마시자

Let's drink someting

 

V하지말자

Let's not V

 

물마시지 말자

Let's not drink water

 

해!

V

하자

Let's V

 

할래?

Shall

할거야?

Will

할수있어?

Can

 

이것

this

그거

it, the

저거

that

 

put

1. to move something into a particular place or position.

옮기는 것/어떤 것을/특정한 장소나 위치로/

She put her bag down by the door.

그녀는/두었다/가방을/문옆에/

 

particular 

1. used to talk about a single thing or person that is special in some way.

사용된다/말하기위해/대해서/사물이나 사람/특별한/어떤면에서/

Do you want any partiular color?

 

into

1. to or toward the inside of a place, container, etc.

공간이나 컨테이너 안으로

 

leave

떠나다

 

too much

너무 많이

 

과거분사

~된

fried chicken

튀겨진 닭

 

현재분사

~하는

frying pan

튀기는 팬

 

완전탐색 유형에 있는 숫자 야구 문제이다.

 

완전 탐색은 이 게시판을 보면 된다.

2019/12/30 - [알고리즘/문제해결전략] - 03 알고리즘 설계 패러다임 - (6)무식하게 풀기

 

모든 경우의 수를 만들 땐 재귀함수를 이용했다.

모든 경우의 수를 만들고, base case가 되면 조건에 맞는지 확인.

 

C++을 사용.

 

1부터 9까지 카드에서 3장을 뽑아 순열을 만들도록 했다.

그리고 모든 경우의 수에서 주어진 데이터와 비교해서 일치하는 경우에 카운팅하도록 구현했다.

 

20191230

#include <string>
#include <vector>
using namespace std;
string cards="0123456789";
bool pickedCard[10]; 

bool check(string& nums, vector<vector<int>>& baseball){
    for(int i=0; i<baseball.size(); ++i){
        string instring = to_string(baseball[i][0]);
        int ss=0, bb=0;
        
        for(int j=0; j<instring.size();++j){
            int nth = nums.find(instring[j]);
            if(nth== string::npos){
                continue;
            }
            else if(nth == j){
                ss++;
            }else if(nth != j){
                bb++;
            } 
        }
        if(baseball[i][1] !=ss || baseball[i][2] != bb){
            return false;
        }
    }
    return true;
}

void sol(string &picked, vector<vector<int>>& baseball, int &ans){
    if(picked.size() == 3){
        // 체크해서 값 상승
        if (check(picked, baseball)== true){
            ans++;
        }
        return;
    }
    for(int i = 1; i<10; i++){
        //만약 이미 선택된 카드라면 패스
        if(pickedCard[i]) continue;
        
        picked.push_back(cards[i]);
        pickedCard[i] = true;
        
        sol(picked, baseball, ans);
        
        picked.pop_back();
        pickedCard[i] = false;
    }
}

int solution(vector<vector<int>> baseball) {
    int answer = 0;
    string t = "";
    sol(t, baseball, answer);
    return answer;
}

개관

알고리즘을 고안하는 것은 까다롭다.

알고리즘을 고안하기 위해서는 문제의 특성을 이해하고, 동작 시간과 사용하는 공간 사이의 상충 관계를 이해해야 하며, 적절한 자료구조를 선택할 줄 알아야 한다.

 

알고리즘 설계 패러다임은 문제를 해결하기 위해 알고리즘이 채택한 전략이나 관점을 말한다.

 

06 무식하게 풀기

6.1 도입

가장 많이 하는 실수는 어렵게 푸는 것이다.

전삭학에서 무식하게 푼다는 말은 (부르트 포스) 가능한 모든 경우의 수를 나열해 답을 찾는 것을 말한다.

 

이런 알고리즘을 가리켜 완전탐색(exhaustive searce)라고 부른다.

 

컴퓨터의 경우 빠른 연산이 가능하기에 작은 입력에 경우 완전탐색이 빠르고 정확한 풀이일 수 있다.

 

6.2 재귀 호출과 완전 탐색

재귀 호출

재귀 함수란 자신이 수행할 작업을 유사한 형태의 여러 조각으로 쪼갠 뒤 그 중 한 조각을 수행하고, 나머지를 자기 자신을 호출해 실행하는 함수를 가리킨다.

 

자연수 n이 주어졌을 때 1부터 n까지의 합을 반환하는 함수를 재귀함수로 구현해보자.

//기본 조건 n>=1
//결과 1부터 n까지의 합을 반환
int sum(int n){
    int ret = 0;
    for(int i=1; i<=n; ++i)
        ret += i;
    return ret;
}

int recursiveSum(int n){
    if(n==1) return 1;
    return n + recursiveSum(n-1);
}

n개의 숫자 합을 구하는 작업을 n개의 조각으로 쪼개, 더할 각 숫자가 하나의 조각이 되도록 한다.

모든 재귀함수는 더이상 쪼개지지 않는 최소한의 작업에 도달했을 때 답을 바로 반환하는 조건문을 포함해야한다.

쪼개지지 않는 가장 작은 작업들을 재귀함수의 기저 사례(base case)라고 한다.

 

재귀호출은 문제의 특성에 따라 코딩을 간편하게 해준다.

 

예제: 중첩 반복문 대체하기

0부터 n까지 번호의 카드 중에서 네 개를 고르는 모든 경우를 출력하는 코드를 작성해보자.

for(int i=0; i<n; ++i)
    for(int j=i+1; j<n; ++j)
        for(int k=j+1; k<n; ++k)
            for(int l=k+1; l<n; ++l)
                cout<<i<<" "<<j<<" "<<k<<" "<<l<<endl;

4중 포문을 써서 구현할 수 있다. 하지만 7개를 고르는 경우라면?..

 

이런경우 재귀 호출은 간결하고 유연한 코드를 작성할 수 있게 해준다.

 

위 문제의 경우 네개의 조각으로 나눌 수 있다.

각 조각에서 하나의 원소를 고른다. 원소를 고른 뒤, 남은 원소들을 고르는 작업을 재귀함수로 구현한다.

남은 원소를 고르는 작업을 다음과 같은 입력들의 집합으로 정의할 수 있다.

  • 원소들의 총 개수
  • 더 골라야 할 원소들의 개수
  • 지금까지 고른 원소들의 번호
//n은 전체 원소의 수
//picked는 지금까지 고른 원소들의 번호
//toPick은 더 고를 원소의 수

void pick(int n, vector<int>& picked, int toPick){
    //base case:더 고를 원소가 없을 때 고른 원소들을 출력한다.
    if(toPick == 0){printPicked(picked);return;}
    
    //고를 수 잇는 가장 작은 번호를 계산한다.
    int smallest = picked.empty() ? 0 : picked.back()+1;
    //이 단계에서 원소 하나를 고른다.
    for(int next = smallest; next<n; ++next){
        picked.push_back(next);
        pick(n, picked, toPick - 1);
        picked.pop_back();
     }
 }

재귀 호출을 이용하면 특정 조건을 만족하는 조합을 모두 생성하는 코드를 쉽게 작성할 수 있다.

때문에 재귀 호출은 완전 탐색을 구현할 때 아주 유용한 도구이다.

 

완전탐색 레시피

1. 완전탐색은 존재하는 모든 답을 하나씩 검사하므로, 걸리는 시간은 가능한 답의 수에 정확히 비례한다.

최대 크기의 입력을 가정했을 때 답의 개수를 계산하고 이들을 모두 제한 시간 안에 생성할 수 있을지를 가늠한다.

만약 시간안에 계산할 수 없다면 다른 설계 패러다임을 적용해야한다.

2. 가능한 모든 답의 후보를 만드는 과정을 여러 개의 선택으로 나눈다. 각 선택은 답의 후보를 만드는 과정의 한 조각이 된다.

3.그중 하나의 조각을 선택해 답의 일부를 만들고, 나머지 답을 재귀호출을 통해 완성한다.

4. 조각이 하나밖에 남지 않은 경우, 혹은 하나도 남지 않은 경우에는 답을 생성했으므로, 이것을 기저 사례로 선택해 처리한다.

 

이론적 배경: 재귀 호출과 부분 문제

문제와 부분 문제의 정의를 알아야한다.

이 정의는 동적계획법, 분할정복 같은 디자인 패러다임을 설명하는데 사용된다.

쉽게 생각하는 직관과는 다르다.

 

문제를 여러 조각으로 나누었을 때 조각들을 부분문제라고 할 수 있다.

 

나의 정리

부분으로 조각내고 각 케이스 별로 만들어서 케이스의 끝인 경우 문제의 정답인지 확인 후 정답인 경우 반환하면 된다.

그 전에 나오면 안되는 예외의 경우 함수 내에서 더이상 진행되지 않도록 처리.

 

6.7 최적화 문제 (Optimization problem)

문제의 답이 하나가 아니라 여러 개이고, 그 중에서 어떤 기준에 따라 가장 '좋은' 답을 찾아내는 문제를 최적화 문제라고 한다.

 

n개의 사과 주에서 r개를 골라서 무게의 합을 최대화하는 문제, 가장 무거운 사과와 가장 가벼운 사과의 무게 차이를 최소화 하는 문제 등은 최적화 문제가 된다.

사과를 고르는 방법은 여러 가지인데, 이 중 특정 기준에의해 가장 좋은 답을 고르는 문제이기 때문이다.

 

최적화 문제는 우리 생활과 밀접하다. 세상에는 효율적인, 최대의, 최소의 값을 찾아야하는 경우가 많다.

때문에 최적화 문제는 중요한 주제 중 하나이다.

 

예제: 여행하는 외판원 문제

어떤 나라에 n(2≤n≤10)개의 큰 도시가 있다고 하자.

한 영업 사원이 한 도시에서 출발해 다른 도시들을 전부 한 번씩 방문한 뒤 시작 도시로 돌아오려고 한다.

문제를 간단히 하기 위해, 각 도시는 모두 직선 도로로 연결되어 있다고 한다.

이 때 이동 거리는 도시 방문 순서에 따라 달라진다.

 

무식하게 풀 수 있을까?

완전 탐색으로 문제를 풀기 위한 첫 번째 단계는 시간 안에 답을 구할 수 잇는지 확인하는 것이다.

시작한 도시로 돌아오는 경로를 찾기에 경로의 시작점은 신경쓰지 않아도 된다.

시작 도시를 정하고 나머지 도시의 경우의 수는 (n-1)!가 된다.

도시 10개의 경우 9!은 362,880개가 되어 1초안에 처리할 수 있다.

 

재귀 호출을 통한 답안 생성

int n;//도시의 수
double ist[MAX][MAX];//두 도시 간의 거리를 저장하는 배열
//path는 지금까지 만든 경로
//vidited는 각 도시의 방문여부
//currentLength는 지금까지 만든 경로의 길이

//나머지 도시들을 모두 방문하는 경로들 중 가장 짧은 것의 길이를 반환한다.
double shortestPath(vector<int>& ath, vector<bool>& visited, double currentLength)
{
    //base case - 모든 도시를 방문한 경우 시작 도시로 돌아가고 종료한다.
    if(path.size() == n)
        return currentLength + dist[path[0]][path.back()];
    
    double ret = INF;
    //다음 방문할 도시를 전부 시도해 본다.
    for(int next = 0; next < n; ++next)
    {
        //방문할 곳이 이미 방문한 곳이라면 통과
        if(visited[next]) continu;
        //방문한 곳이 아니라면 방문
        int here = push.back();
        path.push_back(next);
        visited[next] = true;
        
        //나머지 경로를 재귀 호출을 통해 완성하고 가장 짧은 경로의 길이를 얻는다.
        double cand = shortestpath(path, visited, currentLength + dist[here][next]);
        //나머지 경로를 반복해서 받아오면서 최소 길이를 찾는다.
        ret = min(ret, cand);
        
        //다른 경우의 수를 찾아야 하므로 경로에서 제거한다.
        visited[next] = false;
        path.pop_back();
    }
    return ret;
}

 

6.8 문제: 시계 맞추기 (문제 ID: CLOCKSYNC, 난이도: 중)

그림과 같이 4X4개의 격자 형태로 배치된 열여섯 개의 시계가 있다.

이 시계들은 12, 3, 6, 9시를 가리키고 있다.

이 시계들이 모두 12시를 가리키도록 바꾸려한다.

시계의 시간을 조작하는 방법은 열개의 스위치들을 조작하는 것으로, 각 스위치는 누를 때 마다, 해당 스위치와 연결된 시계들의 시간은 3시간 후로 움직인다.

 

스위치 번호 연결된 시계 스위치 번호 연결된 시계
0 0, 1, 2 5 0, 2, 14, 15
1 3, 7, 9, 11 6 3, 14, 15
2 4, 10, 14, 15 7 4, 5, 7, 14, 5
3 0, 4, 5, 6, 7 8 1, 2, 3, 4, 5
4 6, 7, 8, 10, 12 9 3, 4, 5, 9, 13

시계 순서는 위에서 아래로, 왼쪽에서 오른쪽으로 매겨진다.

모든 시계를 12시로 돌리기 위해 최소한 스위치를 몇 번 눌러야 할지 구하시오.

 

시간 및 메모리 제한

프로그램은 10초 안에 실행되어야 하며, 64MB 이하의 메모리를 사용해야한다.

 

입력

첫번째 줄에 테스트 케이스 개수 C가 주어진다. (C≤30)

각 테스트 케이스는 한줄에 16개의 정수로 주어진다. 각 정수는 시계를 의미하며 정수의 값은 3, 6, 9, 12중 하나로 표현한다.

 

출력

각 케이스당 정수 하나를 한줄에 출력한다. 정수 값은 스위치 누르는 횟수이다.

시계들을 12시로 만드는 것이 불가능 하다면, -1을 출력한다.

 

예제 입력

2

12 6 6 6 6 612 12 12 12 12 12 12 12 12 12

12 9 3 12 6 6 9 3 12 9 12 9 12 12 6 6

 

예제 출력

2

9

 

6.9 풀이: 시계 맞추기

문제 변형하기

문제 그대로 풀려고 하면 복잡하다.

문제의 특성을 이용해 단순화하면 완전탐색으로 해결할 수 있다.

 

이 문제에서 깨달아야 할 것은 스위치를 누르는 순서는 중요하지 않다는 것이다.

순서를 바꾼다고 결과가 달라지지 않는다.

구해야할 것은 각 스위치를 몇번 누를 것인가 이다.

 

이렇게 문제를 바꿔도 완전탐색으로 구할 수 없다.

완전 탐색 알고리즘을 사용하려면 스위치를 누르는 횟수의 모든 조합을 하나하나 열거할 수 있어야 하는데,

각 스위치를 몇번 누르는 지는 상관이 없기에 조합의 수가 무한하기 때문이다.

 

시계는 12시간이 지나면 제자리로 돌아온다는 점을 이용하면 무한한 조합의 수를 유한하게 바꿀 수 있다.

어떤 스위치를 네번 누르면 연결된 시계는 모두 12시간 앖으로 이동하니 하나도 누르지 않은 것과 같다.

따라서 어떤 스위치건 3번 이상 누를 일이 없다.

 

따라서 각 스위치를 누르는 횟수는 0에서 3사이의 정수이다.

10개의 스위치가 있으니 전체 경우의 수는 4^10이 된다.

 

완전탐색 구현하기

 

const int INF = 9999, SWITCHES = 10, CLOCKS = 16;
//linked[i][j]가 x인 경우는 i번 스위치와 j번 시계가 연결되어 있다는 의미
//linked[i][j]가 .인 경우는 연결되어 있지 않다는 의미
const char linked[SWITCHES][CLOCKS+1] = {
   //0123456789012345
    "xxx.............", 
    "...x...x.x.x....",
    "....x.....x...xx",
    "x...xxxx........",
    "......xxx.x.x...",
    "x.x...........xx",
    "...x..........xx",
    "....xx.x......xx",
    ".xxxxx..........",
    "...xxx...x...x.."
};

//모든 시계가 12시를 가리키는지 확인한다.
bool areAligned(const vector<int>& clocks);

//swtch번 스위치를 누른다.
void push(vector<int>& clocks, int swtch){
    for(int clock = 0; clock < CLOCKS; ++clock)
        if(linked[swtch][clock] == 'x'){
            clocks[clock] += 3;
            if(clocks[clock] == 15) clocks[clock] = 3;
        }
}

//clocks는 현재 시계들의 상태
//swtch는 이번에 누를 스위치의 번호
//남은 스위치를 눌러서 clocks를 12시로 맞출 수 있는 최소 횟수를 반환한다.
//불가능하다면 INF이상의 큰 수를 반환한다.
int solve(vector<int>& clocks, int swtch){
    //끝까지 탐색한 경우 시계들의 상태를 확인
    if(swtch == SWITCHES) return areAlingned(clocks) ? 0:INF;
    
    //이 스위치를 번 누르는 경우부터 세번 누르는 경우까지 모두 시도한다.
    int ret = INF;
    for(int cnt = 0; cnt < 4; ++cnt) {
        ret = min(ret, cnt + solve(clocks, swtch + 1));
        push(clocks, swtch);
    }
    
    //push()가 4번 호출되어 초기상태와 같아진다.
    return ret;
}

 

6.10 많이 등장하는 완전 탐색 유형

 

모든 순열 만들기

서로 다른 N개의 원소를 일렬로 줄 세운 것을 순열이라한다.

자주 볼 수 있는 유형이다.

가능한 순열의 수는 N!인데, N이 10을 넘어간다면 시간 안에 모든 순열을 생성하기 어려워져, 완전 탐색이 아닌 다른 방법을 찾아야한다.

 

C++ 사용시 유리하다.

STL에 포함된 next_permutation()함수에서 모든 순열을 순서대로 생성하는 작업을 해준다.

 

다른 언어에서는 직접 순열을 만들어야 한다.

 

모든 조합 만들기

서로 다른 N개의 원소 중에서 R개를 순서 없이 골라낸 것을 조합이라고 한다.

nCr의 경우의 수가 나온다.

 

위에서 6.2의 pick()함수처럼 구현하면 된다.

 

2ⁿ가지 경우의 수 만들기

n개의 질문에 대한 답이 예/아니오 중의 하나라고 할 때 존재할 수 있는 답의 경우의 수는 2ⁿ가지이다.

 

흔한 문제이며, 각 조합을 하나의 n비트 정수로 표현한다고 생각하면 1차원 for문으로 모두 시도할 수 있다.

이것은 뒤에서 기술한다.

 

 

복습

완전 탐색 레시피

1. 완전 탐색은 존재하는 모든 답을 하나씩 검사하므로, 걸리는 시간은 가능한 답의 수에 정확히 비례한다.

2. 가능한 모든 답의 후보를 만드는 과정을 여러 개의 선택으로 나눈다.

3. 그 중 하나의 조각을 선택해 답의 일부를 만들고 나머지 답을 재귀 호출을 통해 완성한다.

4. 조각이 하나밖에 남지 않은 경우, 혹은 하나도 남지 않은 경우 답을 생성 한 것이니, 기저 사례로 처리한다.

 

즉, 답을 만드는 과정을 나누고 재귀로 답의 일부를 만들고 나머지를 재귀 호출로 완성한다.

결과가 나온 경우 처리.

 

기저 사례

나누어서 처리

재귀

 

처리된 것과 처리안된 것을 나누어서 관리.

shall

할, 하

1. sometimes used with 'I' and 'we' to talk about the future.

때때로/사용된다/'I'와 'we'와 함께/말하기위해/미래에 대해

I shall tell you tomorrow.

는 말하겠다 너에게 내일

We shall never give up.

우리는 절대 포기하지 않겠다.

 

will과 비교하기.

 

2. [FORMAL] used in questions to offer to do something, ask for advise, or make a suggestion

사용된다/질문에서/제공하기위해/무언가 하는 것을, /조언을 구하기 위해, /제안을 하기위해

Shall I tell him you're here?

~할까/내가/말ㅎ(말할까?)/그에게/너가 여기있는 거

What shall we do?

무엇을/~할까/우리가/하

 

예문을 보면 shall은 I, We와 쓰이고 Will은 you랑 쓰이는 것으로 보인다.

 

개관

어떤 작업이 주어졌을 때 컴퓨터가 이 작업을 해결하는 방법을 알고리즘이라 한다.

 

알고리즘은 알고리즘이 사용하는 시간과 공간으로 평가할 수 있다.

 

 

04 알고리즘의 시간 복잡도 분석

시간복잡도란 가장 널리 사용되는 알고리즘의 수행 시간 기준으로, 알고리즘이 실행되는 동안 수행하는 기본적인 연산의 수를 입력의 크기에 대한 함수로 표현한 것.

 

보통 빅오 표기법을 이용해 표현한다.

 

주먹구구 수행시간 짐작

입력의 크기를 시간 복잡도에 대입해서 얻은 반복문 수행 횟수에 대해, 1초당 반복문 수행 횟수가 1억(10^8)을 넘어가면 시간 제한을 초과할 가능성이 있다.

 

주먹구구는 주먹구구이다.

실제 내부 반복문은 더 높을 수 있다. 

파일 입출력, 실수 연산이 많다면 더 오래걸린다.

메모리 사용 패턴이 복잡한경우 더 빨라질 수 있다. 캐시 사용.

언어와 컴파일러 차이로 속도가 달라진다.

하드웨어 차이.

 

실제 적용

1차원 배열에서 연속된 부분 구간 중 그 합이 최대인 구간을 찾는 문제.

예를 들어 [-7, 4, -3, 6, 3, -8, 3, 4]에서 최대 합을 갖는 부분 구간은 [4, -3, 6, 3]으로 그 합은 10이다.

 

첫번째, 주어진 배열의 모든 부분 구간을 순회하면서 그 합을 계산하는 알고리즘.

 

가장 무식한 방법

//numeric_limits는 해당 자료형의 표현 한계치를 구할 때 사용한다.
//아래 경우에는 int의 최소 표현 값을 반환한다.
const int MIN = numeric_limits<int>::min();

//A[]의 연속된 부분 구간의 최대 합을 구한다. 시간 복잡도O(N³)
//비효율적인 최대합 구하는 알고리즘
//모든 경우의 수를 다 계산해서 구한다.
int inefficientMaxSum(const vector<int>& A){
    int N = A.size(), ret = MIN;
    for(int i=0; i<N;++i)
        for(int j=i; j<N; ++j)
        {
            //구간 A[i..j]의 합을 구한다.
            int sum = 0;
            for(int k=i; k<=j; ++k)
                sum += A[k];
            ret = max(ret, sum);
        }
    
    return ret;
}

 

sum을 구할 때, 처음부터 더해주는 부분이 중복된다.

sum을 구할 때 처음부터 다시 구하지 않도록 수정한다.

 

//A[]의 연속된 부분 구간의 최대 합을 구한다. 시간복잡도:O(N²)
int betterMaxSum(const vector<int>& A)
{
    int  = A.size(), ret = MIN;
    for(int i=0; i<N; ++i)
    {
        int sum = 0;
        for(int j = i; j <N; ++j)
        {
            sum += A[j];
            ret = max(ret, sum);
        }
    }
    return ret;
}

 순차적으로 더 하면서 for문이 하나 사라졌다.

 

분할 정복 기법을 이용하면 더욱 빠른 시간에 동작하는 알고리즘을 설계할 수 있다.

입력받은 배열을 우선 절반으로 잘라 왼쪽 배열과 오른쪽 배열로 나눈다.

정답은 왼쪽 배열에 있을 수도, 오른쪽에 있을 수도, 두배열 사이에 걸쳐있을 수도 있다.

 

각 경우의 답을 재귀함수와 탐욕법을 이용해서 계산하면, 분할 정복 알고리즘이 된다.

//A[lo..hi]의 연속된 부분 구간의 최대 합을 구한다. 시간 복잡도 O(N*logN)
int fastMaxSum(const vector<int> &A, int lo, int hi)
{
    //기저 사례: 구간의 길이가 1인 경우. 하나짜리.
    if(lo == hi) return A[lo];
    
    //배열을 A[lo..mid], A[mid+1..hi]로 나눈다.
    int mid = (lo+hi)/2;
    
    //두 부분에 걸쳐있는 경우와 하나에만 속한 경우를 나눠 계산
    
    //두 부분에 모두 걸쳐있는 최대 합 구간을 찾는다.
    //이 구간은 A[i..mid]와 A[mid+1..j] 형태를 갖는 구간의 합으로 이루어진다.
    //중앙은 붙어있어야 하므로 양쪽으로 늘어나면서 최대 값을 구한다.
    
    //A[i..mid] 형태를 갖는 최대 구간을 찾는다.
    int left = MIN, right = MIN, sum=0;
    for(int i = mid; i>=lo; --i)
    {
        sum += A[i];
        left = max(left, sum);
    }
    
    //A[mid+1..j] 형태를 갖는 최대 구간을 찾는다.
    sum = 0;
    for(int j=mid+1; j<=hi; ++j)
    {
        sum += A[j];
        right = max(right, sum);
    }
    
    //최대 구간이 두 조각 중 하나에만 속해 있는 경우의 답을 재귀 호출로 찾는다.
    int single = max(fastMaxSum(A, lo, mid), fastMaxSum(A, mid+1, hi));
    
    //두 경우 중 최대 치를 반환한다.
    return max(left + right, single);
}

 

이 문제를 선형시간에 푸는 방법은 동적계획법 사용이다.

A[i]를 오른쪽 끝으로 갖는 구간의 최대 합을 반환하는 함수  maxAt(i)를 정의해보자.

A[i]에서 끝나는 최대 합 부분 구간은 항상 A[i] 하나만으로 구성되어 있거나, A[i-1]을 오른쪽 끝으로 갖는 최대 합 부분 구간의 오른쪽에 A[i]를 붙인 형태로 구성되어 있습니다.

A[i]를 오른쪽 끝으로 가져야 하기에.. A[i]혼자거나, A[i] + maxAt(i-1)이다.

 

따라서 점화식으로 표현하면 다음과 같다.

maxAt(i) = max(A[i], maxAt(i-1) + A[i]) = max(0, maxAt(i-1)) + A[i]

//A[]의 연속된 부분 구간의 최대 합을 구한다. 시간 복잡도:O(N)
int fastestMaxSum(const vector<int>& A)
{
    int N = A.size(), ret = MIN, psum = 0;
    for(int i = 0; i<N; ++i)
    {
        //이전 까지 계산한 값에 현재 요소를 더한 것과 현재 요소를 비교하여 큰 것을 psum이 할당.
        //이전까지 계산한 값+현재 요소가 현재 요소보다 작다면 잘리는 효과.
        psum = max(psum, 0) + A[i];
        //기존 계산 값과, 새로 계산한 값 중 큰 것을 ret에 할당.
        ret = max(psum, ret);
    }
    return ret;
}

 

 

4.7 계산 복잡도 클래스: P, NP, NP-완비

계산 복잡도 이론에서는 다항 시간 알고리즘이 존재하는 문제들의 집합을 P 문제라고 한다.

다항시간 알고리즘이 존재하지 않으면 NP.

NP문제란 답이 주어졌을 때 이것이 정답인지를 다항 시간 내에 확인할 수 있는 문제를 의미한다.

 

임의의 NP문제를 다항식 시간 내에 'A' 문제로 환원(reduction 또는 transformation)할 수 있는 경우, 이 'A'문제를 'NP-난해(NP-hard) 문제'라고 부른다. NP-난해 문제 중에는 NP 문제가 아닌 것도 있다.

 

NP 문제들 중에서 NP-난해 문제인 것을 가리켜 'NP-완전(NP-complete) 문제'라고 부른다. NP-완전 문제를 풀 수 있으면 모든 NP 문제를 풀 수 있게 되는 셈이므로 NP 문제들 중에서는 가장 핵심이 되는 문제들인 셈이다.

 

 

05 알고리즘의 정당성 증명

수학적 귀납법과 반복문 불변식

수학적 귀납볍은 반복적인 구조를 갖는 명제들을 증명하는 데 유용하게 사용되는 증명 기법입니다.

 

단계 나누기: 증명하고 싶은 사실을 여러 단계로 나눈다.

첫단계 증명: 그 중 첫 단계에서 증명하고 싶은 내용이 성립함을 보입니다.

귀납 증명: 한 단계에서 증명하고 싶은 내용이 성립한다면, 다음 단계에서도 성립함을 보인다.

 

반복문 불변식

귀납법은 알고리즘의 정당성을 증명할 때 유용하게 사용되는 기법이다.

반복문 불변식이란 반복문의 내용이 한 번 실행될 때마다 중간 결과가 우리가 원하는 답으로 가는 길 위에 잘 있는지 명시하는 조건이다.

 

1.반복문 진입시에 불변식이 성립함을 보인다.

2.반복문 내용이 불변식을 깨뜨리지 않음을 보인다. 다르게 말하면, 반복문 내용이 시작할 때 불변식이 성립했다면 내용이 끝날 때도 불변식이 항상 성립함을 보인다.

3. 반복문 종료 시에 불변식이 성립하면 항상 우리가 정답을 구했음을 보인다.

 

//(*)불변식은 여기에서 성립해야 한다.
while(조건){
    ..
    //(**)불변식은 여기에서도 성립해야한다.
}

 

반복문 안에서 변하면 안되는 조건을 어기지 않는지 확인하는 과정이다.

 

단정문을 통해서 반복문 불변식을 강제할 수 있다.

 

 

비둘기집의 원리

비둘기집 원리는 간단하게 말해서 n+1개의 물건을 n개의 상자에 넣은 경우, 최소한 한 상자에는 그 물건이 반드시 두 개 이상 들어있다는 원리를 말한다. 보통 비둘기와 비둘기집의 형태로 비유되어 쓰이기 때문에, 비둘기 집의 원리라고 불린다.

유니티 에디터 인터페이스

메인 에디터 창은 몇 개의 창(윈도우, 뷰)으로 이루어져있다.

유니티에는 다양한 종류의 뷰(창)가 있고 각각 다른 역할을 가지고 있다.

 

에디터의 모양은 개인의 취향에 따라 다를 수 있다.

 

기본 윈도우 배열은 일반적으로 많이 사용되는 것들로 배치되어있다.

가장 일반적이고 실용적인 윈도우 배열은 아래와 같다.

 

프로젝트 창

프로젝트에서 사용할 수 있는 에셋의 라이브러리를 보여준다.

프로젝트에 에셋을 임포트하는 경우 여기에 나타난다.

씬뷰

씬을 편집하고 탐색할 수 있다. 씬뷰는 2D나 3D로 볼 수 있다.

 

Hierarchy 창

씬안에 있는 객체를 계층적으로 나타낸다. 

씬에 있는 객체는 모두 들어가있다.

이 창을 통해 어떤 객체가 다른 객체에 붙어잇는지 구조적으로 알 수 있다.

 

Inspector 창

현재 선택된 객체의 속성을 보거나 편집할 수 있게 해준다.

다른 종류의 객체는 다른 속성들을 갖는다.

툴바

툴바는 많이 사용되는 기능들이 들어가 있다. 

왼쪽에는 씬과 씬안의 객체를 조작할 수 있는 기본적인 툴들이 있다.

중앙에는 재생, 일시정지, 스텝 제어 버튼이 있다.

오른쪽에는 유니티 클라우드 서비스, 유니티 계정에 접근할 수 잇는 버튼이 있다.

그리고 레이어 메뉴와 레이아웃 메뉴가 있다.

 

툴바는 창이 아니다. 그래서 배열을 바꿀 수 없다.

 

 

출처

https://docs.unity3d.com/kr/530/Manual/LearningtheInterface.html

'개발 > 유니티' 카테고리의 다른 글

[유니티] 1. 설치하기  (0) 2019.12.21

+ Recent posts