Unity SDK 설정
FirstLook Unity SDK를 사용하면 Unity 게임에서 FirstLook과 연동할 수 있습니다. SDK는 Steam 및 Google Play 인증, 인게임 설문조사, 세션 추적, 커스텀 이벤트, 커스텀 지속 시간 이벤트, 플레이어 조회, PlayFab 아이덴티티 연동, 엔타이틀먼트, 플레이테스트 워터마킹을 지원합니다.
SDK는 두 개의 Unity 패키지로 제공됩니다:
com.pragma.firstlook.core는 인증, 세션, 애널리틱스, 설문조사 전송을 위한 필수 런타임 패키지입니다.com.pragma.firstlook.ui는 core 위에 구축된 선택적 네이티브 설문조사 UI 패키지입니다.
주요 통합 진입점은 FirstLookClient이며, FirstLookBootstrap.InitializeWithSettings(...)를 통해 초기화합니다. UI 패키지를 설치하면 FirstLookSurveyPresenter가 네이티브 인게임 설문조사 렌더링을 위한 주요 패키지 진입점이 됩니다.
이 설정 가이드에서는 MyGame이라는 이름의 Unity 프로젝트가 있다고 가정합니다.
사전 준비
섹션 제목: “사전 준비”관리자 대시보드에서 FirstLook Unity SDK를 다운로드하세요.

FirstLook에서 Google Play를 설정하세요. 비공개 테스트 트랙 구성, 필수 OAuth 2.0 자격 증명 생성, FirstLook에 클라이언트 ID 추가 방법은 Google Play 연동 가이드를 참고하세요.
구체적으로, FirstLook 대시보드의 Config > Google Play에 Web application OAuth 2.0 클라이언트 ID(Android 클라이언트 ID가 아님)를 추가해야 합니다. 또한 Google이 빌드에서 오는 로그인 요청을 수락할 수 있도록 앱의 패키지 이름과 SHA-1 지문으로 등록된 Android OAuth 클라이언트도 필요합니다.
설정에 필요한 값들을 수집하세요:
- FirstLook 게임 설정에서
gameSlug - FirstLook 도메인 설정에서
clientUrl
- FirstLook 게임 설정에서
FirstLook Unity 패키지 설치
섹션 제목: “FirstLook Unity 패키지 설치”FirstLook Unity SDK를 다운로드하고 FirstLook에서 게임을 설정했다면, Unity 프로젝트에 패키지를 설치합니다.
FirstLookUnitySdk.zip(관리자 대시보드에서 다운로드한 파일)의 압축을 풀어com.pragma.firstlook.core및com.pragma.firstlook.ui패키지 tarball을 추출합니다.- Unity 에디터에서
Window > Package Manager를 엽니다. + > Add package from tarball...을 선택하고 zip에서 추출한com.pragma.firstlook.coretarball을 설치합니다. 이것은 필수 패키지입니다.패키지로 제공되는 네이티브 인게임 설문조사 UI를 원한다면
com.pragma.firstlook.ui에 대해서도 동일한Add package from tarball...과정을 반복합니다. 설문조사 UI를 직접 렌더링할 계획이라면 이 패키지를 건너뛸 수 있습니다.플랫폼 인증 의존성을 추가합니다:
Packages/manifest.json에 Steamworks.NET을 추가합니다.{"dependencies": {"com.rlabrecque.steamworks.net": "https://github.com/rlabrecque/Steamworks.NET.git?path=/com.rlabrecque.steamworks.net#2025.163.0"}}Steamworks.NET이 설치되면 Unity가 자동으로
FIRSTLOOK_STEAMWORKS를 정의하며, 이를 통해FirstLookSteamHelper가 활성화됩니다.FirstLook SDK는 원시 Google ID 토큰을 받으므로, ID 토큰을 제공하는 Google Sign-In 라이브러리라면 무엇이든 사용할 수 있습니다. 예를 들어 Google Play Games Plugin for Unity나 Google Sign-In Unity Plugin을 사용할 수 있습니다.
선호하는 Google Sign-In 라이브러리를 설치하고, FirstLook 대시보드에 추가한 Web application 클라이언트 ID로 구성합니다. 반드시 동일한 클라이언트 ID여야 합니다 — 로그인 시작과 결과로 나온 ID 토큰 검증 모두에 사용됩니다.
사용자가 로그인한 후 라이브러리에서 ID 토큰을 가져와
AuthenticateWithGoogle(idToken)에 전달합니다. 정확한 API는 라이브러리마다 다릅니다:- Google Play Games Plugin:
PlayGamesClientConfiguration에서RequestIdToken = true를 설정한 다음, 로그인 후((PlayGamesLocalUser)Social.localUser).GetIdToken()으로 토큰을 가져옵니다. - Google Sign-In Unity Plugin:
GoogleSignIn.DefaultInstance.SignIn()이 완료되면 결과에서GoogleSignInUser.IdToken을 읽습니다.
전체 로그인 설정은 선택한 라이브러리의 문서를 참고하세요.
- Google Play Games Plugin:
FirstLookSettings 구성
섹션 제목: “FirstLookSettings 구성”Unity SDK는 FirstLookSettings 에셋에서 구성 정보를 읽습니다.
Unity 에디터에서
Assets/Resources/FirstLookSettings.asset을 생성합니다:Assets > Create > FirstLook > Settings
에셋에서 필수 필드를 구성합니다:
apiUrl:https://api.firstlook.ggclientUrl:https://<game-slug>.firstlook.gggameSlug: FirstLook 게임 슬러그buildVersion: 애널리틱스 이벤트에 첨부되는 선택적 빌드 레이블 (빌드 버전 참고)
프로젝트에서 다른 동작이 필요한 경우가 아니라면 재시도, 큐, 로깅 설정은 기본값으로 유지하세요.
FirstLookSurveyPresenter와 FirstLookAutoLifecycle은 할당된 설정이 없을 때 FirstLookSettings.LoadFromResources()로 설정을 로드합니다. Resources/FirstLookSettings를 읽으며, 에디터 및 개발 빌드에서는 Resources/FirstLookSettingsLocal이 존재할 경우 이를 우선합니다. Local 에셋을 사용하면 출시용 에셋을 변경하지 않고 로컬 빌드를 테스트 게임에 연결할 수 있습니다.
clientUrl은 ActivateSurveyBrowserOverlay(...)를 통해 브라우저 제공 설문조사를 열 계획인 경우에만 필요합니다.
인증 부트스트랩
섹션 제목: “인증 부트스트랩”Unity 통합의 권장 방식은 호스트 소유 부트스트랩입니다. FirstLook를 한 번 초기화하고, 플랫폼으로 인증한 다음, 세션을 명시적으로 시작합니다.
Steamworks가 이미 초기화되어 있는지 확인한 후 인증하고 세션을 시작합니다.
using Pragma.FirstLook;using UnityEngine;
public sealed class FirstLookStartup : MonoBehaviour{ [SerializeField] private FirstLookSettings firstLookSettings;
private FirstLookClient _client;
private async void Start() { var settings = firstLookSettings != null ? firstLookSettings : Resources.Load<FirstLookSettings>("FirstLookSettings");
if (settings == null) { Debug.LogError("[FirstLookStartup] Missing FirstLookSettings."); return; }
_client = FirstLookBootstrap.InitializeWithSettings(settings);
#if FIRSTLOOK_STEAMWORKS var ticket = FirstLookSteamHelper.GetSessionTicket(); if (string.IsNullOrWhiteSpace(ticket)) { Debug.LogError("[FirstLookStartup] Steam ticket unavailable. Make sure Steamworks is initialized first."); return; }
var result = await _client.AuthenticateAndStartSessionAsync( FirstLookAuthRequest.Steam(ticket, FirstLookSteamHelper.GetAppId()));
if (!result.Success) { Debug.LogError($"[FirstLookStartup] FirstLook startup failed: {result.AuthResult?.Error}"); return; }
Debug.Log($"[FirstLookStartup] FirstLook ready. Session: {result.SessionId}");#else Debug.LogError("[FirstLookStartup] Steamworks.NET is not installed.");#endif }}Google Sign-In 라이브러리를 사용하여 Google ID 토큰을 받은 다음 FirstLook에 전달합니다.
using Pragma.FirstLook;using UnityEngine;
public sealed class FirstLookStartup : MonoBehaviour{ [SerializeField] private FirstLookSettings firstLookSettings;
private FirstLookClient _client;
// Google Sign-In 라이브러리(예: Google Play Games Plugin 또는 Google Sign-In Unity Plugin)에서 // Google ID 토큰을 받은 후 이 메서드를 한 번 호출합니다. public async void AuthenticateWithGoogle(string googleIdToken) { var settings = firstLookSettings != null ? firstLookSettings : Resources.Load<FirstLookSettings>("FirstLookSettings");
if (settings == null) { Debug.LogError("[FirstLookStartup] Missing FirstLookSettings."); return; }
_client = FirstLookBootstrap.InitializeWithSettings(settings);
if (string.IsNullOrWhiteSpace(googleIdToken)) { Debug.LogError("[FirstLookStartup] Google ID token was empty."); return; }
var result = await _client.AuthenticateAndStartSessionAsync( FirstLookAuthRequest.GoogleIdToken(googleIdToken));
if (!result.Success) { Debug.LogError($"[FirstLookStartup] FirstLook startup failed: {result.AuthResult?.Error}"); return; }
Debug.Log($"[FirstLookStartup] FirstLook ready. Session: {result.SessionId}"); }}로그인 테스트
섹션 제목: “로그인 테스트”Unity SDK가 설치 및 구성되었으면 로컬에서 Steam 통합을 테스트합니다.
FirstLook 시작 코드가 실행되기 전에 Steamworks를 초기화합니다.
예를 들어,
FirstLookSteamHelper.GetSessionTicket()을 호출하기 전에Awake()에서SteamAPI.Init()을 호출하는 씬 오브젝트를 추가합니다.
- Unity 에디터에서 플레이를 누르거나 개발 빌드를 실행합니다.
Unity 콘솔에서 부트스트랩 코드의 성공적인 시작 로그를 확인합니다.
- 예:
[FirstLookStartup] FirstLook ready. Session: 8c3b8f66-...
- 예:
Steam 설정이 완료되지 않은 경우 다음과 같은 실패 신호 중 하나가 나타납니다:
[SteamManager] SteamAPI.Init() failed...[FirstLookStartup] Steam ticket unavailable...[FirstLookStartup] FirstLook startup failed: ...
Google Play Services가 있는 기기 또는 에뮬레이터에서 Google Play 통합을 테스트합니다.
Google Sign-In 라이브러리를 초기화하고 로그인 흐름을 실행하여 Google ID 토큰을 받습니다.
부트스트랩 코드의
AuthenticateWithGoogle(idToken)에 토큰을 전달합니다.Unity 콘솔에서 성공적인 시작 로그를 확인합니다.
- 예:
[FirstLookStartup] FirstLook ready. Session: 8c3b8f66-...
- 예:
인증에 실패하면 다음과 같은 신호 중 하나가 나타납니다:
[FirstLookStartup] Google ID token was empty.[FirstLookStartup] FirstLook startup failed: Invalid Google ID token: ...
인게임 설문조사 테스트
섹션 제목: “인게임 설문조사 테스트”로그인과 세션 시작이 정상적으로 동작하면 Unity에서 인게임 설문조사를 트리거할 수 있습니다.
게임 클라이언트 배포가 활성화된 설문조사를 생성합니다. 설문조사 만들기를 참고하세요.
새로 만든 설문조사에 대한 트리거를 설정합니다. 트리거 설정하기를 참고하세요.
패키지로 제공되는 네이티브 설문조사 UI를 원한다면
com.pragma.firstlook.ui를 설치하고 씬에FirstLookSurveyPresenter와FirstLookSurveyCanvas를 추가합니다.FirstLookSurveyPresenter는OnNewNativeSurveyAvailable을 구독하고, 활성 설문조사를 캐시하며,TryShowCurrentSurvey()를 통해 다시 열 수 있습니다.UI 패키지와 함께 제공되는 설문조사 프리팹, 스킨, 테마 에셋에서 시작한 다음, 커스터마이징이 필요하면 프로젝트로 복제하세요.
브라우저 제공 설문조사를 원한다면 호스트 코드에서
OnNewBrowserSurveyAvailable을 구독하고ActivateSurveyBrowserOverlay(surveyUuid)를 호출합니다.- 제공되는 Unity UI 패키지는 브라우저 제공 설문조사를 자동으로 열지 않습니다.
게임에서 설문조사를 트리거합니다:
await _client.PostSurveyTriggerEventAsync("match.completed");
완전히 커스텀 설문조사 UI를 구축하는 경우 com.pragma.firstlook.ui를 완전히 건너뛰고 FirstLookClient의 core 설문조사 이벤트를 직접 구독할 수 있습니다.
세션 및 이벤트
섹션 제목: “세션 및 이벤트”세션 추적
섹션 제목: “세션 추적”Unity SDK는 설치만으로 세션을 시작하지 않습니다. 세션은 호스트가 StartSessionAsync()를 호출하거나 AuthenticateAndStartSessionAsync(...)가 성공적으로 완료될 때 시작됩니다.
세션이 시작되면 SDK는 세션을 종료하거나 앱이 종료될 때까지 활성 세션을 추적합니다. 내부적으로 FirstLookRuntimeDriver는 애플리케이션 종료 시 최선의 방법으로 EndSessionAsync()를 호출하려 시도합니다. FirstLook 계정을 아직 생성하지 않은 플레이어도 추적됩니다 — 대시보드에서 연결되지 않은 플레이어로 표시되며 플랫폼 계정이 연결됩니다.
세션이 기록되기 시작하면 Retention 탭의 애널리틱스 페이지와 각 플레이어 프로필에서 플레이어 활동 및 세션 지속 시간 데이터를 확인할 수 있습니다.
커스텀 이벤트
섹션 제목: “커스텀 이벤트”세션 추적 외에도 스튜디오에서 가장 중요한 게임플레이 이벤트(영웅 선택, 매치 결과, 스토어 구매 등)를 직접 계측할 수 있습니다. FirstLookClient의 PostCounterEventAsync(...)를 사용하여 정수 값을 가진 이름 있는 카운터를 보냅니다:
public async void HandleHeroSelected(){ if (_client == null || !_client.IsSessionActive) return;
await _client.PostCounterEventAsync("loadout.hero-a-selected", 1);}이벤트 이름 지정 및 그룹화
섹션 제목: “이벤트 이름 지정 및 그룹화”이벤트 이름은 <category>.<event-type> 규칙을 따릅니다. 이 패턴을 사용하면 FirstLook이 애널리틱스 페이지와 플레이어 프로필에서 관련 이벤트를 자동으로 그룹화하여 카테고리별로 메트릭을 쉽게 탐색할 수 있습니다.
게임에서 이벤트가 발생하는 위치를 반영하는 카테고리 네임스페이스를 선택하세요 — 예: match, lobby, menu, store, in-game. 필요한 만큼 카테고리를 자유롭게 정의할 수 있습니다.
파라미터
섹션 제목: “파라미터”선택적 파라미터를 전달하면 새로운 이벤트 이름을 정의하지 않고도 하나의 이벤트를 변형으로 분리할 수 있습니다. 예를 들어 플레이어가 시작한 레벨이나 구매한 아이템 등을 구분할 때 유용합니다:
public async void HandleLevelStarted(string levelId){ if (_client == null || !_client.IsSessionActive) return;
await _client.PostCounterEventAsync("level.started", levelId, 1);}FirstLook은 변형을 level.started#forest_3으로 저장하고, 애널리틱스 페이지의 기본 이벤트 하위에 차트로 표시하며, 모든 변형을 기본 합계에 더합니다. 파라미터는 트림 및 소문자로 변환되고, 최대 64자이며, #을 포함할 수 없습니다. 빈 파라미터는 일반 이벤트를 전송하며, 두 인수 오버로드는 변경 없이 계속 작동합니다. 각 고유 파라미터가 별도의 변형으로 추적되므로 값의 집합을 작게 유지하세요.
커스텀 지속 시간 이벤트
섹션 제목: “커스텀 지속 시간 이벤트”카운터 이벤트는 무언가가 발생했음을 기록하지만, 때로는 얼마나 오래 걸렸는지 알아야 할 때도 있습니다. 지속 시간 이벤트를 사용하면 게임의 두 명시적 시점 — 매치, 로딩 화면, 메뉴에서 보낸 시간, 또는 추적하려는 다른 구간 — 사이의 경과 시간을 측정할 수 있습니다.
활동이 시작될 때 StartDurationEventAsync(...)를, 완료될 때 EndDurationEventAsync(...)를 호출합니다. SDK가 타이밍과 전송을 처리하므로 이름만 제공하면 됩니다.
public async void OnMatchStart(){ if (_client == null || !_client.IsSessionActive) return;
await _client.StartDurationEventAsync("match.round");}
public async void OnMatchEnd(){ if (_client == null || !_client.IsSessionActive) return;
await _client.EndDurationEventAsync("match.round");}이벤트 이름 지정 및 그룹화
섹션 제목: “이벤트 이름 지정 및 그룹화”지속 시간 이벤트 이름은 카운터 이벤트와 동일한 <category>.<event-type> 규칙을 따릅니다. FirstLook은 애널리틱스 페이지에서 카테고리 접두사별로 자동 그룹화합니다.
빌드 버전
섹션 제목: “빌드 버전”세션, 카운터, 지속 시간 이벤트 각각에 build_version을 첨부할 수 있습니다. FirstLook은 이를 불투명한 레이블로 처리하고 전송된 내용을 그대로 저장하므로 형식은 전적으로 스튜디오의 선택입니다: 1.4.2와 같은 semver, CI 빌드 번호, 브랜치+커밋 문자열 등을 사용할 수 있습니다. 하나의 규칙을 선택하고 일관되게 유지하세요. 플레이어 필터의 빌드 필터는 정확한 값과 일치합니다.
우선순위 순으로 세 가지 방법으로 제공할 수 있습니다:
| 소스 | 방법 | 적합한 경우 |
|---|---|---|
| 런타임 오버라이드 | client.OverrideBuildVersion("1.4.2") | 시작 시 자체 빌드 파이프라인에서 버전 읽기 |
| 자동 | FirstLookSettings의 buildVersionSource | 설정 불필요: ApplicationVersion은 Player Settings를 읽고, SteamAppId는 실행 중인 Steam 앱 ID를 읽어 Steam Playtest 앱과 메인 앱을 구분 |
| 설정 필드 | FirstLookSettings의 buildVersion | 빌드별로 수동으로 설정하는 레이블 |
buildVersionSource는 기본적으로 Manual로 설정되어 있어 buildVersion 필드를 그대로 사용합니다. Steamworks.NET 없이 SteamAppId를 사용하는 경우처럼 확인할 수 없는 소스는 buildVersion 필드로 폴백됩니다.
플레이어
섹션 제목: “플레이어”현재 플레이어
섹션 제목: “현재 플레이어”GetCurrentPlayerAsync()를 호출하면 인증된 플레이어의 FirstLook 레코드를 읽을 수 있습니다. 예를 들어 클레임 프롬프트 표시 여부를 결정하는 데 사용할 수 있습니다:
public async void RefreshPlayer(){ var me = await _client.GetCurrentPlayerAsync(); if (me == null) return;
if (me.Player.IsUnlinked) await _client.GetPlayerClaimAsync();}클라이언트가 인증되지 않았거나 요청이 실패하면 null을 반환합니다.
| 필드 | 내용 |
|---|---|
Player.Id | FirstLook 플레이어 ID |
Player.State | 플레이어의 상태 (소문자 문자열, 예: unlinked 또는 onboarded) |
Steam.SteamId | 연결된 Steam ID. Steam 계정이 연결되지 않은 경우 Steam은 null |
Discord.DiscordId | 연결된 Discord ID. Discord 계정이 연결되지 않은 경우 Discord는 null |
Role.Id, Role.Name | 플레이어의 역할 |
State 문자열을 직접 비교하는 대신 Player.IsUnlinked와 Player.IsLinked를 확인하세요. FirstLook이 향후 상태를 추가할 수 있기 때문입니다.
연결되지 않은 플레이어 온보딩
섹션 제목: “연결되지 않은 플레이어 온보딩”SDK는 연결되지 않은 상태로 새 플레이어를 생성합니다. 이 플레이어들에게 계정을 클레임하고 프로필 완성을 위한 온보딩을 완료할 수 있는 링크를 제공할 수 있습니다. 이를 통해 이메일, 보상, Discord, 친구 초대 및 해당 역할이 제공하는 모든 기능을 활성화할 수 있습니다.
게임 내 플로우
섹션 제목: “게임 내 플로우”연결되지 않은 플레이어를 온보딩하려면 먼저 대시보드에서 From Game 플로우를 구성합니다.
- SDK 구성 페이지에서 Unlinked Claiming 토글을 활성화합니다.
- From Game 플로우의 Claim, Onboarding, Complete 단계를 구성합니다.
- 선택 사항 - 역할을 구성합니다.
클레임 링크 제공
섹션 제목: “클레임 링크 제공”From Game 플로우가 설정되면 게임 클라이언트에서 FirstLookClient의 **GetPlayerClaimAsync()**를 호출하고 OnPlayerClaimAvailable 이벤트를 구독할 수 있습니다. 이벤트가 트리거되면 URL과 Base64로 인코딩된 QR 코드가 제공됩니다. 이 링크나 QR 코드를 플레이어에게 표시하여 이메일 인증과 From Game 플로우에 구성된 온보딩 단계를 완료하도록 합니다.
외부 아이덴티티 연동
섹션 제목: “외부 아이덴티티 연동”플레이어가 인증된 후 외부 서비스의 플레이어 ID를 FirstLook에 알려주면, FirstLook이 두 레코드를 매칭할 수 있습니다. 현재 PlayFab만 지원되는 제공자입니다.
var result = await _client.LinkIdentityAsync(FirstLookIdentityProvider.Playfab, playfabId);if (!result.Success){ Debug.LogWarning($"PlayFab link failed (status={result.StatusCode}): {result.Error}");}플레이어 자신의 ID를 다시 연동하는 것은 성공하므로 매번 시작 시 안전하게 호출할 수 있습니다.
| 상태 | 의미 |
|---|---|
403 | 게임에서 이 제공자에 대한 연동이 활성화되지 않았으며 result.Code가 FeatureNotEnabled입니다. 활성화하려면 FirstLook에 문의하세요. |
409 | 해당 ID가 이 게임의 다른 플레이어에 이미 연동되어 있습니다. |
422 | ID가 비어 있거나 64자를 초과합니다. |
실패는 재시도 큐에 추가되지 않고 반환됩니다.
엔타이틀먼트
섹션 제목: “엔타이틀먼트”엔타이틀먼트는 FirstLook에서 플레이어에게 부여하는 인게임 아이템입니다. SDK는 FirstLook 타입의 엔타이틀먼트를 전달합니다: 대시보드의 Entitlements에서 생성한 다음 플레이어에게 부여합니다. 예를 들어 Grant Entitlement 대량 작업을 사용할 수 있습니다. 게임은 플레이어의 미지급 엔타이틀먼트를 가져와 아이템을 부여하고, 중복 전달을 방지하기 위해 각각을 사용 처리합니다. Pragma 엔타이틀먼트는 Pragma를 통해 전달되며 여기에 나타나지 않습니다. 대시보드에 Entitlements가 표시되지 않으면 FirstLook에 활성화를 요청하세요.
public async void SyncEntitlements(){ var result = await _client.GetEntitlementsAsync(); if (!result.Success) { Debug.LogWarning($"Entitlements unavailable (status={result.StatusCode}): {result.Error}"); return; }
foreach (var entitlement in result.Entitlements) { // entitlement.Id로 부여를 키잉하면 재시도된 사용 처리가 아이템을 한 번만 부여합니다. MyInventory.GrantOnce(entitlement.Id, entitlement.Sku);
var redeem = await _client.RedeemEntitlementAsync(entitlement.Id); if (!redeem.Success && redeem.Error != "Entitlement already redeemed") Debug.LogWarning($"Redeem {entitlement.Id} failed (status={redeem.StatusCode}): {redeem.Error}"); }}각 FirstLookEntitlement에는 Id, EntitlementType, Name, Sku, RedeemableTypeId, CreatedAt이 포함됩니다. 아이템 매칭은 대시보드에서 설정한 Entitlement ID인 Sku로 하며, 번역되거나 이름이 변경될 수 있는 표시 문자열인 Name으로는 하지 마세요.
사용 처리는 일회성입니다. 동일한 엔타이틀먼트를 다시 사용 처리하면 400과 Entitlement already redeemed로 실패하는데, 이는 일반적으로 이전 시도가 성공했음을 의미하므로 완료된 것으로 처리하세요. 두 호출 모두 재시도 큐에 추가되지 않으며, 실패는 Success, StatusCode, Error로 반환됩니다.
워터마크 오버레이
섹션 제목: “워터마크 오버레이”SDK는 플레이테스트 빌드에 워터마크를 적용할 수 있습니다. 각 세션에는 고유한 코드가 부여되며, SDK는 해당 코드를 화면 전체에 비스듬히 타일링하여 천천히 이동시킵니다. 가운데는 항상 가려져 있어 잘라내도 제거할 수 없습니다. 스크린샷이나 스트림이 유출되면 코드를 통해 해당 플레이어와 세션을 추적할 수 있습니다.
- SDK 구성 페이지에서 Playtest Watermark 아래의 Enable Watermark를 켜고 Save Changes를 클릭합니다.
- 세션이 시작되면 SDK가 해당 세션의 코드를 가져와 오버레이를 자동으로 그립니다. 세션이 종료되면 오버레이가 제거되고, 다음 세션에는 해당 세션의 코드가 표시됩니다.
- 유출을 추적하려면 Search watermark 페이지에서 코드를 입력하여 해당 플레이어와 세션을 찾습니다.
FirstLook은 워터마크 활성화 여부만 제어합니다. 표시 방식은 프로젝트에서 설정합니다: 오버레이는 모든 다른 UI 위에 있는 화면 공간 캔버스로, 씬 로드 시에도 유지되며 입력을 차단하지 않습니다. FirstLookSettings 에셋의 Watermark 섹션에서 조정할 수 있습니다:
| 필드 | 기본값 | 범위 | 효과 |
|---|---|---|---|
color | 흰색 | 텍스트 색상 | |
opacity | 0.06 | 0 ~ 1 | 텍스트 불투명도 |
tileDensity | 5 | 1 ~ 12 | 화면 너비에 맞는 대략적인 코드 수 |
angleDegrees | 30 | 0 ~ 90 | 그리드 기울기 |
driftSpeed | 0.5 | 0 ~ 2 | 0은 그리드를 고정 |
includeCenter | true | 화면 중앙을 가린 상태로 유지 |
OnWatermarkEnabled를 구독하면 오버레이가 나타날 때 알 수 있습니다. 이벤트는 코드를 전달합니다. 오버레이는 자체적으로 렌더링되므로, 플레이어에게 세션이 워터마킹되었음을 알리는 용도로만 사용하세요:
_client.OnWatermarkEnabled += code => ShowToast("This playtest session is watermarked.");게임에 워터마킹이 활성화되지 않은 경우 게임은 오버레이 없이 실행되며 SDK는 경고를 기록합니다: Watermarking is not enabled for this game. Contact FirstLook to enable it. 이 경고를 보려면 FirstLookSettings의 logLevel을 Warning 이하로 설정하세요.
