유니티에서 ui를 클릭 혹은 터치해도 게임 중 입력 이벤트를 처리하는 부분에서 계속 문제가 발생했다. 


게임 ui를 유니티의 ui로 만들지 않았을때는 몰랐는데, 이거 어떻게 처리해야 할지 한동안 고민이 많았는데...


EventSystem.current.IsPointerOverGameObject 라는 함수가 있는지 몰라서 한참 고생했네;;


아래와 같은 클래스를 하나 추가해서 처리.

using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;

public class InputEventManager : MonoBehaviour {
     public bool GetMouseDown(int _idx){
        if (EventSystem.current.IsPointerOverGameObject())
            return false;

        return Input.GetMouseButtonDown(_idx);
    }

    public bool GetMouseUp(int _idx){
        if (EventSystem.current.IsPointerOverGameObject())
            return false;

        return Input.GetMouseButtonUp(_idx);
    }

    public bool GetMouse(int _idx){
        if (EventSystem.current.IsPointerOverGameObject())
            return false;

        return Input.GetMouseButton(_idx);
    }

    static InputEventManager mInst;
    public static InputEventManager Inst {
        get{
            if (mInst == null) {
                GameObject go = new GameObject ();
                go.name = "InputEventManager";
                mInst = go.AddComponent<InputEventManager> ();
            }
            return mInst;
        }
    }
}




이전 버전에서는 IsPointerOverEventSystemObject  라는 이름으로 쓰였는데, 이름이 조금 달라져서 애매한데, 일단 잘 작동은 하는 듯. 

게임 다 만들고, google play에 프로젝트 등록하고 로그인을 해봤는데 마지막 로그인에서 계속 fail뜸. 


원인을 찾던 중 로컬에 등록한 keystore의 값을 google play api 관리자에 등록을 안 해서 발생한 문제였음. 


아래 이미지 중 붉은 테두리 안에 keystore에 등록된 sha1 값을 등록해야 함.


(keytool -list -v -keystore "자신이 등록한 keystore 이름" 을 입력하면 sha1 값을 볼 수 있다.)



  1. 최창인 2017.09.28 21:50 신고

    정말 감사합니다.
    소스코드도 맞고, 콘솔에서도 문제가 없는데, 계속 로그인이 안되서 무슨 문제인가 했더니
    SHA1값이 다르더군요..
    정말 감사합니다.

이미지에서 처럼, ragdoll 물리객체가 저 멀리 날아가고 있다. 


이는 spine 3.0 미만 버전에서 발생하는데.. 


spine ragdoll을 적용할 객체의 scale이 1.0 미만일 경우 이 현상이 발생한다.




Hierarchy에서는 스케일을 1로 고정하고, spine에서 출력된 skeletonData의 스케일을 조정하면 문제없음.






facebook, google, tapjoy 세 개를 합쳐서 샘플 프로젝트를 작성중에 아래 같은 에러가 발생!!


Error building Player: CommandInvokationFailure: Failed to re-package resources. See the Console for details.

C:\Program Files (x86)\Android\android-sdk\build-tools\22.0.1\aapt.exe package --auto-add-overlay -v -f -m -J gen -M AndroidManifest.xml -S "res" -I "C:/Program Files (x86)/Android/android-sdk\platforms\android-23\android.jar" -F bin/resources.ap_ --extra-packages com.facebook.android:com.google.android.gms:com.google.example.games.mainlibproj -S "E:\Facebook Sample\Temp\StagingArea\android-libraries\facebook\res" -S "E:\Facebook Sample\Temp\StagingArea\android-libraries\google-play-services_lib\res"


png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-mdpi-v4\ic_plusone_small_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-hdpi-v4\ic_plusone_small_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-xhdpi-v4\ic_plusone_small_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-xxhdpi-v4\ic_plusone_small_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-mdpi-v4\ic_plusone_standard_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-hdpi-v4\ic_plusone_standard_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-xhdpi-v4\ic_plusone_standard_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-xxhdpi-v4\ic_plusone_standard_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-mdpi-v4\ic_plusone_tall_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-hdpi-v4\ic_plusone_tall_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-xhdpi-v4\ic_plusone_tall_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-xxhdpi-v4\ic_plusone_tall_off_client 1.png: Invalid file name: must contain only [a-z0-9_.]

res\drawable-mdpi-v4\powered_by_google_dark 1.png: Invalid file name: must contain only [a-z0-9_.]

.

.

.

.

아래 스샷 처럼 에러 발생!


해당 폴더로 가봤더니 같은 이름의 파일들이 복사되면서 들어가면 안될 빈칸이 들어감.



tapjoy 패키지를 설치하면 Assets\Plugins\Android\google-play-services_lib 폴더가 존재함. 구글 패키지가 두개가 존재하게 되어, 빌드할 때 같은 리소스를 복사해 에러가 발생한다.


tapjoy 패키지를 import 할 때 샘플과 google play service lib를 제외하고 import 받으면 해결됨. 


tapjoy 서포터분들의 빠른 답변 감사합니다. :)


Facebook Unity SDK 6.0 을 받아 패키지를 설치하고, 샘플을 돌려보는데 아래와 같은 에러가 발생


Could not securely load assembly from 

https://integrated-plugin-canvas-rsrc.fbsbx.com/rsrc/unity/lib/sdk_6.0/CanvasFacebook.dll


FB.cs 파일 line 411에 전처리기 "#if UNITY_4_5" 를 찾아 그 뒤에 " || UNITY_4_6 || UNITY_5_0 || UNITY_5" 를 붙여줄 것! 현재 버전 define만 붙여도 됨.




http://forum.unity3d.com/threads/facebook-sdk-assembly-cannot-be-loaded.264126/


커뮤니티에서 해결책을 찾았는데, 불편하게 개발자가 꼭 수정해야 되나 --; 


배포 버전 수정해서 올려주면 좋을텐데 --

foreach (DictionaryEntry item in abTable) {

Debug.Log (" key = " + item.Key );

//    value값 정리

abTable.Remove(item.Key);

}


위처럼 사용할 경우 foreach에서 계속 참조하기 있기 때문에, "Hashtable.Enumerator: snapshot out of sync."와 같은 에러가 발생한다.


foreach 문 안에서의 키 삭제는 문제가 될 수 있으니, value값 정리와 리스트에서의 정리 처리는 분리해야 한다. 


일괄 삭제의 경우 아래와 같이..


foreach (DictionaryEntry item in abTable) {

Debug.Log (" key = " + item.Key );

//    value값 정리

}

   abTable.Clear();


필요한 값만 정리한다면.. 삭제할 키 리스트르를 중심으로 해당 값만 Remove 처리할 것!

* 정적으로 사용된 리소스

 : 특정 씬에 포함된 리소스는, 빌드 시 해당 씬을 포함하면 배포되는 기본 파일에 포함됩니다.


* 동적으로 사용된 리소스

 : 동적으로 로딩되는 리소스는 아래 몇가지 방식으로 동적 로딩을 진행할 수 있습니다.

 1. Resources 라는 폴더명을 만들어 리소스를 넣어두면 기본 파일에 포함됩니다. Resources.Load 함수로 동적 로딩 할 수 있습니다

 >> Resources 폴더는 여러개를 만들어 사용할 수 있습니다. 추후 이 폴더명 안에 있는 리소스들은 빌드 시 하나로 합쳐지는데, 같은 파일명이 있으면 문제가 됩니다. 파일명이 중복되지 않도록 주의하시기 바랍니다.

 >> AssetBundle 파일을 이곳에 넣어둘 수 있습니다. AssetBundle.CreateFromFile 함수로 동적 로딩 할 수 있습니다. 좋은 방법은 아닙니다. 이러지 마세요 !!


 2. SteamingAssets에 넣어두면 기본 파일에 포함됩니다. WWW로 로딩 가능합니다. 만약 AssetBundle 파일들을, 게임 설치 후 초기 다운로드가 아닌 바로 실행 가능하게 하려면 이 폴더에 AssetBundle 파일을 넣어두는 방법을 추천합니다. 


 3. AssetBundle 파일로 만든 후, 게임 실행 시 혹은 게임 중 필요할 때 WWW로 다운로드/로딩 가능합니다.


끝!!!

GAME SETUP AND LIGHTING


1. Mesh Collider에 Mesh 말고 Material이 추가로 있음.

  : 충돌체에 매터리얼이 필요한 이유가 뭐지??


2. Camera의 Rendering Path 선택 옵션이 다름.

  4.x >>  Vertex Lit, forward, Deferred Lighting

  5.x >>  forward, Deferred, legacy Vertex lit, legacy Deferred (light prepass)

  : 기존의 Deferred Lighting 이 legacy Deferred가 된건가? (그러니까 legacy가 된거겠지??)

  : 그럼 현재의 Deferred와 legacy Deferred의 차이는 무엇일까?


3. Edit -> Render Setting은 Window -> Lighting 으로 이동됨. fog 설정탭이 이 안에 존재함.

   예제와 비슷하게 하려면 보간 방식을 linear로 설정할 것. Color 를 포함한 소수 옵션을 조절할 수 있지만, Global Fog image effect를 사용할 것을 권장하고 있음. 나중에 Global Fog image effect를 어떻게 활용하는지 찾아보고 장,단점을 정리해보자.

   

4. windows -> Light mapping 메뉴는 Lighting 메뉴로 수정되었으며, 이 튜토리얼에 있는 baking 설정은 General GI와 Baked GI에 분리되어 있다. 




카드키 삭제할 때 Destroy(gameObject) -> GameObject.Destroy(gameObject); 임.


Body Mask 는 Humanoid로 이름이 변경됨.




전반적으로, 크게 바뀐 UI는 내용이 없고, 다른 것들은 따라할 정도 수준.









  

  

굳이 이럴 필요 없으나, 이 샘플이 워낙 잘 구성되어 있다고 하니, 이걸 5.x에서 가동시키면 여러모로 도움될 듯 해서 시도해 봄. 할 일 없어서 이거 하는거는 비밀.. 


처음 import 받으면 발생하는 에러들.


1. UnityEngine.Component 로 사용되는 것들을 GetComponent<>()로 수정할 것! 한 50개 정도 되는 듯.


2. doneSceneFadeInOut.cs는 주석처리. 

   Assets/Done/DoneScripts/ScreenFaderScripts/DoneSceneFadeInOut.cs(15,28): error CS1061: Type `UnityEngine.Component' does not contain a definition for `pixelInset' and no extension method `pixelInset' of type `UnityEngine.Component' could be found (are you missing a using directive or an assembly reference?)


3. 네비매쉬 다시 rebake하고.. 

   windows -> Navigation 열고 리베이크.


4. NpShape::setFlag(s): triangle mesh and heightfield triggers are not supported! 에러는 Unity 5.0이 PhysX3.3 SDK로 업그레이드 되면서 발생한 문제다.

 PhysX의 제약사항인데, TerrainCollider는 더 이상 isTrigger 플레그를 지원하지 않으며, Mesh Collider는 convex 모양에서만 트리거를 가질 수 있게 되었다. 이제 MeshCollider 중 isTrigger를 가지지만, convex가 아닌 것을 찾아 convex로 수정하자. 수동으로... 고고!!하면 죽을 지도 --;


Hierachy에 객체를 생성하고, 새로운 스크립트를 추가하자. 그리고 해당 스크립트에 아래 코드를 넣자.


      MeshCollider [] glist;


void Start(){

glist = FindObjectsOfType<MeshCollider> ();


foreach (MeshCollider mc in glist) {

if(mc.isTrigger == true && mc.convex == false)

Debug.LogWarning("Found triggered mesh : " + mc.name);

}

}

1 ~ 4까지의 에러들을 수정했다면 가동은 될 것이다. 위 코드를 삽입 후 가동하면 console창에 문제의 오브젝트 이름이 출력되며, Hierachy에서 해당 객체 이름을 넣은 후 클릭 -> Inspector 창에서 MeshCollider를 찾아 convex를 활성화하면 끝!!


이제 에러없이 샘플이 실행됨을 알 수 있다. 



자... 그럼 이제  이 곳 으로 가서 데모 프로젝트를 배워보자. +_+


한 가지 핑계를 대고 넘어가야겠다. 어제 로깅 코드를 만들 때 모든 데이터를 event로 처리한 걸 기억하길 바란다. 사실 모든 게임의 로그를 이벤트로만 처리하는 것은 당연히 잘못된 방법이다. 하지만, 이 글은 Google Analytics와 Unity를 연동하는 과정을 설명하는데 목적을 두고 있다. 구글 애널리틱스에 적합하게 로깅하고 리포트를 분석하는 글이 아님을 밝힌다.(절대 몰라서 그런거... 맞음. --)


아마 대부분의 통계툴이 그렇겠지만, 데이터를 샘플링한다. 그래서 모든 데이터를 세세하게 보지는 못한다. 이번 테스트에서는 어제 게임 두 판만 했음. 팔이 아파서..데이터가 적기 때문에 추론하는 방법만 간단히 언급하겠다.


이제 본론 시작!!


데이터 조회는 보고서 속성에 설정한 시간대에 정리가 된다. 1일마다 리포트되며, 필요한 경우 아래 화면에서 변경 가능하다. 



금일 업데이트 되어 어제 테스트 한 내용을 검토해 볼 수 있게 되었다. 어제는 모든 데이터를 event로 처리했으니,  좌측 메뉴에서 "방문 형태" -> "이벤트" -> "인기 이벤트"로 먼저 가보자. 그럼 아래와 같은 결과를 볼 수 있다.



이전에 목표로 잡았던 총 세 가지 지표를 검토해 보자. 


1. 몇번째 스테이지에서 좌절하는가.

 : Category "game" -> Action "gameover" -> Label "last day" 로 설정했던 값을 검토해보자.

(* 순 이벤트 수란 : 한 세션 기준으로 첫 행동만 기록되는 이벤트의 합계. 즉, 어제 나 혼자, 게임을 두번 했는데, 하나의 세션이었으니, 그 중 첫번째 게임의 데이터를 말한다. 이벤트 값은 10. 두번째는 99판까지 갔다능...)


총 두번 플레이 되었으며,  순 이벤트 수 기준으로 이벤트 값은 10. 이를 통해 유저들은 평균 day 5 플레이 한다는 말도 안되는 결과를 알 수 있다. (모수가 많다면 우리 모두 공감할만한 결과를 얻을 수 있다. 지금은 그냥 패스 --a) 


2. Food의 획득, 이동 시 사용하는 량, 좀비에게 타격받아 소비되는 량

 : Category "food" -> Action "loss","get" -> Label "move","attacked","food","soda"  로 설정했던 값을 검토해보자.


Label 기준으로 본 화면이다. move, attacked는 loss, food, soda는 get action의 값이니 참고하자.


게임에서 이동 시 소비되는 food는 1이다. 평균값이 1인걸 확인할 수 있으며, 총 이벤트수는 90%에 육박하고 있는 걸 볼 수 있다. 그에 비해 attacked는 총 3.91%로 미비하다. (좀비가 우쉽나?)  좀비의 무서움을 더 알릴 필요가 있겠다. 


획득은 food가 soda의 획득 비율은 비슷하다. action "get"을 기준으로 food와 soda를 비교해보면 각각 56%와 44%임을 알 수 있었다. (몰랐는데 뭘 먹으나 food 증가량은 10이었네 --a 모양만 다르고 효율은 같았구나.)


3. 각 스테이지 별로 몇 번 정도의 이동으로 클리어 하는가

 : Category "day" -> Action "clear" -> Label "total move"로 설정했던 값을 검토해보자.

 위 분류는 사실 목적에 알맞지 않은 설정이었다. label을 day 1, day 2 등으로 분류하여 각 day별로 이동 횟수를 볼 수 있게 했어야 했다. 혹시 4번째 글에서 소스를 받은 분들은 이 부분을 개선해서 테스트 해보면 더 좋을 듯. 


day 별로 구분되지 않은 건 아쉽지만, 평균 약 20회 이동으로 스테이지를 클리어 하는 결과를 볼 수 있다.



이상. Unity + Google Analytics 연동에 대한 글을 마친다.


블로그 자체를 개인 저장소로 생각하며 글을 올리다보니 실수가 여기저기 보이네.


가끔 와서 보시는 분들께 심심한 사과의 말씀을 ^^a


다들 행복한 하루 하루 되세요. ~ 




+ Recent posts