# Unity SDK

[Treasure AI](https://www.treasuredata.com/) の Unity SDK を使うと、Unity アプリケーションからイベントを簡単に Treasure AI にインポートできます。この SDK を使えば、モバイルアプリのアクティビティをトラッキングするためにサーバー側に何かをインストールすることなく、Unity アプリケーションからデータを送信できます。

## 前提条件

- Unity 開発の基本的な知識
- Treasure AI の基本的な知識
- Treasure AI の Write-Only API キー


Unity SDK は GitHub から入手できます。最新の SDK を入手するには、リポジトリを確認してください:

- [https://github.com/treasure-data/td-unity-sdk-package](https://github.com/treasure-data/td-unity-sdk-package)


## セットアップ

この [Unity パッケージ](https://github.com/treasure-data/td-unity-sdk-package/raw/master/TD-Unity-SDK-0.1.10.unitypackage)をダウンロードし、**Assets -> Import Package -> Custom Package** から Unity プロジェクトにインポートします。

### iOS アプリケーション開発の場合

Xcode で、Treasure Data iOS SDK を次のように `Podfile` に追加します:

```ruby
platform :ios, '12.0'

target 'Unity-iPhone' do
  use_frameworks!
  inherit! :search_paths
end

target 'UnityFramework' do
  use_frameworks!

  pod 'TreasureData-iOS-SDK', '= 1.0.1'
end
```

## 基本的な使い方

### API キーを使って TreasureData オブジェクトをインスタンス化する

```csharp
public class MyTreasureDataPlugin : MonoBehaviour {
#if UNITY_IPHONE || UNITY_ANDROID
  [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
  static void OnRuntimeInitialization() {
    TreasureData.InitializeApiEndpoint("https://us01.records.in.treasuredata.com");
    TreasureData.InitializeApiKey("YOUR_API_KEY");
  }
#endif
}
```

Treasure AI では、インジェストおよびインポート操作、ならびに Treasure Data SDK を使用する際は、常に write-only API キーを使用することを強く推奨します。

Write-Only API キーの取得方法
1. Treasure Console にログインし、[API Key ページ](https://console.treasuredata.com/app/mp/ak)に移動します。
2. write-only API キーをまだ持っていない場合は作成します。右上の **Actions > Create API Key** を選択します。
3. 新しい API キーに名前を付けます。
4. Type ドロップダウンメニューから **Write-only** を選択します。
5. **Save** を選択します。
6. 新しい Write-Only API キーをコピーし、プロジェクトの API 認証に使用します。


### イベントをローカルバッファに追加する

イベントをローカルバッファに追加するには、`AddEvent` 関数を使用します。

```csharp シンプル
TreasureData.Instance.AddEvent("testdb", "unitytbl", ev);
```

```csharp 応用例
Dictionary<string, object> ev = new Dictionary<string, object>();
ev["str"] = "strstr";
ev["int"] = 12345;
ev["long"] = 12345678912345678;
ev["float"] = 12.345;
ev["double"] = 12.3459832987654;
ev["bool"] = true;
TreasureData.Instance.AddEvent("testdb", "unitytbl", ev,
    delegate() {
        Debug.LogWarning ("AddEvent Success!!!");
    },
    delegate(string errorCode, string errorMsg) {
        Debug.LogWarning ("AddEvent Error!!! errorCode=" + errorCode + ", errorMsg=" + errorMsg);
    }
);
```

イベントのインポート先となるデータベースとテーブルを指定します。データベース名とテーブル名の合計の長さは 129 文字未満である必要があります。

### イベントを Treasure AI にアップロードする

バッファされたイベントを Treasure AI にアップロードするには、`UploadEvents` 関数を使用します。この API は任意のタイミングで呼び出せます。

```csharp シンプル
TreasureData.Instance.UploadEvents();
```

```csharp 応用例
TreasureData.Instance.UploadEvents (
    delegate() {
        Debug.LogWarning ("UploadEvents Success!!! ");
    },
    delegate(string errorCode, string errorMsg) {
        Debug.LogWarning ("UploadEvents Error!!! errorCode=" + errorCode + ", errorMsg=" + errorMsg);
    }
);
```

バッファされたイベントをいつ、どの頻度でアップロードするかは、アプリケーションの特性によって決まります。Treasure AI では、次のタイミングでのアップロードを推奨します:

- 現在の画面が閉じられるとき、またはバックグラウンドに移行するとき
- アプリケーションを終了するとき


`UploadEvents` は数分間バッファしてから、Treasure AI ストレージへのインポートを開始します。

### アップロードの再試行と重複排除

この SDK は、次の機能の組み合わせにより、イベントを exactly once 方式でインポートします:

- SDK はバッファされたイベントに一意のキーを付与して保持し、イベントがサーバー側にアップロードされ保存されたことを確認できるまで再試行します（at least once）
- サーバー側はデフォルトで過去 1 時間以内のすべてのイベントの一意のキーを記憶し、重複したインポートを防ぎます（at most once）


重複排除のウィンドウはデフォルトで 1 時間です。重複イベントを避けるため、バッファされたイベントをそれより長く保持しないことが重要です。

### セッションの開始と終了

`StartGlobalSession` メソッドを呼び出すと、SDK は `EndGlobalSession` が呼び出されるまで保持されるセッションを生成します。セッション ID は Treasure AI 上で列名 "`td_session_id`" として出力されます。また、セッション ID は `GetGlobalSessionId` で取得できます。

```csharp
TreasureData.InitializeDefaultDatabase("testdb");
td = new TreasureData("your_api_key");
print("Session ID = " + TreasureData.GetGlobalSessionId());   // >>> (null)

TreasureData.StartGlobalSession();
print("Session ID = " + TreasureData.GetGlobalSessionId());   // >>> cad88260-67b4-0242-1329-2650772a66b1
    :
TreasureData.Instance.AddEvent("testdb", "unitytbl", ev);
    :
TreasureData.EndGlobalSession();
print("Session ID = " + TreasureData.GetGlobalSessionId());   // >>> (null)
    :
TreasureData.Instance.AddEvent("testdb", "unitytbl", ev);

// Outputs =>>
//   [{"td_session_id":"cad88260-67b4-0242-1329-2650772a66b1",
//       ..., "time":1418880000},
//        :
//    {..., "time":1418880123}
//   ]
```

セッションは `StartGlobalSession` が呼び出されてから `EndGlobalSession` が呼び出されるまで継続します。`EndGlobalSession` の呼び出しから 10 秒以内に `StartGlobalSession` が呼び出された場合、前のセッションが再開され、新しいセッションは作成されません。

インスタンスレベルのきめ細かいセッションを使用したい場合は、`TreasureData#StartSession(tableName)` / `TreasureData#EndSession(tableName)` / `TreasureData#GetSessionId()` を使用できます。これらは `StartSession` / `EndSession` の呼び出し時にセッションイベントを追加し、セッション再開機能はありません。

グローバルセッションとインスタンスセッションの違い、それぞれがテーブルに書き込む内容、使い分けについては、[モバイル SDK でのセッショントラッキング](/products/customer-data-platform/integration-hub/streaming/mobile/tracking-sessions-with-mobile-sdks)を参照してください。

## 高度な使い方

### アプリケーションライフサイクルイベントのトラッキング

SDK では、アプリのライフサイクルイベントの自動キャプチャをオプションで有効化できます（デフォルトでは無効）。このオプションは明示的に有効化する必要があります。送信先テーブルは `DefaultTable` で設定できます:

```csharp
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void OnRuntimeInitialization() {
  // TreasureData クライアントのセットアップ...
  TreasureData.DefaultTable = "app_lifecycles";
  TreasureData.Instance.EnableAppLifecycleEvent();
}
```

自動的にトラッキングされるイベントは 3 種類あります:

- Application Open
- Install
- Update


```json Application Open
{
    "td_unity_event": "TD_UNITY_APP_OPEN",
    "td_app_ver": "1.0",
    ...
}
```

```json Application Install
{
    "td_unity_event": "TD_UNITY_APP_INSTALL",
    "td_app_ver": "1.0",
    ...
}
```

```json Application Update
{
    "td_unity_event": "TD_UNITY_APP_UPDATE",
    "td_app_ver": "1.1",
    "td_app_previous_ver": "1.0",
    ...
}
```

### アプリ内購入イベントのトラッキング

有効化すると、Treasure Data SDK は自分でリッスンして `AddEvent` を呼び出すことなく、IAP イベントを自動的にトラッキングできます。この機能の有効化・無効化には次を使用します:

```csharp EnableInAppPurchaseEvent
TreasureData.Instance.EnableInAppPurchaseEvent();
```

```csharp DisableInAppPurchaseEvent
TreasureData.Instance.DisableInAppPurchaseEvent();
```

アプリ内購入イベントのトラッキングは、デフォルトでは無効です。

アプリケーションが動作するネイティブプラットフォームによって、イベントのスキーマは異なる場合があります:

| Android | iOS |
|  --- | --- |
| - `td_android_event`
- `td_iap_product_id`
- `td_iap_order_id`
- `td_iap_product_price`
- `td_iap_quantity`
- `td_iap_product_price_amount_micros`
- `td_iap_product_currency`
- `td_iap_purchase_time`
- `td_iap_purchase_token`
- `td_iap_purchase_state`
- `td_iap_purchase_developer_payload`
- `td_iap_product_type`
- `td_iap_product_title`
- `td_iap_product_description`
- `td_iap_package_name`
- `td_iap_subs_auto_renewing`
- `td_iap_subs_status`
- `td_iap_subs_period`
- `td_iap_free_trial_period`
- `td_iap_intro_price_period`
- `td_iap_intro_price_cycless`
- `td_iap_intro_price_amount_micros`

 | - `td_ios_event`
- `td_iap_transaction_identifier`
- `td_iap_transaction_date`
- `td_iap_quantity`
- `td_iap_product_identifier`
- `td_iap_product_price`
- `td_iap_product_localized_title`
- `td_iap_product_localized_description`
- `td_iap_product_currency_code`

 |


これらの列の値の詳細については、Android / iOS SDK のドキュメントを参照してください:

- [Android SDK - IAP Tracking](https://github.com/treasure-data/td-android-sdk#track-in-app-purchase-events-automatically)
- [iOS SDK - IAP Tracking](https://github.com/treasure-data/td-ios-sdk#app-lifecycle-events)


## 追加設定

### エンドポイント

API エンドポイント（デフォルト: https://us01.records.in.treasuredata.com）は `InitializeApiEndpoint` で変更できます:

```csharp
TreasureData.InitializeApiEndpoint("https://us01.records.in.treasuredata.com");
```

### 暗号化キー

`TreasureData.InitializeEncryptionKey()` で暗号化キーを設定すると、SDK は `AddEvent` の呼び出し時にイベントデータを暗号化して保存します。

```csharp
TreasureData.InitializeEncryptionKey("hello world");
    :
TreasureData.Instance.AddEvent("testdb", "unitytbl", ev);
```

### デフォルトデータベース

```csharp
TreasureData.InitializeDefaultDatabase("testdb");
    :
TreasureData.Instance.AddEvent("unitytbl", ev);
```

### デバイスの UUID を各イベントに自動的に追加する

`EnableAutoAppendUniqId` を呼び出すと、デバイスの UUID が各イベントに自動的に追加されます。この値はアプリケーションがアンインストールされるまで変わりません。

```csharp
TreasureData.Instance.EnableAutoAppendUniqId();
    :
TreasureData.Instance.AddEvent("unitytbl", "name", "foobar");
// Outputs =>>
//   {"td_uuid":"cad88260-67b4-0242-1329-2650772a66b1", "name":"foobar", ... }
```

値は列名 `td_uuid` として出力されます。

### UUID を各イベントレコードに自動的に追加する

`EnableAutoAppendRecordUUID` を呼び出すと、UUID が各イベントレコードに自動的に追加されます。イベントごとに異なる UUID になります。

```csharp
TreasureData.Instance.EnableAutoAppendRecordUUID();
// 列名をカスタマイズしたい場合は、API に渡します
// TreasureData.Instance.EnableAutoAppendRecordUUID("my_record_uuid");
    :
TreasureData.Instance.AddEvent(...);
```

値はデフォルトで列名 `record_uuid` として出力されます。

### デバイスのモデル情報を各イベントに自動的に追加する

`EnableAutoAppendModelInformation` を呼び出すと、デバイスのモデル情報が各イベントに自動的に追加されます。

```csharp
TreasureData.Instance.EnableAutoAppendModelInformation();
    :
TreasureData.Instance.AddEvent("unitytbl", "name", "foobar");
// Outputs =>>
//   {"td_device":"iPod touch", "name":"foobar", ... }
```

次の列名と値が出力されます:

| iOS | Android |
|  --- | --- |
| - `td_device` : UIDevice.model
- `td_model` : UIDevice.model
- `td_os_ver` : UIDevice.model.systemVersion
- `td_os_type` : "iOS"

 | - `td_board` : android.os.Build#BOARD
- `td_brand` : android.os.Build#BRAND
- `td_device` : android.os.Build#DEVICE
- `td_display` : android.os.Build#DISPLAY
- `td_model` : android.os.Build#MODEL
- `td_os_ver` : android.os.Build.VERSION#SDK_INT
- `td_os_type` : "Android"

 |


### アプリケーションパッケージのバージョン情報を各イベントに自動的に追加する

`EnableAutoAppendAppInformation` を呼び出すと、アプリケーションパッケージのバージョン情報が各イベントに自動的に追加されます。

```csharp
TreasureData.Instance.EnableAutoAppendAppInformation();
    :
TreasureData.Instance.AddEvent("unitytbl", "name", "foobar");
// Outputs =>>
//   {"td_app_ver":"1.2.3", "name":"foobar", ... }
```

次の列名と値が出力されます:

| iOS | Android |
|  --- | --- |
| - `td_app_ver` : Core Foundation キー `CFBundleShortVersionString`
- `td_app_ver_num` : Core Foundation キー `CFBundleVersion`

 | - `td_app_ver` : android.content.pm.PackageInfo.versionName
- `td_app_ver_num` : android.content.pm.PackageInfo.versionCode

 |


### ロケール設定情報を各イベントに自動的に追加する

`EnableAutoAppendLocaleInformation` を呼び出すと、ロケール設定情報が各イベントに自動的に追加されます。

```csharp
TreasureData.Instance.EnableAutoAppendLocaleInformation();
    :
td.AddEvent("unitytbl", "name", "foobar");
// Outputs =>>
//   {"td_locale_lang":"en", "name":"foobar", ... }
```

次の列名と値が出力されます:

| iOS | Android |
|  --- | --- |
| - `td_locale_country` : [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode]
- `td_locale_lang` : [[NSLocale currentLocale] objectForKey: NSLocaleLanguageCode]

 | - `td_locale_country` : java.util.Locale.getCountry()
- `td_locale_lang` : java.util.Locale.getLanguage()

 |


### デバッグログの有効化・無効化

```csharp EnableLogging
TreasureData.EnableLogging();
```

```csharp DisableLogging
TreasureData.DisableLogging();
```

## エラーコード

`TreasureData.Instance.AddEvent` と `TreasureData.Instance.UploadEvents` は、`errorCode` 引数を付けて `onError` デリゲートメソッドを呼び出します。この引数はエラーの原因や種類を特定するのに役立ちます。エラーコード引数は次のとおりです:

| エラーコード | 説明 |
|  --- | --- |
| `init_error` | 初期化に失敗しました。 |
| `invalid_param` | API に渡されたパラメータが無効です |
| `invalid_event` | イベントが無効です |
| `data_conversion` | JSON との相互変換に失敗しました |
| `storage_error` | ストレージのデータの読み取り/書き込みに失敗しました |
| `network_error` | ネットワークの問題によりサーバーとの通信に失敗しました |
| `server_response` | サーバーがエラーレスポンスを返しました |


## GDPR コンプライアンス

欧州の一般データ保護規則（GDPR）をはじめとする国内およびグローバルなデータプライバシー要件へのコンプライアンスをサポートするため、SDK はアプリケーションや Web サイトにおける個人データとメタデータの収集・トラッキングを制御するメソッドを提供しています。

SDK には、煩雑な if-else 文を多用することなく、デバイス全体のトラッキングを簡単にオプトアウトできる便利なメソッドがあります:

```csharp
<treasure_data_instance>.DisableCustomEvent()         // 独自イベントのオプトアウト
<treasure_data_instance>.DisableAppLifecycleEvent()  // TD が生成するイベントのオプトアウト
```

これらは `EnableCustomEvent()` または `EnableAppLifecycleEvent()` を呼び出すことで再度オプトインできます。これらの設定はアプリケーションを再起動しても保持される点に注意してください。一般に、これらのメソッドは SDK の初期化のたびに呼び出すのではなく、ユーザーの選択を反映するときに呼び出すべきです。デフォルトでは、カスタムイベントは有効、アプリライフサイクルイベントは無効です。

以降のイベントでデバイスの識別子をリセットするには `ResetUniqId()` を使用します。`td_uuid` は別の値にランダム化され、`{"td_unity_event": "forget_device_id", "td_uuid": <old_uuid>}` という追加のイベントが `DefaultTable` にキャプチャされます:

```csharp
TreasureData.Instance.ResetUniqId();
```

`ResetUniqId` は監査イベントも `DefaultTable` に追加します:

```json
{
    "td_unity_event": "forget_device_uuid",
    "td_uuid": old_uuid,
    <configured_additional_parameters...>
}
```

Treasure AI のお客様は、個人データを収集する用途を含む SDK の使用が、Treasure Data サービスへのアクセスと使用を規定する法的契約に準拠していることを保証する必要があります:

| Treasure Data | URL |
|  --- | --- |
| Terms of Service | [https://www.treasuredata.com/terms/](https://www.treasuredata.com/terms/) |
| Privacy Policy | [https://www.treasuredata.com/privacy/](https://www.treasuredata.com/privacy/) |
| Privacy Statement for Customer Data | [https://www.treasuredata.com/td-downloads/Privacy-Statement-for-Customer-Data.pdf](https://www.treasuredata.com/td-downloads/Privacy-Statement-for-Customer-Data.pdf) |


## 実機なしでアプリケーションを実行する開発モード

この SDK は Unity Native Plugin として動作します。そのため、特に iOS プラットフォームで実行する場合は、SDK を組み込んだアプリケーションを実機で実行する必要があります。

実機なしで SDK を組み込んだアプリケーションを実行したい場合は、純粋な C# 実装で動作をエミュレートする開発用の特別なモードを使用できます。

### 通常モードとの動作の違い

開発モードでは:

- バッファされたイベントは永続ストレージではなくメモリに保存されます。
- アップロードに失敗した場合、バッファされたイベントは失われます。


### 設定

**PC / iOS / Android / その他のプラットフォームの場合:**

- **Player Settings > Scripting Define Symbols** にシンボル `TD_SDK_DEV_MODE` を追加します


**Unity Editor の場合:**

- 常に有効です。操作は不要です。


### ソースコードの変更

- `MonoBehaviour#Start` メソッド内で `SimpleTDClient.Create()` static メソッドを呼び出して `SimpleTDClient` インスタンスを作成します
- 作成したインスタンスを `TreasureData` インスタンスにアタッチします


```csharp
public class TreasureDataExampleScript : MonoBehaviour {
    private static TreasureData td = null;
    // private TreasureData tdOnlyInTheScene = null;
            :
    void Start () {
        td = new TreasureData("YOUR_WRITE_APIKEY");
        /* オプション設定
            SimpleTDClient.SetDummyAppVersionNumber("77");
            SimpleTDClient.SetDummyBoard("bravo");
            SimpleTDClient.SetDummyBrand("htc_asia_wwe");
            SimpleTDClient.SetDummyDevice("bravo");
            SimpleTDClient.SetDummyDisplay("ERE27");
            SimpleTDClient.SetDummyModel("HTC Desire");
            SimpleTDClient.SetDummyOsVer("2.1");
            SimpleTDClient.SetDummyOsType("android");
            SimpleTDClient.SetDummyLocaleCountry("JP");
            SimpleTDClient.SetDummyLocaleLang("ja");
        */

        // シーンをまたいで TDClient を使いたい場合は、`SimpleTDClient.Create` に `true` を渡して削除されないようにします。
        td.SetSimpleTDClient(SimpleTDClient.Create(true));

        // シーン内でのみ TDClient を使いたい場合は、オブジェクトリークを防ぐため `SimpleTDClient.Create` に `true` を渡さないでください。
        // tdOnlyInTheScene.SetSimpleTDClient(SimpleTDClient.Create());
            :
```