自作Unity標準ライブラリUniCommonの紹介

# ごあいさつ
こんにちは。プログラマの[@keroxp](https://twitter.com)です。ちょうどUnity歴は１年ほどになります。
今年は新卒で入ったLINEという会社を辞めてエモを追求するために１人で「[黒羽のアリカ](http://hexat.studio/arika)」という2Dスマホゲームを作りました。

今はARKitとiPhoneXの機能を使った「黒羽のアリカAR」という3Dアプリを作ったりしています。
3Dに苦戦中でまだこんな感じで途中です（ホントはこれの完成版を記事にしたかった…😫）

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/%E9%BB%92%E7%BE%BD%E3%81%AE%E3%82%A2%E3%83%AA%E3%82%AB?src=hash&amp;ref_src=twsrc%5Etfw">#黒羽のアリカ</a> with <a href="https://twitter.com/hashtag/Unity%E3%81%A1%E3%82%83%E3%82%93?src=hash&amp;ref_src=twsrc%5Etfw">#Unityちゃん</a> 視線の動きと、開閉可能な翼のアニメーション。 <a href="https://t.co/ZPd9InPKVv">pic.twitter.com/ZPd9InPKVv</a></p>&mdash; keroxp＠がんばらない (@keroxp) <a href="https://twitter.com/keroxp/status/939887062064316416?ref_src=twsrc%5Etfw">2017年12月10日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

アリカさんの名前だけでも覚えて帰ってくださいｗ
それでは本題に入ります。

# 結論

年末年始でお忙しい方も多いでしょうから、短い結論から。

- Unityアプリを開発する際に標準的に使う依存性のないライブラリを開発した
- MITライセンス/Githubで公開中 [https://github.com/keroxp/UniCommon](https://github.com/keroxp/UniCommon)
- インストールは `npm i unicommon`でおｋ
- ドキュメントは [https://scrapbox.io/keroxp-blog/UniCommon](https://scrapbox.io/keroxp-blog/UniCommon)を参照
- プルリクエスト大歓迎！

# Unityでのコードの再利用について

Unityを始めてからいくつかのプロジェクトを作成してアプリを作成しているうちに、同じようなコードを度々書いていることに気が付きました。

[![Screenshot from Gyazo](https://gyazo.com/9a52896230bc4291f77ebc29d73ba089/raw)](https://gyazo.com/9a52896230bc4291f77ebc29d73ba089)

流石に全部一から書き直しているわけではないですが、そのたびにファイルを**気合コピペ**したり、コピペだとコンパイルが通らないところを細かく修正したり…とだんだん面倒になってきました。

そこで、自分なりのまとまりがとれた「黒羽のアリカ」の開発で使用したコードの中からゲームに直接関係のないコードを取り出して別プロジェクト化ました。

Unityは2017.2からUnityPackageManagerというパッケージ管理機能が追加されるとアナウンスされているのですが、実際どういうものなのか2017.3の現在もよく分かっていないので、Unityライブラリを配布する方法として使い慣れた`npm`を選択しました。将来的にUPM（？）が動き出したらそちらに対応します。

参考：[Unityプロジェクトの自作パッケージ依存性管理をnpmで行う](https://qiita.com/thorikawa/items/805498282b0d6571a89f)

# インストール方法

MacならUnityプロジェクトルートで以下のコマンドを実行すればインストール完了です。

```bash
npm i unicommon --save
mkdir -p Assets/Plugins/Packages
$(npm bin)/unity3d--sync
```

# ドキュメント目次

自分のScrapboxにドキュメントを作成してあります。全てではありませんが逐次更新予定です。

- [UniCommon機能紹介 - Component](https://scrapbox.io/keroxp-blog/UniCommon%E6%A9%9F%E8%83%BD%E7%B4%B9%E4%BB%8B_-_Component)
- [UniCommon機能紹介 - Log](https://scrapbox.io/keroxp-blog/UniCommon%E6%A9%9F%E8%83%BD%E7%B4%B9%E4%BB%8B_-_Log)
- [UniCommon機能解説 - Files](https://scrapbox.io/keroxp-blog/UniCommon%E6%A9%9F%E8%83%BD%E8%A7%A3%E8%AA%AC_-_Files)
- [UniCommon機能解説 - Asyncs](https://scrapbox.io/keroxp-blog/UniCommon%E6%A9%9F%E8%83%BD%E8%A7%A3%E8%AA%AC_-_Asyncs)
- [UniCommon機能解説 - KVS](https://scrapbox.io/keroxp-blog/UniCommon%E6%A9%9F%E8%83%BD%E8%A7%A3%E8%AA%AC_-_KVS)
- [UniCommon機能解説 - Crypt](https://scrapbox.io/keroxp-blog/UniCommon%E6%A9%9F%E8%83%BD%E8%A7%A3%E8%AA%AC_-_Crypt)
- [UniCommon機能解説 - Enumerators](https://scrapbox.io/keroxp-blog/UniCommon%E6%A9%9F%E8%83%BD%E8%A7%A3%E8%AA%AC_-_Enumerators)

詳細な解説は機能目次から確認していただくとして、UniCommonの中から特に便利な機能を４つ紹介します。

# 便利な機能４選

## Asyncs - お手軽非同期処理

Unityのなかで非同期処理を簡単に実行したいと思ったことはありませんか？  
Asyncsを使えば1行で簡単に非同期処理が実装できます。

```csharp
 // 返り値なし
 Asyncs.Execute(() => {
   // ファイルIOとかの重い処理
 }, () => {
    // 完了。メインスレッドで受け取れる。
 });
 // 返り値あり
 Asyncs.Execute(() => {
   // 重い計算？
   return 1
 }, result => {
   // result => 1。メインスレッド    
 });
```
`Execute`メソッドには、`Action`もしくは`Func<T>`を引数に渡し、バックグラウンドで非同期処理を実行してその結果をメインスレッドで受け取れます。
## Loggers - お手軽ファイルロガー

`Loggers`はUnityの`ILogger`を実装したロガーのファクトリです。以下のように作成することで、メタデータが付与されたフォーマットでログ出力できるロガーをすぐに作成できます。

```csharp

var logger = Loggers.New("MyClass");
logger.Log("MyMeshod", "way");
// => 2017-12-24 20:59:53+09:00 230ms/433F <L> [MyClass/MyMethod]: way
```
同様に、ファイルロガーも簡単に作成できます。ファイルへの書き込みは`Asyncs`を経由してバックグラウンドで実行され、指定インターバルごとに行われるため、アプリケーションのパフォーマンスを落とすことはありません。

```csharp
var logpath = Application.dataPath + "/logs/my.log";
// 30秒ごとにflush
var fileLogger = Loggers.NewFileLogger("tag", logpath, TimeSpan.FromSeconds(30));
fileLogger.Log("MyMethod", "way");
// ファイルに"2017-06-01 20:59:53+09:00 230ms/433F <L> [tag/MyMethod]: way"と書き込まれる
```

## Files - お手軽 & 安全なファイルIO

`Files`には、ファイルIOに関した便利なメソッドがあります。
`Files.TryWrite`は指定パスにデータを同期的に書き込みます。

```csharp

Files.TryWrite(Application.dataPath + "/save.dat", data);
```

`Asyncs`と併用することで非同期保存が可能です。

```csharp
Asyncs.Execute(() => {
	Files.TryWrite(Application.dataPath + "/save.dat", data)
}, () => {
	Debugs.Log("保存完了");
});
```
`Files.TryRead`は指定パスのファイルを同期的に読み込みます。

```csharp
var data = Files.TryRead(Application.dataPath + "/save.dat");
```

`Asyncs`と併用することで非同期読み込みができます

```csharp
var path = Application.dataPath + "/save.dat";
Asyncs.Execute(() => Files.TryRead(path), data => {
  // 読み込み完了
});
```   
FilesのIOメソッドはちょっとした工夫をしていて、書き込み時に指定パスのすでにあるファイルが消失も破損もしないようになっています。

## Crypter - お手軽暗号化
Crypterは、秘密鍵を用いた暗号化/復号化を簡単に実装できるクラスです。
このように使います。

```csharp
// クリプタを作成
var crypter = Crypter.Default(() => "secret");
// 暗号化
var encrypted = crypter.TryEncrypt(new byte[] { 0, 1, 2});
// 復号化
var decrypted = crypter.TryDecrypt(encrypted); // bytes[] { 0, 1, 2}
```
Crypterのファクトリに渡しているのは、秘密鍵のプロバイダです。暗号化/復号化を行う場合にこの鍵を利用します。これは次のような方法で実装できると思います。

- C#に直書き
- Unityのリソースファイルに書く
- サーバー経由で貰う
- iOS/AndroidネイティブライブラリにC拡張関数を書いてDLLから読み出す
- などなど…

# おわりに

明日はAdvent Calener最終日、[Yuta_Nakano0902](https://qiita.com/Yuta_Nakano0902)さんの「クリスマスに相応しい記事」の予定です。それではみなさま健やかに新年をお迎えください。