もんりぃ is undefined.

育児ネタとか、技術ネタとか。

AssemblyDefinition × AssetBundle の罠?

🌱 はじめに

📝 現象

Unity 2017.x 時代に作った AssetBundle が AssemblyDefinition 対応済の Unity 2018.1 ビルドから読み込めない。

🔍 調査

とにかく「AssemblyDefinition AssetBundle」でググる

ひたすらググる

すると、 フォーラムの記事 がヒットする。

この中で Unity の中の人の回答 に以下のような情報が。

To load scripts correctly in C#, we store assembly, namespace, and class information in the asset bundle: ...code... This means that any time you rename a class, move the class to a new namespace, move the code to a new assembly, or rename the assembly it is in, you will need to rebuild your asset bundles.

雑に訳すと「AssetBundle に Assembly, namespace, class の情報追加するようにしたから、 再構築して クレメンス」というコトらしい。

よろしい、ならば再構築だ。

🖋 前提

で、再構築の時の罠の話をする前に、キッズスターの AssetBundle 運用がどうなってるのかをザッとお伝えする必要があります。

キッズスターでは、「都度のビルド毎に生成される SingleManifest *1 をビルド毎にバージョニングして Amazon S3 にアップロードし、これを起動時にダウンロードさせる」「個別の AssetBundle については、AssetBundle ビルド時に AssetBundle のハッシュ値(AssetFileHash)をファイル名に して Amazon S3 にアップロードする」という運用をしています。

こうすることで、「アプリ側は SingleManifest のバージョンさえ間違えずにダウンロードできれば、個別の AssetBundle のバージョニングについて意識するコト無くダウンロードができる」状態が構築されています。

これは、言い換えると「AssetBundle 的に何らかの変化があった場合には、AssetBundle 本体はもちろんのこと AssetBundle の AssetFileHash も変化する ことを期待している」ということです。

さもなければ、ファイルが上書きされてしまい、「新しいビルドでは読めるが、古いビルドでは読めない」みたいなコトが起きてしまいます。

🕳 罠

で、まぁ、察しの良い読者の方はお気づきかと思いますが、今回の罠というのは「AssemblyDefinition 化したことにより追加される Assembly, namespace, class の情報は AssetBundle の AssetFileHash を変化させない 」というコトです。*2

つまり、「AssetBundle を再構築しないと AssemblyDefinition ビルドでは読めないが、再構築すると旧ビルドで読めなくなる」という 😱 な状況になるわけですね。

🏃‍♂️ 回避策

こりゃマズいというコトで回避策を id:fakestarbaby と一緒にあれやこれやと考えました。

結果出てきた案としては「何とかして AssetBundle の中身 *3 を変化させずに、新しい AssetFileHash を生成させる」というワークアラウンドでした。

最初は「ファイル名を変えて AssetBundle をビルドした後、再度ファイル名を戻してビルドし直す」という手段で行けたように見えましたが、「元 Asset が ScriptableObject の場合は、ファイル名を戻した後の AssetFileHash が元に戻ってしまう」という状況だったようです。

で、「こりゃ手詰まりか…!?」とか思って一晩寝かせたところ、翌朝に「 AssetBundle Variant を付けてビルドし、再度 Variant を外してビルドし直す 」というワークアラウンドを思いつき、試してみてもらったところ巧く行きました!

てことで、コレが現時点の答えのようです。

2018/06/21 11:34 追記:

どうやら「一度 Variant の付け外しを行えば AssetFileHash の再生成が行われる」っぽいです。付け外しの間にビルド挟まなくても良いっぽい。

2018/06/21 12:07 追記:

.metatimeCreated っていうフィールドを弄れば AssetFileHash が更新される」ことも判明しました。

アセットの内容と時刻をもとにハッシュが決まるみたいな情報を見かけたことがあるので、このフィールドがそれに該当するみたいですね。

ただ、このフィールドがどのタイミングで生成されるのか?がイマイチ分かりません…。

🤔 所感

  • AssetBundle 側の仕様バグだとは思いますが、まぁ、レアケースなんでしょーがない…のかな…?
  • 諦めなければ閃きは降ってきます。
  • なお、この時のやり取りは Slack のとある発言に対する Thread で行われていたんですが、その Reply の数をご覧いただければ大変さがご理解頂けるかと存じます。ご査収くださいませ。
    f:id:monry84:20180621112730p:plain

*1:AssetBundle 出力先ディレクトリに吐き出される AssetBundle

*2:稀に変化するモノもあったようですが、私が作業していたわけではないので、仔細は不明です…。

*3:というか、AssetBundle の内容物の情報

「Unity テスト完全に理解した #1」に登壇しました

はじめに

  • 2018/06/06 (Wed) に開催された Unity テスト完全に理解した という勉強会に登壇したので、その感想を綴ります。
  • また、内容に対する質問なども頂戴しているので、そちらに回答します。

「Unity テスト完全に理解した」とは?

  • 私を含めた有志の Unity エンジニア数名が主催し、mixi さんに会場をお借りして開催された「Unity におけるソフトウェアテストについて語る勉強会」です。
  • キッカケは @toru_inoue (a.k.a. 殺意開発駆動) さんに「こんな勉強会やりたいんだけど!」とご相談いただいたところからスタートしています。
  • その後、イベント主催にめちゃくちゃ強い @lycoris102 (a.k.a. 青木とと) くんを巻き込み、会場提供いただいた mixi にお勤めの @adarapata(a.k.a. いも) さんも巻き込んで第1回の開催に漕ぎ着けました。
  • タイトルが「つよめ」なのは、勢いで名前をつけたからに他なりませんw

セッション

スライド

speakerdeck.com

ライブ放送アーカイブ

www.youtube.com

概要

  • 「さては密結合だなオメー Clean Architecture で学ぶテストフレンドリーな疎結合設計」というタイトルで講演いたしました。
  • 「如何にしてテストし易いコードベースにするのか?」というメタなテーマで、最近布教活動中な CAFU: Clean Architecture For Unity の宣伝を織り交ぜつつ、「こういう風にするとシステムが疎結合になって、テストし易くなるよ!」というお話をしました。
    • 詳しくはスライドや録画放送をご覧くださいませ!

アンサー

  • Twitter で講演中に頂戴したご意見やご質問に回答していきます。
  • 基本的に時系列で回答していくので、読み辛いと思いますがご容赦ください。

Zenject 使わないとダメなの?

  • スライドの中で @toRisouP さんの Unity開発で使える設計の話+Zenjectの紹介 というスライドについて言及した際の疑問かな?と思います。
  • Zenject じゃなくても全く問題は無いのですが、Zenject able なシステムになっていると、テストが書きやすくなるのは事実なので、Zenject 使っているとテストが書きやすくなるというのは十分条件かな?と思います。
  • @toRisouP さんも このツイート で触れていますね。

コードの数が多くなりそうなイメージある。

  • はい。めっちゃ多くなります。
  • 一つのシーンで20個くらい .cs ファイルが必要になるとかザラです。
  • スライドの中で触れている CAFU: Clean Architecture For Unity では、コードジェネレータを実装しているので、作成時の手間はちょっと減らせているかな?とか思っています。
    • 厳密に言うと CAFU Core 本体ではなく CAFU Generator という別モジュールで提供しているのですが、 README の Installation の作法に従ってインストールして頂ければ依存モジュールとして勝手にインストールされます。

この手のアーキテクチャの出自は?

  • 自分も詳しくは無いのですが、一説に依れば SI 系の出自という説もあり、はたまた Web という説もあり、イマイチ不明です…。
  • なんとなくクライアントアプリケーション系な匂いもするのですが、どなたか詳しい方教えてくださいw
  • @z_zabaglione さんが こちらのツイート で触れているように、OS のアーキテクチャとして考えるとシックリくるモノがあるので、そっち系の出自な可能性もありますね。

ちょっとしたアプリには向いてないのでは?

  • はい。そう思います。
  • 例えば 1Week GameJam などに出す単発アプリを作る場合などは、無理に使う必要性は無いと思っています。
  • ローンチ後にも改良・改修を考えているプロダクトに適用すると良いんじゃないかなぁ?と思います。

何のゲームのオマージュ?

  • 「ぷ○ぷよ」です。
  • 「テ○リス」とか「Fl○ppy Bird」とかも例示用に考えましたが、一番好きなゲームということで採用しました。

Mock じゃなくてよくね?

  • はい。そう思います。
  • ちょっと勢いで書いてしまった部分もあったので、わざわざ Mock しなくても良い箇所はあります。

どのレイヤーに当てはめるか?が難しい…。

  • これはある程度の慣れが必要になるのは否めません。
  • 実は、テストを書くようになるとスッと理解出来るようになったりします。
  • 「ユーザ入出力に関するモノは View」「計算処理は UseCase」「データ入出力に関するモノは DataStore」と思っておくと良いかも知れません。

Translator, Repository, DataStore について

  • Repository に Translator 的な処理を噛ませるのはアリだと思います。
  • 私は、「Repository は単なるインタフェース」「Translator に変換の実ロジック」と分けたかったので、レイヤー分けしました。
    • Translator には Translate メソッド一つのみを配置して、見通しを良くしたかったという思いもあります。
  • その後のツイートで言及してくださっていますが、「DataStore が実ロジックで Repository はインタフェース」という理解で正しいです。
  • 懇親会でもちょっとお話ししました。

  • その理解で良いと思います。
  • 一つの大きい JSON をパースして、複数の Entity を含む大きい Entity のインスタンスを作る、という実装は結構やっています。
    • ScriptableObject と可換にしようとするとかなり死ねるんですが、それは別のお話。
  • Entity のリストを持つ Entity や、JSON のノードとして幾つかの種類の Entity を持つ Map (Dictionary) 的な Entity なんてのもバンバン使います。

  • これは、そうかも知れません。
  • 私は、Entity や Model の構造を変更する時に UseCase を修正したくなかったので、Translator 層に退避させた感じです。
  • 実際、CAFU を使ったとしても Translator 層ナシでも実装できます。

適用させやすいゲームとそうじゃないゲームがある?

  • RPG などの方が適用させやすいのは事実です。
    • というか、 適用させる価値が高い と言い換えられます。
  • ですが、本質的にはどんなゲームにも適用できるかな?と思っています。
  • アクションゲームで言うと、複雑なアクションの結果生じた「データの計算」やその「データの入出力」などの ルールを定義 しているに過ぎないため、見た目やアクションやエフェクトの複雑さとは切り離すコトが可能かなぁ?とは思っています。
    • やったことないので何とも言えませんがw

もはや Unity 関係なくね?

  • はい。その通りです。
  • というか、そこを目指して開発しました。
  • 元々普遍的な概念なので、「部分最適することで Unity に当てはめた」という感じですね。

Entity…?

  • 懇親会でも何名かの方から聞かれたのですが、DDD の文脈に於ける Entity とは意味合いが違います。
  • 元ネタのブログ では「An entity can be an object with methods, or it can be a set of data structures and functions.」とあるので、私は外部データ定義レイヤーとしてネーミングしました。

Repository と DataStore の分離

  • 私は必要に応じて Repository レイヤーのサブクラス的な扱いで DataStoreResolver 的なモノを用意し、「利用する DataStore を選択するためのサブレイヤー」を追加定義することがあります。
    • DataStoreResolver 自体も疎結合にする必要があるので、結構面倒ですがw
  • この辺は、まだ画一的な方法が見出せておらず、プロジェクト毎に自由にやらせてしまっているのが実情です。
  • 良案募集中です。

適用するの難しそう…。初速鈍そう…。

  • はい。容易ではありません。
  • 正直、初速は良くありません。
  • が、慣れると、めちゃめちゃ速いです。
  • 1本小さめのアプリ書き上げるくらいまで使うと、その後の開発は相当楽になります。
    • 元々弊社プロダクトは、小さめのアプリを大量に作って一つのアプリにする必要があるという特性があるので、その辺をかなり意識して作りました。

密結合なアセットどーすんの?

  • 私はロジックにガッツリ介入してくるようなアセットは殆ど使っていません。
  • Unity の文脈で言うところの Component に該当するアセット(View レイヤー)はバンバン使っちゃって良いと思いますが、 View 以降のレイヤーに介入してくるアセットは、相当厳選して入れています。

コードジェネレータないの?

  • あります
  • CAFU Core を yarn でインストールすれば依存として勝手にインストールされます。
    • 2018/06/07 現在、Unity 2018.1 でちょっと問題があるので修正中です。

CAFU のテストなくね?

  • はい。書きます。
  • ドキュメントやサンプルとともに喫緊の課題として積んでおります…orz

所感

  • mixi さんのイベントスペースがとても良く、感動しきりでした。
    • 最大90名程度の収容力
    • 2面スクリーン
    • ワイヤレス映像出力
    • 生放送・録画機材
    • おしゃれ感
    • etc...
  • イベント自体は、公開直後に満席になり、増席してもなお人が増え続けて、ピーク時には定員90名のところに158名もの方にご応募いただくという、「このテストケースは書けなかったわーw」という状況にまでなりました。
  • 流石に90人(スタッフ入れたら100人超えていたかも?)の前でフルセッション話すのは(多分)はじめてだったので、登壇直前までガッチガチに緊張していましたが、会場の空気が精神的な意味で暖かく、落ち着いて話すことができました。
    • スライドが100Pを超えていたので、早口にはなっていたと思いますがw
  • 結果、ほとんど無言ドタキャンもなく、セッションは勿論のこと懇親会も大いに盛り上がり、「大成功」と言える勉強会になったと思います!
  • メインで動いてくれた青木ととくんや登壇者の皆さんや現場で設営・撤営・録画など多大なご協力をいただいた mixi 社の方々に、この場を借りて改めて深く御礼申し上げます!ありがとうございました!!!

Utf8Json を macOS で動作させるまでの記録

前置き

  • Utf8Json とは、私が尊敬して止まない @neuecc さん *1 が作った C# で動作する高速な JSONリアライザのコトです。
  • 私の頭脳で理解出来た範囲で仕組みを掻い摘まむと、以下のような特徴があります。
    • 専用のコードジェネレータが、任意のディレクトリ以下にあるクラスのシリアライズ・デシリアライズのルールを C# のコードとして生成
    • ランタイムで用いられる Utf8Json.JsonSerializer.Serialize(), Utf8Json.JsonSerializer.Deserialize<T>() メソッドは、そのルールに基づいてシリアライズ・デシリアライズを行う
    • Unity でも動く!IL2CPP 環境でも動く!
      • JsonUtility でええやん」という声が聞こえた気がしますが、アイツは Dictionary のシリアライズが出来なかったり、ネストした ScriptableObject のシリアライズが出来なかったりと、色々と制約が大きいのです。
  • 何で速いのか?とかは README を読むと良いんじゃないかな?
  • で、この Utf8Json のルール定義コードを生成するジェネレータが .NET Core 2.1 な macOS 上で動作しない *2 コトが判明したので、その辺どうにかするために格闘した記録をここに綴ります。

.NET Core is 何?

  • .NET のオープンソース実装の一つです。
  • .NET Standard を使用した .NET 実装であり、Windows, macOS, Linux の何れの環境でも動作するコンソールアプリケーションを作れます。
  • 詳しいことは この記事 を参照すると良いんじゃないでしょうか。
  • まぁ、凄く雑に言えば macOS でも動く .NET です。
  • 私は、.NET 界隈に明るくないので、ググって調べた範囲だとこんな感じっぽいです。

なんで動作しないの?

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'System.Runtime.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
  • README に従って releases ページに添付してある Utf8Json.UniversalCodeGenerator というコードジェネレータのコマンドを叩くと、上記のようなエラーを吐いて落ちてしまいます。
    • dotnet Utf8Json.UniversalCodeGenerator.dll とかやっても同じでした。
    • Utf8Json.UniversalCodeGenerator.runtimeconfig.json の書き換えも試しましたがダメでした。
  • 原因は深追いしてないので不明です。
    • まぁ、エラーを見るに System.Runtime.Extensions.dll 的なモノを参照出来てないんだと思います。
    • 同一ディレクトリに存在してるんですが、それでも読めないのが謎です。.NET のバージョン問題とか?

どうやって解消したの?

  • ローカルの環境でビルドし直しました。
  • 幸いにも、コードジェネレータのソースコードGitHub に上がっているので、そのプロジェクトを JetBrains Rider 上でビルドしました。
  • 手順としては以下の通り。
    1. GitHub から clone したソースの中にあるソリューションファイル Utf8Json.sln を Rider で開く
    2. src 以下にある唯一エラーが出ていない Utf8Json.UniversalCodeGenerator というプロジェクトを選択
    3. メニューなりコンテキストメニューなりからビルド
      f:id:monry84:20180531014541p:plain
    4. src/Utf8Json.UniversalCodeGenerator/bin/Debug/netcoreapp2.0 以下に Utf8Json.UniversalCodeGenerator.dll が出来る
  • このできあがった dll を dotnet コマンド経由で実行したら以下のようにちゃんとコマンドヘルプが出るようになりました!
$ dotnet src/Utf8Json.UniversalCodeGenerator/bin/Debug/netcoreapp2.0/Utf8Json.UniversalCodeGenerator.dll
arguments help:
  -i, --inputFiles=VALUE     [optional]Input path of cs files(',' separated)
  -d, --inputDirs=VALUE      [optional]Input path of dirs(',' separated)
  -o, --output=VALUE         [required]Output file path
  -f, --allowInternal        [optional, default=false]Allow generate internal(
                               friend)
  -c, --conditionalsymbol=VALUE
                             [optional, default=empty]conditional compiler
                               symbol
  -r, --resolvername=VALUE   [optional, default=GeneratedResolver]Set resolver
                               name
  -n, --namespace=VALUE      [optional, default=MessagePack]Set namespace root
                               name

それ欲しいんだけど!

  • 元の Utf8Json が MIT ライセンスなんで多分大丈夫だとは思いますが、ビルド成果物を再配布して良いモノか分からんかったので、一先ず公開とかはしないでおきます。
    • 要望が多ければ @neuecc さんに許可とって、Fork したリポジトリの releases ページにでも添付するかも。

所感

  • 触ったコトない環境でビルドやら何やらやるのは結構骨が折れますね…。
  • アーキテクチャとかの概念がある程度分かっていないとエラーの意味が分からないし、分かっても対処の仕方が思いつかないなぁとか感じました。
  • まぁ、とりあえずやりたいことは達成できたので満足!

*1:@neuecc さんは、かの有名な UniRx の作者さんです。

*2:ちなみに、同じく @neuecc さんが作った MessagePack for C#ZeroFormatter なんかも同じくシリアライザなんですが、こちらはほぼ確実に macOS では動かないっぽい(未検証だけど)ので完全に見送っています。

しがないラジオ Meetup vol.1 に参加してきました

はじめに

  • 2018/05/23 (Wed) 夜に開催された しがないラジオ Meetup vol.1 に参加してきました。
  • その感想とかを(雑に)綴ります。
  • (気付けば1ヶ月ブログ書いてなかった…。)

しがないラジオ とは?

  • SIer の SE から Web 系に転職したんだが楽くて仕方がないラジオ」略して「しがないラジオ」です。
  • SIer から Web 系企業に転職したずっきーさん (@zuckey) とがみさん (@gami) がパーソナリティを務める Podcast で、お二人のみでトークする回もあれば、同じような環境のゲストを迎えてトークする回もあります。
  • ゲストは「手を挙げれば出演できる」という良い意味での緩さを有しています。
    • 「出られるラジオ」の二つ名を冠しているとすら言われるとか…?
  • 私はてぃーびーさん (@tbpgr) にご紹介いただいて、 sp.10 (前編) (後編) に出演させていただいています。
    • 良ければ聴いてみてください!

しがないラジオ Meetupとは?

  • しがないラジオのパーソナリティのお二人と、ゲスト出演した人達と、リスナーの人達が、一堂に会して LT したりお酒飲んだりお菓子食べたり語らったりするイベントです。
    • サポーターズさんのセミナールームに40人くらいの大人が集まってワイワイやっている画は壮観でした!
  • 「やるぞやるぞ」という気配は(昨年末くらいから?)醸し出しており、ついに開催!となったので、受付開始前からワクワクしながらポーリングしていました。

感想とか

  • 何人かの知り合いも来ており、その中の一人に至っては全然別の経路でしがないラジオに出会っており、裾野の広さすげー!って感じに感動しておりました!
  • パーソナリティ・ゲスト・リスナーの何れの皆さんも良い人ばかりで、懇親会で「どうも、もんりぃって言います!」と話に入るボクを受け入れてくれて、ぼっちにならずに済みましたw
  • 諸事情により全ての LT は聞けなかったんですが、少なくとも私が聞いた LT は全て盛り上がっており、「みんなトークスキル高いなぁ…。」とも感じました。
    • 再来週にフルセッションが2件入っているので身が引き締まりました。
  • この先控えている大きめのアウトプットが終わったら二回目のゲスト出演を目指して動きたいなぁ、とか思いました。

技術書典4 に参加しました。

はじめに

2018/04/22 (Sun) に開催された技術書典4に、サークル側として参加してきました。

そのことについて綴ります。

2018.04.25 追記

BOOTH での販売を開始しました!

こちら よりお買い求めいただけます!

技術書典 is 何?

新しい技術に出会えるお祭りです。 技術書典は、いろんな技術の普及を手伝いたいとの想いではじまりました。 技術書を中心として出展者はノウハウを詰め込み、来場者はこの場にしかないおもしろい技術書をさがし求める、技術に関わる人のための場として『技術書典』を開催します。

(技術書典公式サイトより引用)

ということで「ITや機械工作とその周辺領域について書いた本」を展示・販売・購入するためのイベントです。

サークル?何出したの?

f:id:monry84:20180423184928p:plain

日本 Android の会 Unity 部」というサークルとして「 UNIBOOK9 」という書籍の第一章「Goodbye f○cking code, Hello Clean Architecture. / CAFU のおはなし」という章を担当し、技術書典4の当日はサークルブースで id:takuyaiwamoto と一緒に売り子を担当しました。

UNIBOOK は、「日本 Android の会 Unity 部」に所属する*1有志で記事を寄稿し書籍化される同人誌です。

過去にも UNIBOOK4 と UNIBOOK5 に寄稿したことがあるので、今回で3回目の UNIBOOK 参戦となります。

技術書典に参加するのは*2初めてだったので、空気感とかを把握しきっていない状態で臨んだのですが、思っていた以上にアツいイベントで、「うおー!楽しいっ!!!」って感じにテンション上がりまくってましたw

所感

様々な「技術」に対してアツい想いを持った人達が一堂に会して、書籍の売買を通してふれあうというイベントはなかなか経験できるモノではないので、とても良い刺激になりました。

また、以前に比べて「技術書を書く」というコトに対するハードルが低くなっているなぁとも感じ、自分自身は勿論のこと周りの技術者でアウトプットの意欲が高い人はバンバン書いてみたら良いんじゃないかな?と思いました。

UNIBOOK は次回で10巻になるので、運営メンバー的にも「豪華にしたいよねー」という想いがあったりするので、ちょっとでも興味がある人は名乗りを上げてもらえると嬉しいです!

*1:してなくても良いかも?

*2:一般側としてもサークル側としても

開発合宿

はじめに

私が所属する株式会社キッズスターのエンジニアチームでは、隔週くらいのペースで「開発合宿」なる勉強会を開催しています。

今のところ内輪での開催で、社員と業務委託のパートナーさんとで開催しているイベントなのですが、今日はそのコトについて綴ります。

なにやるの?

主に Unity に関する技術的なトピックについて、みっちり3時間とか*1掛けて勉強します。宿泊するわけではありません。

きっかけ

元々週一回開催しているエンジニアチームの定例ミーティング内で「Unity に関する技術的な話」や「Docker の概要について」など、トピックを絞った簡易勉強会的なモノを突発開催したりしていました。

ただ、最近は業務委託のパートナーさんも増えてきて、パートナーさんは開発定例に出ないこともあるので、「勿体ないよね…。」「いっそ、しっかり時間取って開催しよう!」という流れになったのが経緯です。

どんな流れ?

普段の流れとしては、以下のような感じです。

  1. エンジニアチーム定例ミーティングで「これやりたいよね」というトピックを決定
  2. 会場を押さえる
    • id:lycoris102 が会場選びや予約をやってくれています。ありがとう!!!
  3. 開催を Slack とかで連絡する
  4. 会場に集まる
  5. 私がモブプログラミングする

もうちょい詳しく

扱うトピックとしては、株式会社キッズスターのプロダクト開発で用いる技術について取り扱うことを前提にしています。*2

例えば、以下のようなモノが挙げられます。

  • Clean Architecture の考え方を共有
  • UniRx についてちょっと詳しく解説
  • umm についてちょっと解説
  • 既存のプロダクトのコードをリファクタリング
    • 冒頭の写真はその回の写真です。
    • 私含めて7人のオッサンがマンションの一室で同じ方向向いて座っています。

これらのネタを、時にはコードを読みながら、時にはコードを書きながら、時にはホワイトボードに図を書きながら、延々語ります。

また、語っている最中も参加メンバーから「え?これってどういうこと?」「今の操作どうやったの?」「こういう考え方もあると思うんだけど。」とざっくばらんに発言が飛び交う感じに盛り上がっています。

で、どうよ?

私は前で喋る側なので、開催の成果を直接的に感じることはできませんが、チーム技術力の向上には寄与できているんだろうなぁと思っています。

が、メイントピックを喋っている中で「あ、そいえば、こんな機能があってね…?」みたいな枝葉の話をすると、「うおー!知らなかった!すげー便利じゃん!」みたいな流れになるコトがあるので、そういった点でも開催の意義はあるんだろうなぁとか感じています。

逆に喋る側の立場として見ると、事前調査をしたり喋る前や喋っている最中にコードを深く読むことになるので、「知っているつもりで知らなかったこと」や「キャッチアップできていなかった新機能」などの学びがあるので、とても有意義なモノだと考えています。

未来のおはなし

この先取り扱うテーマとしては、個人的に以下のようなモノをやりたいと思っています。

  • umm について深掘り
  • Clean Architecture についてもっと研究
  • テスト
    • Edit Mode, Play Mode
    • Testing Framework
  • Zenject
    • 採用したいと思っているので
  • Unity の新機能
    • Timeline を深掘り
    • ECS: Entity Component System
    • Assembly Definition
    • PlayerLoop
  • シェーダ*3
  • エディタ拡張
  • AssetBundle
  • 実機ビルド
    • Xcode 関連
    • Jenkins おじさん

また、年内は厳しいと思いますが、将来的にはもうちょい規模を拡げるのもアリかなぁ?とか妄想しています。あくまで個人的な妄想です。

まとめ

「社内勉強会楽しいよ!」っておはなしでした。

「Clean Architecture とか興味あるんですけど!」「umm って何…!?」って人は Twitter とか Facebook とか口頭とか何でも良いのでお声かけください〜!

あ、それと、2018年4月現在、株式会社キッズスターでは、一緒に「なりきり!!ごっこランド」のパビリオン*4をつくるデザイナーさんアニメーターさんプロデューサーさんを募集しております!興味ある方は Wantedly からでも私個人でも良いのでご連絡くださいませ!

*1:時間は不定

*2:必須ではありませんが、今の所そんな感じ。

*3:キッズスターのアプリで使うシーンが殆ど無さそうなんだよなぁ…。

*4:アプリ内のミニゲームコンテンツのこと。

Unity で Android 6.0 の Runtime Permission に対応してみて得られた知見

はじめに

現在、「端末のマイクで声を録音する」という要件を含んだパビリオンを開発しています。 んで、対応するためには Runtime Permission へのサポートを行う必要があるわけです。 その辺対応している時に色々調べたので、その知見を雑に纏めます。

ハマりポイント

  • iOS と足並みを揃える
  • Unity のお節介
  • AndroidManifest.xml マージ

iOS と足並みを揃える

iOSAndroid とで Runtime Permission の実装方法は異なります。*1 大きな違いとして Android では Application.RequestUserAuthorization が使えない(っぽい) という点が挙げられます。 このため、Android 用に専用処理を書いてあげる必要があります。

細かい説明は他のブログ記事に譲りますが、 UnityEngine.AndroidJavaClass とかを使って android.support.v4.content.ContextCompat.checkSelfPermission() とか android.support.v4.app.ActivityCompat.requestPermissions とかを呼んであげる感じですね。 詳細なコードは、以下のリポジトリが参考になるんじゃないですかね?(宣伝)

Android での Runtime Permission

github.com

Unity のお節介

最新の Unity *2 は、プロジェクト内で UnityEngine.Microphone クラスを使用しており、かつ Target SDK Version が API Level 23 (Android 6.0 / Marshmallow) 以上の場合に、「起動時に Runtime Permission ダイアログを出す」という心折親切設計になっております。 このため、「いや、ちゃうねん。自分で制御するから、そういうのええねん!」という人にとっては、問題になります。 で、これを回避するための手段もちゃんと用意されています。

ザックリ要約すれば「<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />AndroidManifest.xml に追記」すれば OK です。簡単ですね!

AndroidManifest.xml のマージ

で、じゃあ AndroidManifest.xml に書こうかな、と思った時に、ぶつかるのが「 AndroidManifest.xml のマージ」に関する問題です。 言い換えると、Unity で Android 向けに APK をビルドすると、ヨシナに AndroidManifest.xml のマージ処理を走らせてくれるのですが、この辺のマージルールについてしっかり理解して上記の unityplayer.SkipPermissionsDialog を追記してあげないといけない、ってコトですね。 Android Developer のドキュメント にしっかり纏められているので、詳細はこちらを参照してください。

やり方としては、「小さい Library Project として AndroidManifest.xml マージ用の設定を配置する」と楽なんじゃないかと。 詳細な設定としては、以下のリポジトリが参考になるんじゃないですかね?(宣伝)(しつこい)

AndroidManifest.xml

github.com

project.properties

github.com

まとめ

実機のアレコレは、色々とハマリどころが多いので大変ですね。

*1:そもそも iOS では Runtime Permission って呼ばないけど。

*2:いつから対応されたのかは調べてない。