対話システムのプロトタイプの知見のまとめ

#目次

1. スクリプト関連

2. オブジェクト関連

3. パッケージ関連

## 1. スクリプト関連

#### Path モジュール

using System.OS; で使用可能になる。

パス同士をつなげる　Path.Combine
ディレクトリ Path.GetDirectroyName
拡張子ありのファイル名　Path.FileName
拡張子なしのファイル名 Path.FileNameWithoutExtension

#### 他のファイルを使いたい場合

[Serialize Field] 別ファイルのクラス名 変数名;

でオブジェクトを Drag&Drop するのが、なんだかんだ一番楽。

#### 他ファイルのプロパティを参照したい場合。

public プロパティ　だと、[Serialize Field]と同じになる。

public プロパティ{get; set;}とする。

#### null チェック

ReferenceEquals(オブジェクト, null)

## 2.　オブジェクト関連

#### マイク入力をするとループバックでうるさい

AudioMixer を作って、Group に Mic を追加。 MicのdBを最低にして、マイク入力を受け付けるAudio Source のAudioMixer を Mic にすると、音が返ってこなくなる。

#### 画像を押したときに関数呼び出し

画像のオブジェクトに　Event Trigger を追加。　Event Trigger の Add New Event type を押して、Pointer Click　を選択。あとは UI の Button オブジェクトのときのイベント追加と同じ。

#### Font 

.ttf ファイルを Asset フォルダ内のどこかに Drag & Drop! 

#### Json

wavファイルの送受信に用いる
JsonUtility + byte[] と　Json.Net + string の２通りのやり方が存在する

##### Json + byte[]

まず、Jsonを使うためにclassの定義をする

```ChatAPI.cs
        [System.Serializable]
        public class RequestWavJson{
            public byte[] requestWavString;
        }
        [System.Serializable]
        public class ResponseWavJson{
            public byte[] responseWavString;
            public string emotion;
        }
            
```
使うときはこんな感じ

```chatAPI.cs
        public async UniTask<byte[]> ChatWav(string UserWavFilePath, string CharacterWavFilePath){
        var url = "http://localhost:8000";
        var wavBytes = File.ReadAllBytes(UserWavFilePath);
        var wavString = conv(wavBytes);
        var data = new RequestWavJson();
        data.requestWavString = wavBytes;
        data.requestWavString = wavString;
        var jsonData = JsonUtility.ToJson(data); // ここでエラーの原因が発生。
        var response = await wavPost(url, jsonData);
        var jsonResponse = JsonUtility.FromJson<ResponseWavJson>(response);
        var resWavBytes = jsonResponse.responseWavString;
        File.WriteAllBytes(CharacterWavFilePath, resWavBytes);
        return resWavBytes;
        }

        public async UniTask<string> wavPost(string url, string jsonData){
            var request = new UnityWebRequest(url + "/wav", "POST");
            byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData);
            Debug.Log("Length of bodyRaw " + bodyRaw.Length);
            request.uploadHandler = (UploadHandler) new UploadHandlerRaw(bodyRaw);
            request.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer();
            request.SetRequestHeader("Content-Type", "application/json");
            await request.SendWebRequest();
            Debug.Log("Status Code: " + request.responseCode);
            return request.downloadHandler.text;
        }
```

#### Json.Net + string

まず、大前提としてbyte[]はハードコードするのがめんどくさい。pythonでのバイト文字列に相当する関数を作成する.

```ChatAPI.cs
//   #0: 比較用 String
        string conv(byte[] data) {
        // {0, 1, 2, 255} -> "\x00\x01\x02\xFF"
        return new System.String(System.Array.ConvertAll(data, x => (char)x));
        }
// // #0: String
        byte[] rev(string str) {
        return System.Array.ConvertAll(str.ToCharArray(), x => (byte)x);
        }
```
これに加えて、ハードコードしたstringをJSONUtilityに入れると、途中で"}"と同じバイト列が含まれているためにデータが破損する。データを破損させないためにJSON.Netを使用する。
JSON.Netのクラス定義部分は以下

```ChatAPI.cs
    [JsonObject]
    class WavJson
    {
        [JsonProperty("wavString")]
        public string wavString { get; set; }

        [JsonProperty("emotion")]
        public int emotion { get; set; }
    }
```

これを使って、wav ファイルを string に変換し flask の API のエンドポイントへ送信する。

```ChatAPI.cs
      public async UniTask<byte[]> ChatWav(string UserWavFilePath, string CharacterWavFilePath){
        var url = "http://localhost:8000";
        var wavBytes = File.ReadAllBytes(UserWavFilePath);
        var wavString = conv(wavBytes);
        var jsonObj = new WavJson{wavString = wavString};
        var jsonData = JsonConvert.SerializeObject(jsonObj, Formatting.None);
        var response = await wavPost(url, jsonData);
        var jsonResponse = JsonConvert.DeserializeObject<WavJson>(response);
        var resWavBytes = rev(jsonResponse.wavString);
        File.WriteAllBytes(CharacterWavFilePath, resWavBytes);
        return resWavBytes;
        }

        public async UniTask<string> wavPost(string url, string jsonData){
            var request = new UnityWebRequest(url + "/wav", "POST");
            byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData);
            Debug.Log("Length of bodyRaw " + bodyRaw.Length);
            request.uploadHandler = (UploadHandler) new UploadHandlerRaw(bodyRaw);
            request.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer();
            request.SetRequestHeader("Content-Type", "application/json");
            await request.SendWebRequest();
            Debug.Log("Status Code: " + request.responseCode);
            return request.downloadHandler.text;
        }
```



## 3. パッケージ関連

#### [AutoSave](https://gist.github.com/tsubaki/8709502)

Unity の自動保存。マジで便利。

#### [UnityWav](https://github.com/deadlyfingers/UnityWav/blob/master/WavUtility.cs)

保存した wav ファイルを Play 中に Audio clip に変換してくれる優れもの!


以上!