한 가지 핑계를 대고 넘어가야겠다. 어제 로깅 코드를 만들 때 모든 데이터를 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


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





GameManager.zip

기반 준비는 다 되었다. 이제 실제 이벤트를 전송하고 그 결과를 어떻게 보는지 살펴보자.


이 전 글에서 공유했던 목표는 아래와 같다. 


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

 : Game Over되는 시점의 Day 날짜를 전달하자.


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

 : Food 나 Soda 획득시 획득량 전달

 : 이동할 때마다 1씩 소비됨. 이 정보 전달

 : 좀비에게 공격 당하면 10씩 소비된다. 이 정보 전달.


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

 : 각 스테이지가 클리어 될 때 총 이동 횟수 전달.


event parameter는 총 4개로 구성되며, string category, string action, string label, int value로 구성된다. 위 세 가지 이벤트를 위해 아래와 같은 분류를 만들자.


Category

"game" - 게임 전체에 대한 대분류

"day"   - 한 턴 끝날 때.

"food"  - 게임의 중요 요소, Food


Action

"clear" - 턴 클리어 시

"gameover" - 게임 종료 시

"get"   - 획득

"loss"  - 손실


Label

"total move" - 한 턴의 총 이동 횟수

"Last Day" - 마지막 day 

"food","soda" - 획득 시 구분되는 요소

"attacked","move" - 손실 시 구분되는 요소

 

관련된 코드는 첨부된 파일, GameManager.cs, Player.cs를 참고할 것!


테스트 한 실시간 그래프는 아래처럼 볼 수 있다.



Google Analytics에서는 이벤트 기록을 상세 분석하기 위해서는 하루가 지나야 가능하기 때문에 


리포트 상세보기는 내일 이어서 업데이트 할 예정


  1. 2015.07.14 16:29

    비밀댓글입니다

    • 가끔.하늘 가온아 2015.07.15 09:37 신고

      첨부파일이 빠졌었네요. ^^;

      첨부된 압축파일에 두 파일 같이 업데이트 해뒀습니다.

      도움 되셨으면 좋겠네요. 즐거운 하루 되세요.

  2. 개발초봅 2015.07.16 14:40 신고

    공유 감사합니다!! 많은 도움이 될 것 같습니다.
    항상 하시는 일 건승을 기원합니다~

  3. ssh 2015.08.12 00:39 신고

    글 잘 봤습니다!
    앱의 활성 사용자 수는 바로 업데이트가 되나요?
    작업 시작한 지 한시간이 되었는데도 아직도 액티브 사용자 수가 0이네요..

    • 가끔.하늘 가온아 2015.08.12 16:59 신고

      위 스크린 샷처럼 데이터를 보내는 유저가 있으면 활성 사용자 수는 변화합니다. 데이터 전달이 없으면 활성 사용자 수는 다시 줄어드니 참고하세요.

샘플 제작을 위한 게임 샘플은 2D Roguelike를 사용했다. Android를 기준으로 설명한다. iOS에 대한 내용은 다음 글에서 세팅과 관련된 내용만 다루도록 한다. 그 이외의 내용이 다르진 않으니..





트래킹을 위한 1차 목표는 아래와 같다. 


- 몇번째 스테이지에서 주로 좌절하는가

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

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


Google Analytics 설정 절차


1. google 계정을 생성 후(기존 계정 사용 가능) https://www.google.com/analytics/에 로그인한다.


2. 애널리틱스 계정이 없다면 계정을 생성하는 폼이 출력될 것이다. 그곳에 원하는 대표 계정명, 속성명(속성은 프로젝트명과 동일하다고 생각하면 된다.)을 입력하면 아래와 같은 기본 화면을 볼 수 있다. 테스트를 위해 속성명을 "LogTest"로 명명함.



이제 실제 프로젝트를 세팅해보자. 


1. 빈 프로젝트를 만들고, Roguelike, googleanalyticsv3.unitypackage를 생성한 프로젝트에 Import한다.


2. Assets/Plugins/GoogleAnalyticsV3에 GAv3.prefab을 클릭하고, Inspector view의 내용을 채워준다. 


아래 내용만 채우면 테스트가 가능하다.

 Android Tracking Code : 속성의 추적 ID를 입력한다.

 Product Name : 제품명을 입력한다. 여기서는 속성값과 같은 "LogTest"를 입력했다.

 Bundle Identifier : com.YourCompanyName.YourProductName 과 같은 포멧으로 입력하여야 한다.

 Bundle Version : 원하는 대로.. 여기서는 0.1로 입력했다.

나머지는 기본값을 사용하겠다.


3. Project View에서 GameManager.prefab을 찾고, GameManager.cs에 아래 코드를 삽입한다.

public GoogleAnalyticsV3 googleAnalytics;



4. Project View에서 GameManager.prefab을 클릭하고, Google Analytics에 세팅했던 GAv3를 Project View에서 찾아 연결한다.



5. GAv3를 활성화 하기 위해 GameManager.cs에 아래 코드를 삽입하자.


void Awake(){

  .   

  .

  // Start Google Analytics 

  Instantiate(googleAnalytics);

  googleAnalytics.StartSession();

  .   

  .

}


void OnApplicationQuit(){

  googleAnalytics.StopSession();

}  


이제 세팅이 완료되었다. 


위 세팅은 일반적이라고 할 수 없다. "Google Analytics 연동하기 - 1. "의 설명과는 조금 다른데, 이 프로젝트의 중심인 GameManager의 특성 문제이니 참고하기 바란다.


다음은 실제 로그를 남기고, 구글 애널리틱스 리포트에서 결과를 보도록 하자.

(* 원문 : https://developers.google.com/analytics/devguides/collection/unity/v3/reference?hl=ko )

*역자주 : 원문을 그대로 변역하는게 아닌, 실무에 적용하면서 불필요하게 긴 내용은 빼고, 추가할 내용은 넣으면서 진행합니다. 번역이 아님을 알아주세요. ^^a


데이터를 보낼 때는 Basic 나 Builder method를 사용합니다. Builder method들은 보낼 정보들에 대한 수치, campaign 파라미터들을 추가하길 원할 때 사용됩니다. 


Dispatch Hits

네트웍 연결이 가능하다면 데이터를 전송한다.

public void DispatchHits();


Session Control

Session들은 스크린 뷰, 이벤트들 그리고 전사상거래 업무 등과 과 같은 의미있는 행동들을 포함한 유요한 커네이너들을 제공한다.


아래 메소드들은 강제로 세션을 시작하거나 종료할 수 있다.

// Start a new session.
public void StartSession();
// There should be no need to end a session explicitly. However, if you do
// need to indicate the end of session you can use the following method.
public void StopSession();

Screens


GA에서 Screens는 게임안에서 보이는 유저 컨텐츠를 대표한다. screen은 단일 문자열 필드로 구성되어 있으며, GA 리포트에서 screen name으로 구분되어진다.


basic 

public void LogScreen(string title);

Builder

public void LogScreen(AppViewHitBuilder builder);

Example

googleAnalytics.LogScreen("Main Menu");

//Builder Hit with all App View parameters (all parameters required):
googleAnalytics
.LogScreen(new AppViewHitBuilder()
   
.SetScreenName("Main Menu"));


Events

Events는 유저의 반응에 대한 데이터를 모으는데 유용한 방법이다. 네 개의 파라미터를 사용하며, 게임의 유저 반응을 묘사하는데 사용할 수 있다. 


Basic

public void LogEvent(string eventCategory,
   
string eventAction,
   
string eventLabel,
   
long value);

Builder

public void LogEvent(EventHitBuilder builder);

Example

googleAnalytics.LogEvent("Achievement", "Unlocked", "Slay 10 dragons", 5);

// Builder Hit with all Event parameters.
googleAnalytics
.LogEvent(new EventHitBuilder()
   
.SetEventCategory("Achievement")
   
.SetEventAction("Unlocked")
   
.SetEventLabel("Slay 10 dragons")
   
.SetEventValue(5));

// Builder Hit with minimum required Event parameters.
googleAnalytics
.LogEvent(new EventHitBuilder()
   
.SetEventCategory("Achievement")
   
.SetEventAction("Unlocked"));


Crashes & Exceptions

충돌과 예외에 대해 측정할 수 있다.


Basic

public void LogException(string exceptionDescription, bool isFatal);

Builder

public void LogException(ExceptionHitBuilder builder);

Example

googleAnalytics.LogException("Incorrect input exception", true);

// Builder Hit with all Exception parameters.
googleAnalytics
.LogException(new ExceptionHitBuilder()
   
.SetExceptionDescription("Incorrect input exception")
   
.SetFatal(true));

// Builder Hit with minimum required Exception parameters.
googleAnalytics
.LogException(new ExceptionHitBuilder());


User Timings

GA에서 시간의 간격을 측정하는 기본적인 방법을 제공한다. 예를들면, 리소스 로딩 시간을 측정하는데 유용할 수 있다.


Basic

public void LogTiming(string timingCategory,
   
long timingInterval,
   
string timingName,
   
string timingLabel);

Builder

public void LogTiming(TimingHitBuilder builder);

Example

googleAnalytics.LogTiming("Loading", 50L, "Main Menu", "First Load");

// Builder Hit with all Timing parameters.
googleAnalytics
.LogTiming(new TimingHitBuilder()
   
.SetTimingCategory("Loading")
   
.SetTimingInterval(50L)
   
.SetTimingName("Main Menu")
   
.SetTimingLabel("First load"));

// Builder Hit with minimum required Timing parameters.
googleAnalytics
.LogTiming(new TimingHitBuilder()
   
.SetTimingCategory("Loading"));

Social Interactions

컨텐츠 안에 내장된 여러 SNS, 추천 위젯 등에 대한 유저 반응을 측정할 수 있다.


Basic

public void LogSocial(string socialNetwork,
   
string socialAction,
   
string socialTarget);

Builder

public void LogSocial(SocialHitBuilder builder);

Example

googleAnalytics.LogSocial("twitter", "retweet", "twitter.com/googleanalytics/status/482210840234295296");

// Builder Hit with all Social parameters (all parameters required).
googleAnalytics
.LogSocial(new SocialHitBuilder()
   
.SetSocialNetwork("Twitter")
   
.SetSocialAction("Retweet")
   
.SetSocialTarget("twitter.com/googleanalytics/status/482210840234295296"));


E-Commerce

GA에 in-game 구매와 판매에 대한 정보를 전달한다.


* 참고 : 이 절차는 GA에서 "전자상거래 보고서"를 사용하기 위해 설정이 필요합니다. (https://support.google.com/analytics/answer/1009612?hl=ko#Enable)


Basic

public void LogTransaction(string transID,
   
string affiliation,
   
double revenue,
   
double tax,
   
double shipping);

public void LogTransaction(string transID,
   
string affiliation,
   
double revenue,
   
double tax,
   
double shipping,
   
string currencyCode);

Builder

public void LogTransaction(TransactionHitBuilder builder);

Example

googleAnalytics.LogTransaction("TRANS001", "Coin Store", 3.0, 0.0, 0.0);
googleAnalytics
.LogTransaction("TRANS001", "Coin Store", 3.0, 0.0, 0.0, "USD");

// Builder Hit with all Transaction parameters.
googleAnalytics
.LogTransaction(new TransactionHitBuilder()
   
.SetTransactionID("TRANS001")
   
.SetAffiliation("Coin Store")
   
.SetRevenue(3.0)
   
.SetTax(0)
   
.SetShipping(0.0)
   
.SetCurrencyCode("USD"));

// Builder Hit with minimum required Transaction parameters.
googleAnalytics
.LogTransaction(new TransactionHitBuilder()
   
.SetTransactionID("TRANS001")
   
.SetAffiliation("Coin Store"));


Items

Basic

public void LogItem(string transID,
   
string name,
   
string SKU,
   
string category,
   
double price,
   
long quantity);

public void LogItem(string transID,
   
string name,
   
string SKU,
   
string category,
   
double price,
   
long quantity,
   
string currencyCode);

Builder

public void LogItem(ItemHitBuilder builder);

Example

googleAnalytics.LogItem("TRANS001", "Sword", "SWORD1223", "Weapon", 3.0, 2);
googleAnalytics
.LogItem("TRANS001", "Sword", "SWORD1223", "Weapon", 3.0, 2, "USD");

// Builder Hit with all Item parameters.
googleAnalytics
.LogItem(new ItemHitBuilder()
   
.SetTransactionID("TRANS001")
   
.SetName("Sword")
   
.SetSKU("SWORD1223")
   
.SetCategory("Weapon")
   
.SetPrice(3.0)
   
.SetQuantity(2)
   
.SetCurrencyCode("USD"));

// Builder Hit with minimum required Item parameters.
googleAnalytics
.LogItem(new ItemHitBuilder()
   
.SetTransactionID("TRANS001")
   
.SetName("Sword")
   
.SetSKU("SWORD1223"));

Custom Dimensions & Metrics

Custom Dimemsions은 GA에서 hits, 유저들, 그리고 세션들을 가진 metadata의 묶음이다. Custom Metrics는 GA에서 당신 자신의 통계를 생성하고 증가시킬 수 있다.


사용전에 각각에 대해 생성과 설정이 필요하다. 설정 이후에는 Builder method를 통해 해당 부분으로 전송될 수 있다.


Builder

// Custom Dimension.
public T SetCustomDimension(int dimensionNumber, string value);
// Custom Metric.
public T SetCustomMetric(int metricNumber, string value);


Example

// Custom Dimension.
// An AppView hit example, but custom dimensions can be sent with all hit types.
googleAnalytics
.LogScreen(new AppViewHitBuilder()
   
.SetScreenName("Another screen")
   
.SetCustomDimension(1, "200"));

// Custom Metric.
// An Event hit example, but custom metrics can be sent with all hit types.
googleAnalytics
.LogEvent(new EventHitBuilder()
   
.SetEventCategory("Achievement")
   
.SetEventAction("Unlocked")
   
.SetEventLabel("Slay 10 dragons")
   
.SetEventValue(5)
   
.SetCustomMetric(3, "200"));

Campaigns

GA에서 Campaigns는 게임에서 유저가 활성화하는 campaigns와 통신 소스들의 속성을 활성화한다.

Campaign 파라미터들은 Builder method를 사용해 어떤 hit의 부분으로 보내질 수 있다.


Build

public T SetCampaignName(string campaignName);
public T SetCampaignSource(string campaignSource);
public T SetCampaignMedium(string campaignMedium);
public T SetCampaignKeyword(string campaignKeyword);
public T SetCampaignContent(string campaignContent);
public T SetCampaignID(string campaignID);

Example

googleAnalytics.LogTiming(new TimingHitBuilder()
   
.SetTimingCategory("Loading")
   
.SetTimingInterval(50L)
   
.SetTimingName("Main Menu")
   
.SetTimingLabel("First load")
   
.SetCampaignName("Summer Campaign")
   
.SetCampaignSource("google")
   
.SetCampaignMedium("cpc")
   
.SetCampaignKeyword("games")
   
.SetCampaignContent("Free power ups")
   
.SetCampaignId("Summer1"));

// Send campaign parameters with timing hit.
// Builder Hit with minimum required Campaign parameters.
googleAnalytics
.LogTiming(new TimingHitBuilder()
   
.SetTimingCategory("Loading")
   
.SetTimingInterval(50L)
   
.SetTimingName("Main Menu")
   
.SetTimingLabel("First load")
   
.SetCampaignSource("google");


Advanced

이 method는 오직 tracker concepts를 가진, GA의 파워유저가 사용하길 추천한다. 


SetOnTracker

다른 hits로 보내진 값을 추적하는 값을 세팅하는 것. (? 약간 이해가 안감. 테스트하면서 다시 봐야 할 듯.)

fieldName 파라미터를 위해 Assets/Plugins/Fields.cs 의 변수들을 사용해라. (예를들면,Fields.SCREEN_NAME 같은..)

public void SetOnTracker(Field fieldName, object value);

* 참고: 같은 값을 전달하면 중복됩니다.


Example

googleAnalytics.SetOnTracker(Fields.SCREEN_NAME, "Main Menu");


Dispose

관리중인 리소스들을 해제하고 tracker를 초기화 한다.


만약 dispose 이후에 어떤 tracking hit이 호출되면, 새로운 tracker가 생성된다. dispose는 실제로 모든 tracking이 완료된 이후에 호출할 것! 예를들면, 게임이 종료될 때.

public void Dispose();

Example

googleAnalytics.Dispose();


이상. 일단 기본 API 문서를 살펴보았다.


다음에는 Unity 테스트 프로젝트에 적용하고, 그 결과를 Google Analytics 보고서에서 보는 결과를 정리하겠다.


즐건 하루 ! 



아래 주소에서 package를 다운로드 할 수 있다. 이 글 작성일 기준으로 아직 베타임.


https://github.com/googleanalytics/google-analytics-plugin-for-unity?hl=ko



이를 사용하기 위한 정책이 있다.(변경 될 수 있으니 , https://developers.google.com/analytics/devguides/collection/unity/policy?hl=ko 를 꼭 읽어볼 것!)


1. 당연하지만, Google Analytics Account가 필요하다.


2. End User에서 당신이 Analytics로 전송하는 데이터에 대한 동의를 얻어야 하며, 유저에게 보낼지 말지를 선택할 수 있는 옵션을 제공해야 한다.


3. 이메일, Social Security Numbers(주민등록번호 같은), 기기를 구별할 수 있는 특별한 정보 등의 개인 혹은 장비를 식별 할 수 있는 중요한 정보를 업로드하면 안된다. 


4. 개인을 식별할 수 있는 어떤 정보를 넘긴다면, 당신의 계정은 삭제될 것이며, 업로드된 데이터 또한 잃어버리게 될 것이다.



설정하는 과정은 아래와 같다.


Android 용


1. 빌드 타겟을 Android로 한 후 build를 하면 Temp/StagingArea 디렉토리(당신이 빌드를 선택한 디렉토리 아래에 생성될 것이다.)에서 AndroidManifest.xml 파일을 복사해서 <YOUR PROJECT ROOT>/Assets/Plugins/Android/ 폴더에 복사하라. 


2. AndroidManifest.xml 파일, <application> tag 위에 아래의 permissions를 추가하라. (이 어플리케이션이 네트웍에 접속을 허용한다는 권한임.)

  <uses-permission android:name="android.permission.INTERNET"/>

  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>


3. Campaign Tracking을 활성화 하길 원한다면, 아래 서비스를 추가하라.

<service android:name="com.google.analytics.tracking.android.CampaignTrackingService" />
<receiver android:name="com.google.analytics.tracking.android.CampaignTrackingReceiver"
         
android:exported="true" >
 
<intent-filter>
   
<action android:name="com.android.vending.INSTALL_REFERRER" />
 
</intent-filter>
</receiver>

IOS 용


1. XCode 프로젝트에 아래 라이브러리들을 추가해라.

  AdSupport,framework

  CoreData,framework

  SystemConfiguration.framework

  libz.dylib

  libsqlite3.dylib


2. 만약 빌드할 때 자동으로 추가되길 원한다면 iOS Extras 디렉토리에서 PostProcessBuildPlayer_GA 파일을 복사하여, <YOUR PROJECT ROOT>/Assets/Editor 디렉토리에 넣어라.


3. mod_pbxproj.py 스크립트를 다운로드해서 Editor 디렉토리에 복사해라. 라이브러리들은 빌드할 때 자동으로 추가될 것이다.


* 참고 : libsqlite3.dylib는 Xcode에서 -ObjC 링커 플래그를 사용할 때만 필요하며 만약 그 플래그를 사용하지 않는다면 PostProcessBuildPlayer_GA 파일에서 삭제해도 괜찮다.



GAv3 prefab 설정하기


1. GAv3.prefab을 클릭하라. Project View,  Assets/Plugins/GoogleAnalyticsV3안에서 찾을 수 있다.
2. Inspector view에서는 여러 정보들의 리스트를 볼 수 있으며, 당신의 프로젝트에 알맞은 값으로 설정해야 한다.
3. Object Hierarchy에 삽입하라.

* 참고 : 모든 플렛폼에 같은 값은 사용할 수 있다. 

오브젝트 트랙하기

GAv3 prefab을 설정 한 후, 아래 스탭들을 따라가면 특정 오브젝트를 추적할 준비가 완료된다.

1. 추적할 오브젝트를 클릭하고 해당 객체의 스크립트를 편집하자. 없다면 Add Component 버튼으로 새로운 스크립트를 만들자.

2. 해당 클래스에 아래처럼 GoogleAnalyticsV3 오브젝트를 생성하자.
public GoogleAnalyticsV3 googleAnalytics;

3. 스크립트를 저장하고 Unity 윈도우로 돌아가자.


4. 추적하고 싶은 객체의 Inspector view를 보자. 이제 googleAnalytics라고 명명된 필드를 볼 수 있고, 이곳에 Object Hierarchy view에서 GAv3 객체를 찾아 드래그 하여 넣어주자.


5. 이제 해당 객체를 추적할 준비가 되었다. 다른 객체들도 추척할 내용이 있다면 위의 과정을 반복하여 설정하면 된다.



이제 본격적으로 API 페이지를 읽어봐야겠다. +_+ GOGO !!!





(windows 환경)


nodejs에서 80포트 열어 쓰던 어플이 있는데, 어느날 갑자기


error: listen EACCES 0:0:0:0:80 에러를 뱉으면서 안된다. --a


netstat -ano 하면 ip,port 그리고 해당 포트를 사용하는 PID를 볼 수 있다. 


찾아보니 4 ... System이 쓰고 있다고. -- ㅁ.... 모지..


이래저래 찾아보니.. 최근에 로컬에 mssql을 설치했는데.. 


SQL Server Reporting Services가 내부적으로 80포트를 쓰고 있었네 --;


서비스 중지 시키니 잘 돌아감. 


휴 ~ 



방법을 몰라서 인터넷을 찾아보니 사람마다 다 방법이 다르다. --;;


var old = new Date ( 특정일 );

var now = new Date();

var gap = new Date( 0,0,0,0,0, now- old);


이렇게 처리한 분도 있던데.. 내가 원하는 값은 아니었고.. 


시간, 분, 초, ms 차이를 알고 싶었기에.. 이거저거 뒤져보다.. 

getTime 인터페이스가 있어 사용해보니.. OK!!


var old = new Date ( 특정일  or 시간);

var now = new Date();


var gap = now.getTime() - old.getTime();

var sec_gap = gap / 1000;
var min_gap = gap / 1000 /60;

이런 식으로 처리 가능!!

 


  1. 조조나리 2016.03.10 16:46 신고

    var now = new Data(); - > var now = new Date();
    오타입니다.

이전에서는 LED를 주기적으로 깜밖이는 것만 했었다. 이번에는 두가지를 복합적으로 해봐야겠다. 


이거 다음엔 바로 인터넷 라디오로 간다. -0-a


일단 오늘의 보드는 아래와 같이 설정한다.




LED : 11번 핀에서 입력을 받아 330옴 저항을 통해 LED의 긴다리(+)로 연결되고 짧은다리(-)에서 GND로 나간다. 


YELLOW BUTTON : 3.3V로 전원이 들어가고 10K옴을 통해 버튼으로 들어간다. 위 그림에서 위 오른쪽 다리 방향으로 GND로 이어지고, 버튼의 입력은 18번 핀으로 받도록 설정했다. 


Raspberry pi2 이름로 각 핀의 wiringpi 번호는 아래와 같다. 



개발 목표는 버튼을 누르면 10초간 LED가 켜지고, 지정한 사운드를 출력하도록 한다. 출력 중 입력이 다시 들어오면 기존의 사운드를 중지하고 다시 출력하도록 하자. 


코드는 아래와 같다. 

#include <stdio.h>

#include <stdlib.h>

#include <wiringPi.h>


int main (void)

{

  int SWITCH = 5; //  pin 18

  int LED = 0; // pin 11

  int sndPID = 0;

  

  if(-1 == wiringPiSetup())

    return 1;

  pinMode( SWITCH, INPUT); // 버튼의 입력을 받는다.

  pinMode (LED, OUTPUT) ;  // LED에 신호를 보낸다.


  for (;;)

  {

    digitalWrite (LED, 0) ;

    if( digitalRead(SWITCH) == 0)

    {

       digitalWrite (LED, 1) ;

       sndPID = fork();

       if(sndPID == 0)

       {

          // 사운드 출력에는 mplayer를 사용한다. 기존에 출력 중이라면 중지시킨다.

          system("killall mplayer");

          execlp("/usr/bin/mplayer", " ", "/home/pi/media/sound/dragon.wav", NULL);  

       }


       delay(10000); // ms. 10초간 불을 켜둔다.

    }

  }

  return 0 ;

}


mplayer 설치법은 여기 를 참고하길 바란다.


테스트 사운드는 아이가 가지고 노는 요괴워치 중 하나를 녹음 한거라 음질이 엄청 나쁘니 양해 바란다. ^^a





이상. 다음은 인터넷 라디오 프로토타입으로 하단의 "인터넷 라디오" 카테고리에 업데이트 됩니다. ^^

'개발/경험 > RaspberryPi' 카테고리의 다른 글

버튼으로 LED, Sound 처리하기  (0) 2015.05.01
blink 샘플 실행  (0) 2015.04.29
기본적이지만 중요 정보 몇가지  (0) 2015.04.18
드디어 왔다!!  (0) 2015.04.17

gpio의 helloworld 예제인 블링크를 wiringPi를 이용해 샘플을 실행해 봤다.


일단 wiringPi lib 설치부터... 아래와 같다. 


설치


1. git 설치

sudo apt-get install git-core


2. wiringPi 프로젝트 다운

git clone git://git.drogon.net/wiringPi


3. build

clone한 위치에 wiringPi안에 들어가서 ./build 실행.

빌드가 이상없이 되었다면 "find / -name "gpio"를 실행해 보자. 

"/usr/local/bin"과 방금 빌드한 곳, 두 곳에 gpio를 발견할 수 있다.

빌드한 곳 gpio 폴더 안에서 ./gpio -v 한 결과와, 

gpio -v 한 결과가 다르다면 gpio 파일을 "/usr/local/bin"에 복사해주라. 

build하면 복사될 줄 알았는데 안된 듯. pi2라서 gpio old version에서 제대로 인식을 못해서 한참 원인을 찾다보니 이거였어.


4. raspberryPi의 핀 번호 및 역할 보기

gpio를 활용하면 보드에 핀 번호를 어떻게 보는지 쉽게 알 수 있다.

"gpio readall" 을 해보면 아래와 같은 결과를 볼 수 있다.     

보드에는 두 줄의 핀이 있는데 rapberryPi2는 위와 같은 순서로 구성되어 있다. 위 표 중앙에 Physical 부분이 보드의 핀 순서와 일치한다. (1,2번이 보드의 전원램프 쪽. 39,40이 usb가 위치한쪽)

Physical을 중심으로 양쪽의 컬럼명이 일치하는 것을 볼 수 있다. (노란색 라인을 참고할 것!)

각 컬럼의 정보는 다음과 같다. 

 BCM 

 Broadcom의 BCM2835 칩에서 사용하는 핀번호

 wPi 

 WiringPi 라이브러리의 핀번호

 Name 

 GPIO의 이름

 Mode 

 IN - 입력모드 ,  OUT - 출력모드

 V

 핀의 값. 1 - 전압이 High상태, 0 - Low상태

 Physical

 핀헤더의 번호

붉은색 라인 부분을 보자.

wiringPi의 blink 샘플을 보면 pin값을 0으로 사용한다. wiringPi에서 0은 wPi가 0인 것이며, 핀헤더 번호는 11번, 핀의 위치는 전원램프 쪽에서 6번째에 위치하다는 걸 알 수 있다. 

이제 샘플 코드를 보자. 


5. 샘플 코드

#include <wiringPi.h>

int main (void)

{

  int PIN = 0;

  wiringPiSetup () ;

  pinMode (PIN, OUTPUT) ;

  int max_count = 5;

  int cnt = 0;

  for (;;)

  {

    digitalWrite (PIN, HIGH) ;

    delay (500) ;

    digitalWrite (PIN,  LOW) ;

    delay (500) ;

    ++cnt;

    if(cnt>=max_count)

        break;

  }

  return 0 ;

}

기존의 샘플 코드에서 LED의 깜밖임이 5번 반복 후 종료하도록 수정했다. PIN변수는 wPi값을 의미한다. 


빌드는 아래와 같이 하면된다.

gcc -o blink blink.c -l:libwiringPi.so.2.25 -I/usr/local/include -L/usr/local/lib

어떤 샘플에서 lib 링크할 때 -lwiringPi 로 되어 있는데 libwiringPi.so 를 링크하겠다는 이야기다. 
새로 받아 빌드한 경우 버전명이 lib 끝에 붙는데 이를 정확히 사용하기 위해서는 위와 같이 입력하면 된다

6. 실행
./blink를 실행해보자. 아래와 같은 결과를 볼 수 있다.




'개발/경험 > RaspberryPi' 카테고리의 다른 글

버튼으로 LED, Sound 처리하기  (0) 2015.05.01
blink 샘플 실행  (0) 2015.04.29
기본적이지만 중요 정보 몇가지  (0) 2015.04.18
드디어 왔다!!  (0) 2015.04.17

기본 id는 "pi", pw는 "raspberry".

--------------------------------

sd에 라즈비안 설치 시 기본 비번은 변경하는게 좋으며, 

초기 설정에서 놓쳤다면 이후 "raspi-config"를 입력하면 다시 설정할 수 있다.


보드에 전원 스위치가 없다.

--------------------------------

전원이 연결되면 바로 가동되는데, 종료시 전원을 바로 내리면 주변장치에 문제가 발생할 수 있다. ( sd카드와 같은.. )

" shutdown -h now " 커멘트를 통해 꼭 모든 디바이스가 unmount 된 이후 종료되도록 해줘야 한다.

재가동하려면 전원선을 뺐다가 다시 연결하니 되네. 이거 몰라서 한참 찾음.


SD 카드는 가능한 큰걸로

---------------------------------

http://www.raspberrypi.org/downloads 에서 os 이미지를 다운받아 http://sourceforge.net/projects/win32diskimager/ 유틸리티를 이용해 SD에 구워 사용하게 되며, 보통 이 sd를 통해 계속 운영하게 된다. 

GPIO용이 아닌 개발 device로 사용하려면 여러가지 라이브러리를 사용해야 하기 때문에 가능한 큰 용량의 sd로 시작하는게 좋다.


전원만 연결하면 원격으로 바로 사용할 수 있게 세팅하자.

---------------------------------

이를 위해 무선랜 설치, 자동 로그인 두가지 설정이 필요하다. 

아래 과정시 관리자 권한을 필요로 하기 때문에 sudo를 입력하거나 혹은 sudo su를 입력 후 아래 절차를 진행하자.


무선랜 설치

------------------------------------

공간활용을 위해 가능한 무선랜을 추천한다. 난 처음 구매시 netis 제품이 동봉되어 도착했다.

무선랜은 아래와 같은 순서로 설치하면 된다. (x-windows에서 설정은 간단하니 패스, 콘솔에서 설정하는 방법을 다룬다.)


1. 설치된 공유기에 접속 설정

nano /etc/wpa_supplicant/wpa_supplicant.conf 를 실행하면 아래와 같은 화면이 뜬다.



아래와 같이 입력하자. ssid와 psk는 각자 공유기의 설정에 따른 값을 입력해야 한다.



nano editor는 vi보다는 좀 더 사용하기 쉽다. 


문자열을 찾을 때는 ctrl+w 입력 후 찾고자 하는 문자를 입력하면 된다. 

ctrl+x를 입력하면 수정된 경우, overwrite할지 물어보고 Y를 입력하면 저장하고 종료된다.


2. nic(network interface card) 설정


nano /etc/network/interfaces 를 입력하고 해당 정보를 아래와 같이 수정한다.



이제 설정은 모두 마무리 되었다. 아래와 같이 무선 인터넷을 재시작해보자.


ifdown wlan0

ifup wlan0


만약 에러가 발생한다면 해당 메세지에 따라 수정이 필요할 수 있다. 잘 안된다면 전체 오류 메세지를 댓글로 달아주면 확인 후 답변 할지도 ^^;;;


재시작되면 ifconfig 명령으로 할당된 ip를 확인할 수 있다. 이제 자동 로그인 되도록 해보자.


2. 자동 로그인 설정


nano /etc/inittab 를 입력해 시스템 기동시 처리되는 내용이 기록된 파일을 연다.


각 런레벨별로 실행하는 정보 라인을 찾아보자. 


1:2345:respawn:/sbin/getty --noclear 38400 tty1  => 이와 유사한 라인을 찾아볼 수 있다. ctrl+w로 noclear를 검색해서 찾아보자.


이를 주석 처리하고 (문장 제일 앞에 #을 붙이면 된다.), 아래 라인을 입력하자.


1:2345:respawn:/bin/login -f pi tty1 </dev/tty1 > /dev/tty1 2>&1


위 문장의 상세한 설명은 생략한다. -0-a

이제 시스템을 재시작해보면 자동으로 로그인 되는 모습을 볼 수 있다.


'개발/경험 > RaspberryPi' 카테고리의 다른 글

버튼으로 LED, Sound 처리하기  (0) 2015.05.01
blink 샘플 실행  (0) 2015.04.29
기본적이지만 중요 정보 몇가지  (0) 2015.04.18
드디어 왔다!!  (0) 2015.04.17

+ Recent posts