ごあいさつ
こんにちは。プログラマの@keroxpです。ちょうどUnity歴は1年ほどになります。
今年は新卒で入ったLINEという会社を辞めてエモを追求するために1人で「黒羽のアリカ」という2Dスマホゲームを作りました。
今はARKitとiPhoneXの機能を使った「黒羽のアリカAR」という3Dアプリを作ったりしています。
3Dに苦戦中でまだこんな感じで途中です(ホントはこれの完成版を記事にしたかった…😫)
#黒羽のアリカ with #Unityちゃん 視線の動きと、開閉可能な翼のアニメーション。 pic.twitter.com/ZPd9InPKVv
— keroxp@がんばらない (@keroxp) 2017年12月10日
アリカさんの名前だけでも覚えて帰ってくださいw
それでは本題に入ります。
結論
年末年始でお忙しい方も多いでしょうから、短い結論から。
- Unityアプリを開発する際に標準的に使う依存性のないライブラリを開発した
- MITライセンス/Githubで公開中 https://github.com/keroxp/UniCommon
- インストールは
npm i unicommon
でおk - ドキュメントは https://scrapbox.io/keroxp-blog/UniCommonを参照
- プルリクエスト大歓迎!
Unityでのコードの再利用について
Unityを始めてからいくつかのプロジェクトを作成してアプリを作成しているうちに、同じようなコードを度々書いていることに気が付きました。
流石に全部一から書き直しているわけではないですが、そのたびにファイルを気合コピペしたり、コピペだとコンパイルが通らないところを細かく修正したり…とだんだん面倒になってきました。
そこで、自分なりのまとまりがとれた「黒羽のアリカ」の開発で使用したコードの中からゲームに直接関係のないコードを取り出して別プロジェクト化ました。
Unityは2017.2からUnityPackageManagerというパッケージ管理機能が追加されるとアナウンスされているのですが、実際どういうものなのか2017.3の現在もよく分かっていないので、Unityライブラリを配布する方法として使い慣れたnpm
を選択しました。将来的にUPM(?)が動き出したらそちらに対応します。
参考:Unityプロジェクトの自作パッケージ依存性管理をnpmで行う
インストール方法
MacならUnityプロジェクトルートで以下のコマンドを実行すればインストール完了です。
npm i unicommon --save
mkdir -p Assets/Plugins/Packages
$(npm bin)/unity3d--sync
ドキュメント目次
自分のScrapboxにドキュメントを作成してあります。全てではありませんが逐次更新予定です。
- UniCommon機能紹介 - Component
- UniCommon機能紹介 - Log
- UniCommon機能解説 - Files
- UniCommon機能解説 - Asyncs
- UniCommon機能解説 - KVS
- UniCommon機能解説 - Crypt
- UniCommon機能解説 - Enumerators
詳細な解説は機能目次から確認していただくとして、UniCommonの中から特に便利な機能を4つ紹介します。
便利な機能4選
Asyncs - お手軽非同期処理
Unityのなかで非同期処理を簡単に実行したいと思ったことはありませんか?
Asyncsを使えば1行で簡単に非同期処理が実装できます。
// 返り値なし
Asyncs.Execute(() => {
// ファイルIOとかの重い処理
}, () => {
// 完了。メインスレッドで受け取れる。
});
// 返り値あり
Asyncs.Execute(() => {
// 重い計算?
return 1
}, result => {
// result => 1。メインスレッド
});
Execute
メソッドには、Action
もしくはFunc<T>
を引数に渡し、バックグラウンドで非同期処理を実行してその結果をメインスレッドで受け取れます。
Loggers - お手軽ファイルロガー
Loggers
はUnityのILogger
を実装したロガーのファクトリです。以下のように作成することで、メタデータが付与されたフォーマットでログ出力できるロガーをすぐに作成できます。
var logger = Loggers.New("MyClass");
logger.Log("MyMeshod", "way");
// => 2017-12-24 20:59:53+09:00 230ms/433F <L> [MyClass/MyMethod]: way
同様に、ファイルロガーも簡単に作成できます。ファイルへの書き込みはAsyncs
を経由してバックグラウンドで実行され、指定インターバルごとに行われるため、アプリケーションのパフォーマンスを落とすことはありません。
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
は指定パスにデータを同期的に書き込みます。
Files.TryWrite(Application.dataPath + "/save.dat", data);
Asyncs
と併用することで非同期保存が可能です。
Asyncs.Execute(() => {
Files.TryWrite(Application.dataPath + "/save.dat", data)
}, () => {
Debugs.Log("保存完了");
});
Files.TryRead
は指定パスのファイルを同期的に読み込みます。
var data = Files.TryRead(Application.dataPath + "/save.dat");
Asyncs
と併用することで非同期読み込みができます
var path = Application.dataPath + "/save.dat";
Asyncs.Execute(() => Files.TryRead(path), data => {
// 読み込み完了
});
FilesのIOメソッドはちょっとした工夫をしていて、書き込み時に指定パスのすでにあるファイルが消失も破損もしないようになっています。
Crypter - お手軽暗号化
Crypterは、秘密鍵を用いた暗号化/復号化を簡単に実装できるクラスです。
このように使います。
// クリプタを作成
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さんの「クリスマスに相応しい記事」の予定です。それではみなさま健やかに新年をお迎えください。