레이블이 Unity인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Unity인 게시물을 표시합니다. 모든 게시물 표시

2019년 9월 23일 월요일

Unity - Firebase 연동 (Analytics, AdMob)

버전 : firebase_unity_sdk_6.5.0.zip

게임에서 통계 측정 및 광고 추적을 위해 Firebase 을 연동한다.
앞서 [Unity - GPGS 와 Admob 연동 및 배포 준비 작업] 연동 이후에 작업을 진행 한다.

유니티에 Firebase를 연결하는 정보는 다음 사이트에 정리되어 있다.
https://firebase.google.com/docs/unity/setup?hl=ko#available_libraries
- ADmob 연동은 별도의 unitypackage 설치 없이 웹 연결을 통해 진행 된다.


1. Firebase 패키지 추가

1-1. 프로젝트 생성

  • 홈페이지 접속
  • [프로젝트 만들기] 버튼을 선택해 생성 시도
  • 생성되어 있는 프로젝트 중 연동에 필요한 프로젝트 선택
  • 약관 선택 후 [계속]
  • "Google 애널리틱스" 사용 설정은 On 으로 지정
    - 애널리틱스 위치 : 대한 민국
    - 약관 설정
  • [계속] 버튼을 선택하면 프로젝트가 생성 됨

1-2. 앱을 추가하여 시작

  • 좌측 [Project Overview] 선택 해 Home 으로 이동
  • 유니티 아이콘을 선택해 "앱을 추가하여 시작" 진행
  • Unity 앱에 Firebase 추가 시작
    - iOS와 Android 동시 출시의 경우 둘다 등록 해야 됨
    - Register as Android app 체크
    - 패키지 이름 : 설정한 패키지 이름 작성
    - 앱 닉네임 : 게임 이름 작성
  • [다음] 버튼으로 설정 이동

1-3. 구성파일 다운로드

  • google-services.json 파일을 다운로드
  • 다운로드 한 파일을 unity 프로젝트 Asset폴더 Root로 이동
    (Assets 폴더 내의 원하는 위치에 Firebase 구성 파일을 배치 가능)
  • [다음] 버튼으로 설정 이동

1-4. Firebase SDK 추가

  • 유니티 패키지를 다운받음
  • firebase_unity_sdk_6.5.0.zip 버젼을 다운로드하여 진행
  • [다음] 버튼으로 설정 이동

1-5. 완료 단계

  • 설정이 완료 됨.
  • "콘솔로 이동" 을 선택해 설정을 종료

1-6. Project Overview 정보 

  • 페이지의 앱 설정에서 등록된 앱 정보가 유니티가 아닌 안드로이드로 표시 된다. 
  • 정보를 확인 하면 통신을 대기 하는 상태가 표시 된다.
  • 이 표시는 Analytics SDK를 추가해 빌드를 한 뒤 실행을 한 번 해야 처리 된다.
  • 정상 처리 시 - "앱에 Firebase를 추가했습니다." 라고 표시된다.
  • 우선은 현 상태로 유지하고 아래 항목을 진행 한다.

1-7. SHA-1 인증서(번외, 필요시)

  • 안드로이드 앱 등록 시 SHA-1 디버그 인증서를 요구 한다. 
  • 디버그는 인증서는 debug.keystore 파일을 의미하고, 보통 C:\Users\user\.android 폴더에 위치한다. 
  • 명령어 프롬프트를 이용해 자바가 설치된 bin 폴더로 이동 
  • keytool -exportcert -list -v -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore 명령어를 입력하면 값을 얻을 수 있다.
    (디버그에는 password가 없으므로 Enter 키 입력)
  • 실제 SHA 인증서 지문 = GooglePlayConsole에서 업로드 증명서의 SHA-1 값을 사용 하면 된다. 


2. 사전 준비

2-1. 데이터 준비

  • SDK 다운로드 : URL
  • 유니티의 .Net 버전을 4.x 로 설정
  • 다운로드한 SDK에서 dotnet4 폴더 unitypackage 를 확인
  • 애널리틱스를 사용하기 위해 FirebaseAnalytics.unitypackage 파일 저장

2-2. Unity 프로젝트에 Firebase 추가

  • 정보 : https://firebase.google.com/docs/unity/setup?hl=ko
  • 1~4단계는 진행한 "Firebase 패키지 추가"와 동일한 내용
  • 5단계 부터 진행한다.
  • FirebaseAnalytics.unitypackage 파일 import 진행
    (무언가 확인 윈도우가 뜰 때 yes 했음)

2-3. Google Play 서비스 버전 요구사항 확인

        Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
            var dependencyStatus = task.Result;
            if (dependencyStatus == Firebase.DependencyStatus.Available)
            {
                // Create and hold a reference to your FirebaseApp, 
                // FirebaseApp에 대한 참조를 작성하고 유지하십시오.
                // where app is a Firebase.FirebaseApp property of your application class.
                // 여기서 app은 애플리케이션 클래스의 Firebase.FirebaseApp 속성입니다.

                //   app = Firebase.FirebaseApp.DefaultInstance;

                // Set a flag here to indicate whether Firebase is ready to use by your app.
                // Firebase를 앱에서 사용할 준비가되었는지 표시하려면 여기에 플래그를 설정하십시오.
                Debug.Log("Firebase 초기화 완료");
            }
            else
            {
                UnityEngine.Debug.LogError(System.String.Format(
                  "Could not resolve all Firebase dependencies: {0}", dependencyStatus));
                // Firebase Unity SDK is not safe to use here.
            }
        });
  • 앱 시작 시 AnalyticsManager를 생성하고 "Start()" 에 코드 추가


3. Analytics 추가

3-1. 유니티 설정

  • 이벤트 로그 등에 대한 내용 작성이 필요
  • >>>작성중<<<


4. ADMob 연동

4-1. 연동 방법

  • Firebase 페이지 이동
  • 연결하려는 프로젝트를 선택해 페이지 이동
  • 좌측 상단의 Project Overview 우측에 있는 "톱니바퀴"(설정) 버튼 선택
  • 프로젝트 Settings 화면에서 [통합] 페이지를 선택
  • ADmob 의 앱 설정에 firebase 연결 버튼이 없다.
    (현재 위 설정을 적용 못하고 있음)



2019년 9월 5일 목요일

Unity Canvas Render Mode 설정

UGUI의 Canvas 설정 중 Render Mode 를 정리한다.
이는 2D 게임 개발 중 Canvas > Particle > Canvas 의 출력 순서를 정의하기 위한 복습 자료이다.


  1. 2D 게임을 만들면서 Main Camera가 Orthographic인 설정에서 Screen Space - Camera 모드로 설정한 Canvas를 복수로 설정하는 것이 좋다. 
  2. 이는 Canvas의 Sorting Layer와 Sort Order의 설정을 통해 Depth를 지정 한다. 
  3. 그리고 Particle System의 Renderer 항목의 Sorting Layer와 Sort Order의 설정을  Canvas 사이로 설정해 Particle 출력의 효과를 발생시킬 수 있다. 


Screen Space - Overlay 모드 

  • 캔버스가 씬 내부의 어느 곳에 있더라도 화면 전체를 덮는 모습으로 렌더링 된다.
  • Pixel Perfect
    - On으로 지정하면 UI의 픽셀의 색 그대로 표현하도록 렌더링 함
    - 경계면이 명확히 표현할 수 있음(안티 앨리어싱 없이 렌더링)
    - 다양한 UI 연출로 인한 퍼포먼스를 위해서는 Off로 사용하기를 권장
  • Sort Order
    - 렌더링 되는 순서를 수치로 설정
    - 값이 작을수록 안쪽에 렌더링 됨 


Screen Space - Camera 모드 

  • 지정된 카메라와 일정한 거리만큼 떨어진 앞쪽에 위치 
  • 카메라의 Projection 속성이 Perspective로 지정된 경우 UI 요소는 원근감이 느껴지도록 렌더링 됨 (원근감의 정도는 Field of View 속성값에 의해 결정)
  • Pixel Perfect
    - On으로 지정하면 UI의 픽셀의 색 그대로 표현하도록 렌더링 함
  • Render Camera
    - 캔버스를 렌더링할 카메라를 지정
  • Plane Distance
    - 카메라에서 캔버스까지의 거리를 설정
  • Sorting Layer
    - 캔버스의 소팅 레이어(Sorting Layer)를 지정.
    - 소팅 레이어란 2D 스프라이트를 포함한 2D 그래픽을 렌더링하는 순서를 제어하는 기능
    - Z좌표와 관계없이 렌더링 순서를 제어 할 수 있음
  • Sort Order
    - 렌더링 되는 순서를 수치로 설정


World Space 모드 

  • 설정된 Canvas는 씬에 있는 다른 게임 오브젝트와 동일한 자격으로 취급
  • Canvas의 크기는 Rect Transform 컴포넌트에 따라 정의
  • UI 요소는 씬에 있는 다른 GameObject와 함께 3D 공간에서의 위치 관계대로 렌더링 됨
  • UI요소를 씬의 일부로 다룰 때 이용하면 좋음
  • Event Camera
    - 이벤트를 처리하기 위한 카메라를 지정
    - OnClickButton()과 같은 UI 이벤트 리스너를 통해 발생 되는 결과가 적용될 대상
  • Sorting Layer
    - 캔버스의 소팅 레이어(Sorting Layer)를 지정.
  • Sort Order
    - 렌더링 되는 순서를 수치로 설정





2019년 9월 4일 수요일

Unity 비동기 로딩(LoadLevelAsync) 일시 정지(Pause)

유니티의 백그라운드에서 비동기적으로 레벨을 로드하는 동안 로딩바를 표시하는 기능과 로딩 완료 시 Play 버튼이 발생해 다른 Scene로 전환되는 기능에 대한 요약 정리



예제

  1. 더미 값을 통해 로딩이 진행 되는 과정 표시
  2. 씬 로딩 완료 후 Start 버튼 표시
  3. 버튼 선택 시 지정된 Scene로 이동

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;  // 씬 이동 처리를 위한 선언
using UnityEngine.UI;               // 게이지 이동 처리를 위한 선언

public class LoadLevelAsyncCode : MonoBehaviour
{
    // 화면에 표시되는 LoadingBar 리소스 연결
    public Slider sliderUI;
    // 화면에 표시되는 toPlay 버튼 리소스 연결
    public GameObject toPlayButtonUI;

    // 더미 시간의 설정 Min Max 값
    float dummyTimeRange_Min;
    float dummyTimeRange_Max;

    // 최초 게이지가 증가되는 더미 시간 -> 이후 본 로딩 시작
    float dummyTime;

    // 로딩 이후 시작 버튼 처리 
    bool toPlayButton;

    void Awake()
    {
        dummyTimeRange_Min = 0.8f;
        dummyTimeRange_Max = 1.5f;
        dummyTime = 0;

        // 버튼의 상태를 초기화 한다.
        toPlayButton = false;
    }

    void Start()
    {
        // UI를 처리 한다.
        sliderUI.gameObject.SetActive(true);
        toPlayButtonUI.SetActive(false);

        // 로딩을 즉시 실행
        StartCoroutine(LoadAsynchronously(1));
    }

    IEnumerator LoadAsynchronously(int _sceneIndex)
    {
        // 더미 타이머로 진행할 값을 설정
        dummyTime = Random.Range(dummyTimeRange_Min, dummyTimeRange_Max);

        // 게이지로 표현되는 loading 값 변수들
        float loadingTime = 0.0f;   // 시간 계산 용
        float progress = 0.0f;      // 게이지 용


        // 타이머 게이지 처리 
        while (loadingTime <= dummyTime)
        {
            // 프레임 당 시간을 증가 
            loadingTime += Time.deltaTime;

            // AsyncOperation 를 통한 추가 로딩 처리를 위해 0.9 값 을 백분율화 
            // 이후 opertaion.progress 는 0.9 까치 처리 되고 완료 된다.
            progress = Mathf.Clamp01(loadingTime / (0.9f + dummyTime));

            // 슬라이더바의 값 증가 처리
            sliderUI.value = progress;
            
            yield return null;
        }

        // "AsyncOperation"라는 "비동기적인 연산을 위한 코루틴을 제공"
        AsyncOperation operation = SceneManager.LoadSceneAsync(_sceneIndex);

        // 로딩 후 스타트 버튼 처리를 위한 선언
        // 이 항목이 없으면 바로 로딩 후 Scene 이동이 처리 됨
        operation.allowSceneActivation = false;

        // 로딩이 종료되기 전까지의 로딩창 게이지 처리
        while (!operation.isDone)
        {
            // 비동기 로딩 진행에 따른 게이지 처리
            progress = Mathf.Clamp01((operation.progress + loadingTime) / (0.9f + dummyTime));

            // 슬라이더 증가 처리
            sliderUI.value = progress;

            yield return null;

            // 로딩 이후의 처리 , 버튼을 누르면 씬 이동이 처리 된다.
            // UI를 반전 처리 한다.
            //sliderUI.gameObject.SetActive(false);
            toPlayButtonUI.SetActive(true);
            Debug.Log("toPlayButtonUI.SetActive(true) - Line");
            // toPlayButton 입력을 대기 한다.
            if (toPlayButton)
            {
                operation.allowSceneActivation = true;
            }

            yield return null;

        }
               
    }

    // 버튼을 입력 한다.
    public void ToPlayButton()
    {
        toPlayButton = true;
    }

}

2019년 8월 21일 수요일

unity 화면 꺼짐 방지

게임 플레이 중 디바이스의 설정에 따라 입력이 없으면 화면이 꺼지는 설정을 강제하는 코드.


// 화면이 꺼지지 않도록 설정
Screen.sleepTimeout = SleepTimeout.NeverSleep;

// 디바이스 설정에 맞추어 화면이 꺼지도록 처리 
Screen.sleepTimeout = SleepTimeout.SystemSetting;

출처 : https://docs.unity3d.com/kr/2018.4/ScriptReference/Screen-sleepTimeout.html

2019년 7월 19일 금요일

Unity 2D 게임 최적화

간단하게 할 수 있는 최적화 항목을 정리해 둔다.


Application.targetFrameRate 
- 특정 프레임 레이트로 렌더린 하도록 설정
- 모바일에서는 30이 기본으로 설정되어 있음 이를 60으로 설정
- Application.targetFrameRate = 60;


QualitySettings.vSyncCount
- 화면 갱신율의 절반으로 프레임률을 제한할 때 사용
- 수직 동기화를 할 경우 1로 설정
- QualitySettings.vSyncCount = 1;
- Edit > Project Setting > Quality > Other 에서 설정


글로벌 일루미네이션 설정
- lighting을 제어하는 게임이 아닌 경우 관련된 설정을 모두 Off
- https://docs.unity3d.com/kr/530/Manual/GlobalIllumination.html
- Precomputed Realtime GI, Based GI, Fog 을 모두 Off 설정


Quality Setting 
- Edit > Project Setting > Quality 에서 설정
- Simple(또는 default) 보다 높은 프로필은 모두 체크 해제
- Pixel Light Count 는 0으로 설정
 (포워드 렌더링 시 픽셀 광원의 최대 수로 2D에선 사용 않함)
Texture Quality 를 가능한 낮은 설정으로
 (모바일에서 Half Res 설정에도 큰 차이 없이 75%나 메모리를 절약)
- Anisotropic Textures 는  해제
 (설정 시 물체가 카메라의 시선에 빗각(Oblique Angle)을 이루면서
  비스듬히 보이는 경우 뭉개지는 현상의 보완 : 3D에서 발생 조건)
 (설정 시 Forced On을 쓰기를 권장하며 성능을 많이 잡아먹지는 않음)
- Anti Aliasing 사용 안함 또는 2X
- Soft Particle 해제
 (파티클을 사용하는 이펙트들이 오브젝트와 겹치는 경계를 부드럽게 바꿔주는 기능)


오브젝트 풀링 사용
- 실시간으로 많이 생성되고 파괴되는 오브젝트는 반드시 풀링으로 관리가 필요.
 (초반에 미리 생성해 메모리를 점유하고, 게임 중 더이상 생성하지 않도록 구현)
- 풀링은 게임 플레이 중 GC의 발생을 방지하기 위함
- GC는 프로그램이 메모리를 추가로 요구할 때 발생 됨.


string 사용 자제
- string msg = "aaa" + "bbb"; 의 경우 3개의 string이 메모리에 할당됨.
- 가능한 string.format()을 사용
- string msg = string.format("A is {0} and B is {1}, {0} - {1} is {2}", A, B, A - B);
 ( 사용법 : 참고1, 참고2 )


Debug.Log 삭제
- 가능하면 사용하지 않도록 처리, string과 조합시 더욱 많은 메모리 점유가 발생 됨
- define 으로 사용 유/무를 플래그해서 호출 자체가 안되도록 설정


스프라이트 아틀라스
- 2배수의 정사각형 메모리에 적재되는 이미지의 여백을 최소환
- 동시에 사용하는 이미지 묶어 호출 횟수를 최소화 시킴

스프라이트 패커(Sprite Packer)
- Window>2D>Sprite Packer 를 이용
- 아틀라스로 만들 개별 sprite의 Inspector에 Sprite Mode>PackingTag를 설정
- Sprite Packer에서 [Pack] 버튼으로 아틀라스 생성
- 설정 방법 참고 : 링크, 링크2







2019년 7월 18일 목요일

Unity Sound 설정

모바일 게임을 제작하다 보면, PC-에디터에서는 잘 나오던 게임 사운드가 핸드폰에서는 밀려 나오는 경우를 종종 겪을 수 있다.

이런 상황을 해결하기 위한 설정값을 기록해 둔다.
출처 : https://docs.unity3d.com/kr/current/Manual/class-AudioClip.html

프로젝트 세팅

Edit > Project Settings > Audio에서 DSP Buffer SizeBest latency로 설정
- Best Performance : 성능이 우선 되어 출력 시 지연이 발생할 수 있음
- Best latency : 지연이 발생하지 않는 것을 우선시하여 출력 품질이 저하될 수 있음


리소스 타입별 세팅

배경음 1
- Force To Mono : 언 체크(퀄리티에 따라 가변)
- Load In Background : 체크
- Load Type : Streaming
- Preload Audio Data : 언 체크
- Compression Format : Vobis (100%)

배경음 2
- Force To Mono : 언 체크(퀄리티에 따라 가변)
- Load In Background : 체크
- Load Type : Compressed In Memory
- Preload Audio Data : 언 체크
- Compression Format : Vobis (70%)

효과음 : 작은 크기의 빈번한 출력 
- Force To Mono : 체크
- Load In Background : 언 체크
- Load Type : Decompress On Load
- Preload Audio Data : 체크
- Compression Format :  PCM

긴 효과음(보이스) : 중간 크기의 빈번한 출력
- Force To Mono : 체크
- Load In Background : 언 체크
- Load Type : Compressed In Memory
- Preload Audio Data : 체크
- Compression Format :  ADPCM

작은 크기의 가끔 발생하는 Sound
- Force To Mono : 체크
- Load In Background : 언 체크
- Load Type : Compressed In Memory
- Preload Audio Data : 언 체크
- Compression Format :  ADPCM

중간 크기의 가끔 발생하는 Sound
- Force To Mono : 체크
- Load In Background : 언체크
- Load Type : Compressed In Memory
- Preload Audio Data : 언 체크
- Compression Format :  Vobis (70%)


개별 리소스 세팅 정보

Force To Mono(모노 강제조정)
- 스테레오를 모노로 강제 조정
- 모바일이고 최적화를 중시할 경우 설정(체크) 함

Load In Background(지연된 로딩)
- 체크 시 출력 타이밍을 엄격히 지키지 않고, 느긋하게 백그라운드에서 로드
- 따라서 배경음악일 경우 사용 FX 사운드의 경우 체크 해제


Load Type
- Decompress On Load
 실행과 동시에 압축을 해제
 작은 사이즈의 FX 사운드에 유용
 많은 메모리 점유 CPU는 적게 사용

- Compressed In Memory
 메모리에 압축 상태로 저장, 실행 시 압축을 해제하여 재생
 약간의 성능상 오버헤드를 발생시킴
 보이스 사운드 등에 사용

- Streaming
 저장소에 위치한 오디오를 실시간으로 읽어냄.
 보통 배경음악에서 사용


Preload Audio Data
- 씬이 로딩될 때 씬에서 사용하는 모든 오디오 클립을 미리 로드
- 언체크시 플레이시 로드 하기에 랙 발생 됨


Compression Format
- PCM
 최고품질 / 용량 큼 / 작은 파일 크기에 적합 / FX 사운드
 Load Type은 Decompress On Load로 하자
 즉시 재생해야 하는 매우 짧은 효과음

- ADPCM
 중간 품질 / 용량 중간
 PCM대비 3.5배의 압축비, 노이즈가 포함됨
 총격 소리와 같이 무압축에 가까운 품질 까지는 필요없지만,
 지연시간 없이 자주 반복 재생 되야 하는 경우 적절

- Vobis
 최저품질 / 용량 적음 / 배경음에 적합
 압축률 설정이 가능(보통 70%로 설정)
 지연 재생 되어도 무방한 일반적인 배경음


Unity SNS Sharing

유니티에서 게임을 SNS에 공유(share)하는 방법 중 한 개를 정리해 본다.

에셋 다운 : [URL]
샘플 : [URL]


1. 에셋을 다운로드한다. 

  • 유니티 에셋 스토어에서 "Native Share for Android & iOS" 에셋을 검색해 현재 프로젝트에 Import 한다.

2. 환경을 설정한다.

  • Assets/Plugins/Android 경로에 AndroidManifest.xml 파일이 있는지 확인한다.
  • [설치된 유니티 경로]\Editor\Data\PlaybackEngines\AndroidPlayer\Apk 폴더에서 AndroidManifest.xml 파일을 복사한다.



  • adroid:authorities 설정은 내 프로젝트의 이름으로 설정한다.
<provider
  android:name="com.yasirkula.unity.UnitySSContentProvider"
  android:authorities="MY_UNIQUE_AUTHORITY"
  android:exported="false"
  android:grantUriPermissions="true" />

3.코드로 기능을 호출 한다. 


  • GitHub의 샘플 코드를 확인해 내게 필요한 항목을 설정한다.
  • SetText 에 마켓 URL를 넣으면 간단하게 공유 기능을 구현할 수 있다.


using System.IO;

void Update()
{
 if( Input.GetMouseButtonDown( 0 ) )
  StartCoroutine( TakeSSAndShare() );
}
 
private IEnumerator TakeSSAndShare()
{
 yield return new WaitForEndOfFrame();

 Texture2D ss = new Texture2D( Screen.width, Screen.height, TextureFormat.RGB24, false );
 ss.ReadPixels( new Rect( 0, 0, Screen.width, Screen.height ), 0, 0 );
 ss.Apply();

 string filePath = Path.Combine( Application.temporaryCachePath, "shared img.png" );
 File.WriteAllBytes( filePath, ss.EncodeToPNG() );
 
 // To avoid memory leaks
 Destroy( ss );

 new NativeShare().AddFile( filePath ).SetSubject( "Subject goes here" ).SetText( "Hello world!" ).Share();

 // Share on WhatsApp only, if installed (Android only)
 //if( NativeShare.TargetExists( "com.whatsapp" ) )
 // new NativeShare().AddFile( filePath ).SetText( "Hello world!" ).SetTarget( "com.whatsapp" ).Share();
}

2019년 7월 15일 월요일

Unity Copying assembly from 'Temp/Assembly-CSharp.dll' to ... Error

빌드시 Copying assembly from 'Temp/Assembly-CSharp.dll' to 'Library/ScriptAssemblies/Assembly-CSharp.dll' failed 에러가 발생 되는 경우가 있다.


이것과 관련되어 다음과 같은 논의가 있었고, 100% 해결은 안된 것으로 보인다.

https://forum.unity.com/threads/solved-copying-assembly-temp-assembly-csharp-dll-failed.552682/

https://forum.unity.com/threads/copying-assembly-from-temp-dll-to-library-failed-project-stucked.669616/



Anit-Virus에서 프로젝트 폴더를 제외하라는 사람이 있었지만, 다음과 같이 파일을 삭제하는 것으로 문제가 해결되는 것으로 보인다.
, remove the file
Library/ScriptAssemblies/com.unity.multiplayer-hlapi.Runtime.dll
and now build works again, once only. The file-removal procedure has to be repeated for every build

https://forum.unity.com/threads/error-copying-assembly-from-temp-com-unity-multiplayer-hlapi-runtime-dll-to-library-scriptassembl.662371/#post-4659752
단, 이 해결은 Unet을 사용하지 않는 상태여야 되는 것 같다.

Unet : 유니티가 제공하는 Unity Networking

2019년 7월 12일 금요일

Unity Notch(노치) 단말기 UI 설정

상단의 프레임 아래쪽으로 툭 튀어나와 있는 H/W 영역인 Notch의 처리를 위해 체크해야 하는 항목을 정리해 둔다.

빌드 세팅

Player Setting > Android > Resolution and Presentation 내부 설정 확인
- Render outside safe area의 항목이 체크되어 있는지 확인(기본값은 OFF)


Screen.safeArea 

SafeArea API(Unity 2017.2p3 이상)는 실행되고 있는 디바이스의 SafeArea 즉, 안전한 영역의 크기를 Rect 타입으로 반환하며, 이를 이용해 UI의 Rect와 Anchor의 조절이 필요

using UnityEngine;

public class SafeArea : MonoBehaviour
{
    RectTransform Panel;
    Rect LastSafeArea = new Rect(0, 0, 0, 0);

    public Text message;

    void Awake()
    {
        Panel = GetComponent();
        Refresh();
    }

    void Update()
    {
        Refresh();
    }

    void Refresh()
    {
        Rect safeArea = GetSafeArea();

        if (safeArea != LastSafeArea)
            ApplySafeArea(safeArea);
    }

    Rect GetSafeArea()
    {
        return Screen.safeArea;
    }

    void ApplySafeArea(Rect r)
    {
        LastSafeArea = r;

        Vector2 anchorMin = r.position;
        Vector2 anchorMax = r.position + r.size;
        anchorMin.x /= Screen.width;
        anchorMin.y /= Screen.height;
        anchorMax.x /= Screen.width;
        anchorMax.y /= Screen.height;
        Panel.anchorMin = anchorMin;
        Panel.anchorMax = anchorMax;
    }
}

출처 : stackoverflow | unity-to-ios-notch-and-safe-are-problems

2019년 7월 11일 목요일

Unity Analytics 설정

게임 분석을 위해 Unity Analytics를 적용 하는 방법을 정리해 둔다.
(각 Analytics 항목에 대한 상세한 설명은 유니티 공식 매뉴얼을 참고)

1. 프로젝트에서 설정하기

  • Unity의 Window>General>Services 으로 메뉴 열기
  • Create a Unity Project ID 로 애널리틱스를 이용한 서비스 프로젝트 생성하기
    (계정 연결하고 [Create] 버튼 선택)

2. Analytics 서비스 켜기

  • 표시되는 Services 메뉴 중 Analytics 의 [OFF] 버튼을 클릭해 [ON]으로 변경
  • Analytics 서비스 페이지의 Discover player insights 를 [ON]으로 변경
  • "이 앱이 13세 미만의 아이들을 대상으로 하는 것인지 확인" 설정

3. Analytics 서비스 연결

  • Play 버튼을 눌러 실행
  • 연동이 완료되면 Services의 Analytics 페이지가 갱신됨
  • 페이지가 갱신 되지 않으면 Services 화면의 우측 상단 메뉴 중 [Reload] 를 선택해 화면을 갱신 하거나 Services 화면 메인으로 이동해 다시 Analytics 페이지로 열어서 재 확인을 함

4. Analytics 서비스 정보

  • Services > analytics 항목의 Validator 정보
  • 발생 되는 이벤트 정보 로그를 표시
  • 설정하자마자 항상 즉시 표시되는 것은 아님(동기화 시간이 필요할 수 있음)

5. 커스텀 이벤트

  • 원하는 시점에 "Tag"로 등록한 값을 Analytics에 보낼 수 있음
  • 코드 예제

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Analytics;

public class AnalyticsManager : MonoBehaviour
{

    #region Singlton선언
    private static AnalyticsManager m_instance = null;

    public static AnalyticsManager Instance
    {
        get
        {
            return m_instance;
        }
    }

    void Awake()
    {
        // 동일한게 있으면 파괴
        if(m_instance)
        {
            Destroy(gameObject);
            return;
        }

        //유효한 인스턴스 생성 및 삭제 방지 처리
        m_instance = this;
        DontDestroyOnLoad(gameObject);
    }
    #endregion

    bool gameLoop = false;

    // 어플리케이션을 종료하는 순간에 처리할 행동들
    private void OnApplicationQuit()
    {
        gameLoop = true;
        Analytics.CustomEvent("App Quit", new Dictionary
        {
            {"Leaderboard Up Load Count", GPGSIntegration.loginSuccessCount },
            {"Best Score",  GPGSIntegration.bestScoreValueText},
            {"Loop Flag", gameLoop }
        });

    }

    int clickCount = 0;

    public void AnalyticsButtonClick()
    {
        clickCount++;

        Analytics.CustomEvent("App Quit", new Dictionary
        {
            {"Version", Application.version },
            {"Best Score",  GPGSIntegration.bestScoreValueText},
            {"Loop Flag", gameLoop },
            {"Button Click Count" ,  clickCount}

        });
    }

    public void ButtonAddCount()
    {
        clickCount++;
    }

}

6. 13세 미만 대상 앱

  • 미국에서는 13세 미만의 아동을 대상으로 하는 웹사이트, 앱, 서비스를 사용하도록 허용하기 위해서 아동 온라인 개인정보 보호법(COPPA: the Children’s Online Privacy and Protection Act)을 준수 해야 됨
  • 게임이 이 카테고리에 부합한다면 연련 제한을 “under 13”로 설정 하십시요. 유니티애즈와 유니티애널리틱스에서 수집하는 데이터의 제약이 생기긴 하지만 그래도 동작은 이상 없이함

7. 퍼널(Funnel) 등록


2019년 7월 4일 목요일

unity 스크립트 라이프 사이클 플로우차트


awake() → start() 등의 unity 에서의 정의된 로드 순서
Order of Execution for Event Functions


실행 : Rest() → Awake() → OnEnable() → Start() → 
반복 : FixedUpdate() → OnTriggerXXX() → OnCollisionXXX() → Update() → LateUpdate() → 
종료 : OnDisable() → OnDestroy() → OnApplicationQuit()


Unity cr_VariationsUtils app_webview error

AdMob의 Banner 광고를 설정한 이후 일부 기기에서 cr_VariationsUtils Tag의 에러가 발생 되었으며 아래와 같은 app_webview와 연관성이 의심되는 로그가 발생 되었다.

07-04 05:40:30.955: E/cr_VariationsUtils(7201): Failed reading seed file "/data/user/0/com.Company.ProductName/app_webview/variations_seed": /data/user/0/com.Company.ProductName/app_webview/variations_seed (No such file or directory)

이 경우, Banner를 요청하는 시점을 Awake()에 두어 Scene의 Initialization 직후 LoadBanner를 호출하면서 문제가 발생하는 것이였다. 

요청 시점을 Start()로 변경한 뒤 테스트를 하니 발생하던 에러는 사라졌다. 

2019년 7월 3일 수요일

Unity 스토어 열기 & 웹페이지 열기

웹 페이지 열기

Application.OpenURL("https://play.google.com/store/apps/details?id=com.Company.ProductName");

구글 플레이 스토어

Application.OpenURL("market://details?id=com.Company.ProductName");
           market://details?id=패키지명

애플 앱 스토어

Application.OpenURL("itms-apps://itunes.apple.com/app/id0123456789")

2019년 6월 27일 목요일

Unity - GPGS 와 Admob 연동 및 배포 준비 작업


0. 사전 정보

  • Unity 버전 : 2018.4.2f1
  • GPGS Plugin 버전 : GooglePlayGamesPlugin-0.9.64.unitypackage
  • AdMob Plugin 버전 : GoogleMobileAds-v3.17.0.unitypackage

1. 배포용 APK를 준비

  • gpgs 패키지가 설정되지 않은 순수 게임 구현까지의 프로젝트
  • Unity>PlayerSettings>PublishingSettings>keystore를 생성해 적용한 프로젝트
  • keystore 와 key의 Alias 를 생성 및 적용한 프로젝트
  • keystore를 설정 하지 않은 APK 업로드 시 "디버그 모드로 서명한 APK...." 형태의 에러가 차후 발생 됨

Google Play Console 앱 삭제 - Android 광고 ID 사용 및 개발자 배포 계약의 4.8 조항 위반 건.

게임에 AdMob을 적용하는 작업도중 "Android 광고 ID 사용 및 개발자 배포 계약의 4.8 조항 위반" 메일과 함께 등록된 게임이 삭제 되는 경우가 발생 된다.
이는 구글 콘솔에 게임 등록 시 광고 처리를 하지 않은 상태로 등록하고, 이후 테스트용 APK에는 광고가 탑재되어 발생한 문제로 확인 되었다.

이런 상황이 발생 되는 아래와 같은 단계로 문제를 해결 할 수 있다.

- 구글 사이트 도구나 블로그를 이용해 개인정보처리방침 정보를 작성하고 URL을 확보 한다.

- 구글 콘솔에 접속해 앱 정보를 업데이트 한다.

1. 모든 애플리케이션>앱 선택> 앱 정보 > 스토어 등록정보 에서 [개인정보처리방침] 항목에 작성한 개인정보 URL을 입력 한다.
2. 모든 애플리케이션>앱 선택> 앱 정보 > 가격 및 배포 에서 [광고 포함] 부분을 확인해 수정 한다.

구글 콘솔에서의 작업을 하면 앱이 다시 제출 된 상태로 [대시보드]의 상태가 "업데이트 처리 중" 으로 표시되는 것을 확인 할 수 있다. (새로 APK를 출시 하지 않아도 된다.)

이후 2~3시간(수시간) 경과 되면 [대시보드]의 상태가 "출시중"으로 변경된다.


개인정보처리방침 참고 자료
한글 : https://www.privacy.go.kr/a3sc/per/inf/perInfStep01.do
영문 : https://app-privacy-policy-generator.firebaseapp.com/#


수집 정보의 예
- Email address, First name and last name, Address, State, Province, ZIP/Postal code, City, Cookies and Usage Data

구글 플레이 스토어 등록 시 개인정보처리방침 등록

게임을 제작하여 내부에 AdMob으로 광고를 적용하고, 구글 플레이 스토어에 "개인정보처리방침" 정보를 연결하지 않으면 "구글 배포 계약의 4.8 조항"(링크)에 의해 등록한 앱이 삭제될 수 있다.

이런 상황을 막기 위해 앱 등록 시 "개인정보처리방침"의 URL을 등록해야 하는데, 개인 호스팅을 하지 않는 이상 URL을 가지기 쉽지는 않을 것이다.

이때 사용할 만한 구글의 서비스가 있다.
사이트 도구 : https://sites.google.com/site/sites/
      또는 https://sites.google.com/new


서비스에 로그인한 뒤, 페이지를 추가해 필요한 "개인정보처리방침" 내용을 작성하고, 게시한 후 게시된 사이트의 URL을 구글 콘솔에 추가하면 된다.


2019년 6월 26일 수요일

Unity에서 Logcat 정보 보기

안드로이드 개발 중 디버깅 시 Log 를 볼 수 있는 장소가 Android Studio의 Logcat 창이다.
이 창에서는 기기에서 오류와 (앱에서 Log 클래스로 작성한) 메시지들을 볼 수 있다.
(Andriod SDK 설치 폴더 내 tools/monitor.bat 로 연결된 기기와 Logcat 확인 가능)

하지만 Unity와 Android Studio을 실행해 Logcat 창을 확인하는 것 보다 Unity에서 바로 Logcat에 표시되는 정보를 확인할 수 있는 방법이 있다.

Logcat (android logging) extension for Unity3D
Link : https://github.com/dzonatan/Unity3D-LogCat-extension

Link 내 How to use 정보와 같이
Asset>Editor 폴더를 생성해 LogCatWindow.cs를 위치 시키고, Unit 메뉴의 Window>LogCat - Android Logger 을 선택하면 Logcat 윈도우를 띄울 수 있다. 




















Debug.Log확인 및 AdMob에서 사용할 테스트 기기 번호를 확인하는 데 사용 했다.

Unity "Build And Run" 미 실행 오류

유니티에 기기를 연결해두고 기기에서 게임을 삭제해 가며 Build And Run 으로 게임을 테스트 하다 보면 종종 "Build completed with a result of 'Succeeded'"으로 성공 메시지가 표시되지만, 기기에서는 실행이 되지 않는 경우가 있다.

이런 문제가 종종 발생한 기기는 구글 계정이 복수로 등록된 기기였다.

기기의 옵션 메뉴에서 설치된 전체 App 리스트를 확인해 테스트를 한 게임 앱이 정상적으로 삭제되었는지 확인하고, 삭제되지 않았으면 우측 상단 메뉴>"모든 사용자에 대해 제거"로 다시 삭제하면 정상적으로 Build And Run 기능이 동작하게 된다.

Unity Build And Run "CommandInvokationFailure: Unable to install APK to device. Please ...." 오류

유니티에서 Build And Run을 실행하는 중에 다음과 같은 에러가 발생 될 수 있다.

CommandInvokationFailure: Unable to install APK to device. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details.
...
[INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.kkumgames.Sample_Gpgs_ADMob signatures do not match the previously installed version; ignoring!]
...

기기 또는 에뮬레이터에서 현재 빌드하는 게임과 동일한 패키지명을 가진 게임이 설치되어 있어서 발생한다.

따라서 설치된 게임을 삭제 후 재시도 하면 된다.

2019년 6월 25일 화요일

Unity PlayerSettings의 Version 참조

유니티의 PlayerSettings > Other Settings > Version 에 입력된 값을 출력하는 스크립트.
PlayerSettings.bundleVersion 는 에디터 전용이라 Apk로 Build 시 사용 할 수는 없음.

using UnityEngine;
using UnityEngine.UI;

using UnityEditor;

public class MyVersion : MonoBehaviour
{
    public Text versionText;

    void Start()
    {
        // using UnityEditor; 와 세트로 edit 전용
        //buildVersionText.text = "Version - " + PlayerSettings.bundleVersion;

        // 빌드 시 사용 할 수 있음
        buildVersionText.text = "Version - " + Application.version;
    }
}

Unity - Firebase 연동 (Analytics, AdMob)

버전 : firebase_unity_sdk_6.5.0.zip 게임에서 통계 측정 및 광고 추적을 위해 Firebase 을 연동한다. 앞서 [Unity - GPGS 와 Admob 연동 및 배포 준비 작업]  연동 이후에 작업을 진행 한다. 유니...