やらなイカ?

たぶん、iOS/Androidアプリの開発・テスト関係。

UWA GOT v2.0.2でAndroidのIL2CPP・ARM64に対応された模様

Unity向けプロファイリングツールであるUWA GOTのv2.0.2がリリースされていました*1。 追加機能として書かれているのはAndroidおよびWindowsプラットフォームでのIL2CPPビルドとAndroidプラットフォームでのARM64対応ですが、細かい使い勝手の向上も入っていたので、あわせて紹介します。

UWA GOTの導入については、過去記事を参照してください。

www.nowsprinting.com

www.nowsprinting.com

AndroidのIL2CPP・ARM64に対応

これまで、AndroidプラットフォームでUWA GOTを有効にするには、スクリプティングバックエンドにMonoを選択する必要がありました。 v2.0.2からは、IL2CPPを選択してビルドしてもUWA GOTが有効になります。また、ターゲットアーキテクチャにARM64を選択しても同様に有効になります。

ただし、IL2CPPビルドではプロファイリング項目の"Mono"テストモードで採取できません。 Monoテストモードでは、ヒープを多く使用しているメソッドやメモリリークの疑いのある関数を探すことができます。こちらを利用したい場合には、スクリプティングバックエンドをMonoに変更してビルドする必要があります。

複数プラットフォームの切り替えが楽になった

v2.0.1までは、以下の理由からプラットフォーム切り替えごとにUWA GOTのSDKをプロジェクトから削除してインポートしなおすことが必要でした。

  • 最初のSceneに配置するprefabのファイルがプラットフォームによって異なる
  • dllの中に同名のシンボルが存在する

これがv2.0.2では解消し、あらかじめ複数のプラットフォーム向けSDKをインポートしておいて、以降は普段通りSwitch Platformで切り替えることができます。

スクリーンショットのアップロードを抑止できるようになった

プロファイリングに必要な各種データとともにスクリーンショットを確認できるのはUWA GOTの良いところなのですが、IPモノを扱っている場合は逆に使いにくいという話も聞きます。

v2.0.2では、採取した計測データをオンラインサービスにアップロードするタイミングで、これを抑止する選択肢が追加されました。

下図は、AndroidのUWA GOT Appで計測データをアップロードする画面です。「スクリーンショットをGOT Onlineにアップロードします」のチェックをoffにすることで、オンラインサービスにはスクリーンショットなしのデータが送られます*2

f:id:nowsprinting:20200221092627p:plain

なお、このチェックボックスが機能するのはオンライン向けのアップロードのみであり、Unityエディタ上で動作するローカルサーバへのアップロードは強制的にスクリーンショットありで送られます。

ローカルサーバに送られた計測データは、そこからさらにオンラインにアップロードすることができます。このとき、下図のようにスクリーンショットの送信有無を指定できます*3

f:id:nowsprinting:20200221094228p:plain

まとめ

今回のアップデートでかなり使い勝手が改善された感じです。日本でももっと流行るといいなと思っています。

*1:日付は2019/12/27。なんのアナウンスもなかったので気づきませんでした

*2:ただし、パケットキャプチャして確認したわけではないので保証の限りではありません

*3:これもパケットキャプチャして確認したわけではありません

JetBrains ReSharper Command Line Tools 2019.3でコードインスペクションを実行する

JetBrains製のC# IDEであるRiderにあるコードインスペクション機能を、そのままコマンドラインで実行できるツールがReSharper Command Line Toolsとして提供されています。 ReSharper Command Line Toolsは、これまでWindows版しかサポートされていませんでしたが、2019.3からはmacOS及びLinuxでも動作するようになりました。

www.jetbrains.com

ReSharper Command Line Toolsには、コードインスペクションツールであるInspectCodeのほかにも、重複コードを検出するdupFinder、コードクリーンナップを行なうCleanupCodeが含まれています。 今回はInspectCodeのみ紹介します。

ReSharper Command Line Toolsのインストール

ReSharper Command Line Toolsは、上記サイトからプラットフォームを選んでダウンロードできます。無料で、ライセンスキーも不要です。

ダウンロードしたzipファイルは、任意のディレクトリに展開するだけでokです。ターミナルで直接コマンド実行するのであればPATHを通しておくのも良いでしょう*1

ツールの実行にUnityエディタは必要ありませんが、ソリューションファイル (.sln) およびプロジェクトファイル (.csproj) が必要です。CIサーバで実行するときにはあらかじめUnityエディタで生成しておく必要があります*2

InspectCodeの実行

InspectCodeは、以下のように実行できます。Windowsの場合、inspectcode.shinspectcode.exeに置き換えてください。

$ inspectcode.sh \
    $(RESHARPER_TARGET) \
    --output=$(LOG_DIR)/inspect.xml \
    --format=xml

$(RESHARPER_TARGET)には、ソリューションファイル (.sln) のパスを指定します。

出力されるxmlファイルは、例えばJenkinsのPMD Pluginなどで表示できます。また引数に--format=htmlと指定することでhtml形式でも出力できます。

インスペクション内容の設定

InspectCodeがインスペクションしてくれる項目およびデフォルト設定は、下記ページにまとめられています。

Code Inspections in C# - Help | JetBrains Rider

設定をプロジェクトに合わせてカスタマイズするには、IDE(RiderおよびReSharper)のPreferencesの設定内容をファイル出力し、プロジェクトのルートに置くか、--profile引数でパスを渡します。

ファイル出力には2種類の方法があります。

設定をteam-sharedとして保存する

Preferencesを変更するとき、"Save"ボタンではなく、その横のプルダウンで"Solution team-shared"を選択します。

f:id:nowsprinting:20200114035826p:plain

すると、プロジェクトのルートに "プロジェクト名.sln.DotSettings" として保存されます。このファイルをリポジトリに追加すれば、CIサーバでも同じ設定でインスペクションを実行できます。

コンピュータの設定をエクスポートする

すでに設定変更を"Save"ボタンで保存していた場合、それはプロジェクトでなくコンピュータ単位の設定ファイルに保存されています。これをエクスポートし、team-shared設定ファイルとして利用できます。

コンピュータ単位の設定をエクスポートするには、Preferencesウィンドウ左下の"Manage Layers"ボタンでPreferences Layersウィンドウを開きます。

f:id:nowsprinting:20200114035841p:plain

"This computer"行を選択し、ツールバーにある"Export to File"アイコンをクリック、Export To Fileウィンドウを開きます。

f:id:nowsprinting:20200114035847p:plain

ここでエクスポートする設定を選択できます。今回はコードインスペクション向けなので"CodeInspection"だけ選択していますが、他の設定もチームで共有したい場合はここで選択し、"OK"ボタンをクリックします。

続いてファイル指定ダイアログが表示されますので、プロジェクトのルートに "プロジェクト名.sln.DotSettings" として保存します。

プラグインの追加

InspectCodeには、.nupkg形式のプラグインを追加することができます。追加は、.nupkgファイルをReSharper Command Line Toolsを展開したディレクトリに入れるだけで完了します。

例えば、先日の記事で紹介した、コードの複雑度を測るプラグインも公開されています*3

コグニティブ複雑度

plugins.jetbrains.com

サイクロマティック複雑度

こちらはReSharper 2019.3.1で正しく動作しないようです。特にエラーも吐かれていないので設定まわりだと思うのですが、詳細未確認。

plugins.jetbrains.com

まとめ

インスペクションツールの実行はCIに頼るのでなく、IDEに備わっていることで問題の作り込みを早期に防ぐことができます。 その点、RiderやReSharperを使い、かつ警告にきちんと対処していれば、内部品質の高い状態を維持できるはずです。

しかしながら、すでにプロジェクトの内部品質が低くなっている状態から改善していく場合など、CIでメトリクスを採取して変化を監視するのは有効です。ぜひ導入を検討してみてください。

なお、ReSharper Command Line Toolsのマルチプラットフォーム対応については、昨年9月のJetBrains .NET Meetup TokyoおよびCEDEC 2019のJetBrainsブースで「2020.x以降になるだろう」と伺っていたのですが、2019.3に前倒されました。たいへんありがたい。

関連記事

www.nowsprinting.com

関連書籍

*1:CIサーバで実行することになりますので、PATHには頼らずにMakefile等にパス込みで書くことをおすすめします

*2:通常、.gitignoreでトラッキング対象外にしているはずなので

*3:Rider向けではなく、ReSharper向けのプラグインである必要があります

JetBrains Riderでコードの複雑度を計測する

JetBrains製のC# IDEであるRiderには、様々なプラグインが提供されています。 その中から、コードの複雑度を計測するプラグインを2つ紹介します。

www.jetbrains.com

サイクロマティック複雑度

サイクロマティック複雑度(cyclomatic complexity)は循環的複雑度とも呼ばれ、コードの複雑さを測る指標としてよく使われます。 メソッド単位に分岐によるパスの最大数を算出した数値で、一般に、32以上でバグ混入率が高い、50以上でテスト困難と言われています。

循環的複雑度 - Wikipedia

これをRiderのインスペクションに組み込むプラグインがCyclomaticComplexityです。

plugins.jetbrains.com

CyclomaticComplexityプラグインは、一般のプラグインと同様、Preferences... > Plugins からインストール・有効化できます。 有効化すると、エディタのメソッド定義の上にサイクロマティック複雑度が表示されるようになります。

f:id:nowsprinting:20200112202350p:plain

上図では、サイクロマティック複雑度が29、Wariningとなるしきい値20(デフォルト値)に対して145%であると表示されています。

しきい値は、Preferences > Languages & Frameworks > Cyclomatic Complexity で変更できます。 既存プロジェクトで数値の高いメソッドが多い場合は、しきい値を緩めの値にして目立つものから少しづつリファクタリングを進めていくことをおすすめします。

f:id:nowsprinting:20200112202402p:plain

コグニティブ複雑度

コグニティブ複雑度(cognitive complexity)とは、2016年からSonarSource社*1が提唱している比較的新しい複雑度の指標です。循環的複雑度にならって日本語化するのであれば「認知的複雑度」でしょうか。

Cognitive Complexity - A new way of measuring understandability

SonarSource社は、サイクロマティック複雑度では保守性を正しく数値化できておらず、その点を改善したものがコグニティブ複雑度であると書いています。

例えば、サイクロマティック複雑度ではネストしたループとswitch-caseは同じスコアになりますが、後者のほうが理解しやすいコードのはずです。 また、異常系の処理をif文で深くネストした中に書くよりも、メソッドの先頭でエラーチェックしてreturnしてしまうほうが読みやすくなります。

そのため、分岐ではなく処理の流れを阻害する個所を加点することで保守性・可読性の評価につなげようというものがコグニティブ複雑度です。

このコグニティブ複雑度をRiderのインスペクションに組み込むプラグインがCognitiveComplexityです。

plugins.jetbrains.com

CognitiveComplexityプラグインは、一般のプラグインと同様、Preferences... > Plugins からインストール・有効化できます。 有効化すると、エディタのメソッド定義の上にコグニティブ複雑度が表示されるようになります。

f:id:nowsprinting:20200112202240p:plain

上図では、コグニティブ複雑度が23、Wariningとなるしきい値10(デフォルト値)に対して230%であると表示されています。またクリックすることでコード内の加点された個所(上図ではif文の横にある"+1")を表示できます。

しきい値は、Preferences > Languages & Frameworks > Cognitive Complexity で変更できます。 既存プロジェクトで数値の高いメソッドが多い場合は、しきい値を緩めの値にして少しづつリファクタリングを進めていくことをおすすめします。

f:id:nowsprinting:20200112202303p:plain

プロジェクト単位のインスペクション実行

いずれのプラグインもRiderのインスペクション機能に組み込まれていますので、Code > Inspect Code... でスコープを指定して実行できます。

f:id:nowsprinting:20200112214547p:plain:w300

実行結果は"Inspection Results"ウィンドウに表示されます。

f:id:nowsprinting:20200112202335p:plain

上図のように、WARNING > Potential Code Quality Issues の下に、サイクロマティック複雑度とコグニティブ複雑度それぞれ別に表示されます。

  • Element exceeds cyclomatic complexity
  • Element exceeds Cognitive Complexity threshold

なお、両方のしきい値を超えているメソッドは、コグニティブ複雑度にのみ表示されます。

まとめ

同じ目的を持つ2つのプラグインを紹介しましたが、いくつかのプロジェクトで見比べた感じ、コグニティブ複雑度のみ適用しておけばよさそうです。

複雑度の高いメソッドは、条件の組み合わせも多くなりテストすることが難しく、バグも作り込まれやすくなります。 プラグインを入れて数値を気にすることで、適切にメソッドを分割して保守性の高い状態をキープできるようになるでしょう。

なお、CyclomaticComplexityプラグインの存在はUnityゲーム開発者ギルドのSlackで知りました。色々と役立つ情報を交換ができるコミュニティですので、Unityでゲームを開発している方は入ってみてはいかがでしょうか。

scrapbox.io

関連記事

www.nowsprinting.com

www.nowsprinting.com

関連書籍

IntelliJ IDEA パーフェクトガイド

IntelliJ IDEA パーフェクトガイド

仮面ライダーゼロワン 変身ベルト DXザイアサウザンドライバー

仮面ライダーゼロワン 変身ベルト DXザイアサウザンドライバー

  • 発売日: 2019/12/28
  • メディア: おもちゃ&ホビー

*1:SonarQubeの開発・運営会社

JetBrains Rider 2019.3でUnityテストのカバレッジを採取する

JetBrains製のC# IDEであるRiderには、テスト実行時にステートメントカバレッジを採取するdotCoverプラグインが提供されています。

これまで、dotCoverプラグインはUnity Test Framework*1に対応していませんでしたが、2019.3からEdit Mode tests実行時のカバレッジを採取・表示できるようになりました。

www.jetbrains.com

dotCoverプラグインの有効化

dotCoverプラグインは、一般のプラグインと同様、Preferences... > Plugins から有効化できます。 ただし使用するには、"ReSharper Ultimate + Rider" または "All Products Pack" のライセンスが必要です(30日間の試用あり)。

また、計測対象のUnityプロジェクトには、JetBrains Rider Editorパッケージの1.2.0以降が必要です。バージョンが古い場合は、UnityエディタのPackage Managerでアップデートしてください。

本稿では以下のバージョンで動作を確認しています。

  • JetBrains Rider 2019.3.1
  • Unity 2019.3.0f1
  • JetBrains Rider Editor 1.2.1
  • Test Framework 1.1.9

カバレッジ採取の準備

dotCoverプラグインカバレッジを採取するには、以下の準備が必要です。

1. Unityエディタを "Start Unity with Coverage" で起動する

RiderでUnityテストを実行するにはUnityエディタとのコネクトが必要ですが、dotCoverを使用するときには通常とは異なる方法でコネクトします。 Unityエディタは一旦閉じ、RiderのUnityツールバー左端にあるUnityロゴをクリックして "Start Unity with Coverage" で起動します。

f:id:nowsprinting:20200111201900p:plain

もしほかの方法で起動したUnityエディタとコネクトした状態でカバレッジを採取しようとすると、下図のアラートが表示されます*2

f:id:nowsprinting:20200111201903p:plain

2. 実行環境にEdit Modeを選択する

カバレッジの採取は、"Unit Tests"タブにあるプルダウンで"Unity Editor - Edit Mode"を選択した状態で実行する必要があります。

f:id:nowsprinting:20200111204832p:plain

つまり必然的に、Play Mode testsのカバレッジは採取できません。

カバレッジの採取

カバレッジは、以下の手順でテスト実行することで採取できます。

  1. Riderのエディタでテストコードを開き、テストメソッド定義にカーソルを置いて alt + enter*2 でContext Actionsメニューを表示します
  2. すると下図のように "Cover" が選択できますので、enterを押下すると当該メソッドが実行されます

f:id:nowsprinting:20200111202202p:plain

もしくは、Rider下部の"Unit Tests"ウィンドウにある"Explorer"タブでEdit Modeテストのアセンブリを選択し、左にある"Cover"アイコンをクリックすると、すべてのEdit Modeテストを実行できます*3

f:id:nowsprinting:20200111215057p:plain

Coverを実行すると、テスト実行結果が"Unit Tests"ウィンドウに表示されるほか、"Unit Tests Coverage"ウィンドウにステートメントカバレッジが表示されます。

カバレッジの見かた

"Unit Tests Coverage"ウィンドウでは、テスト対象のステートメント数と、テスト実行によって通過した/していないステートメント数、またその割合が確認できます*4

f:id:nowsprinting:20200111201855p:plain

また、この状態でテスト対象ソースコードをエディタタブで開くと、通過した/していないステートメントを確認できます。 グリーンでマークされた行(下図16〜19, 25行目)は通過したステートメント、グレーでマークされた行(同22〜23行目)は通過していないステートメントです。

f:id:nowsprinting:20200111201857p:plain

ステートメントカバレッジの使いどころ

ステートメントカバレッジとは、ユニットテストによってテスト対象コードの全ステートメントのうち何%がテストされているかを示すメトリクスです。命令網羅、C0とも呼ばれます。

カバレッジ」には、ほかに、デシジョンカバレッジ、条件カバレッジなどが使われます。 上の例では19行目が通過していることしか確認できませんが、デシジョンカバレジを満たすには a == 0 のテストケースと、a != 0 かつ b == 0 のテストケースが必要です。

また、ステートメントが実行されたことは確認できますが、それが正しい実行結果であるかはアサーションで適切に判定されている必要があります。

以上の観点から、ステートメントカバレッジは品質の指標として信頼度の高いものとは言えず、あくまで「めやす」くらいにとどめるのが良いでしょう。

関連記事

www.nowsprinting.com

www.nowsprinting.com

関連書籍

IntelliJ IDEA パーフェクトガイド

IntelliJ IDEA パーフェクトガイド

  • 作者:横田 一輝
  • 発売日: 2019/11/27
  • メディア: 単行本(ソフトカバー)

仮面ライダーゼロワン 変身ベルト DXエイムズショットライザー

仮面ライダーゼロワン 変身ベルト DXエイムズショットライザー

  • 発売日: 2019/08/31
  • メディア: おもちゃ&ホビー

*1:Unity 2019.2以降パッケージ化された名称。詳しくは https://www.nowsprinting.com/entry/2019/09/28/132800 を参照

*2:Rider 2019.3.1から表示されるようになった模様

*3:Play Modeテストが存在しないのであれば、Tests > Cover All Tests from Solution でもすべてのテストを実行できます

*4:おそらくRider 2020以降で、ウィンドウに表示する(集計する)対象をフィルタリングできるようになります

JetBrains Rider 2019.3でUnityのPlay Mode testsを実行する

JetBrains製のC# IDEであるRiderの2019.3がリリースされました。 これまで、RiderからはUnity Test Framework*1のEdit Mode testsのみ直接実行することができましたが、2019.3からはPlay Mode testsも実行できるようになりました。

www.jetbrains.com

Unityテストの実行方法

基本的には、Edit ModeもPlay Modeも以下の手順で実行できます。

  1. Riderのエディタでテストコードを開き、テストメソッド定義にカーソルを置いて alt + enter*2 でContext Actionsメニューを表示します
  2. すると下図のように "Run" が選択できますので、enterを押下すると当該メソッドが実行されます

f:id:nowsprinting:20200110230813p:plain:w200

テスト実行結果は、Rider下部の"Unit Tests"ウィンドウに表示されます。

Unityテスト実行の前提条件

テストの実行はUnityエディタで行われるため、UnityエディタのプロセスとRiderとがコネクトされてる必要があります。

Unityエディタとのコネクトは、Rider右下に表示されているアイコンで判断できます。下図、右から3つめのUnityロゴ右下にグリーンの丸が表示されていればコネクトされています。

f:id:nowsprinting:20200110233055p:plain

UnityエディタからRiderを開いた場合はコネクトされた状態のはずです。Unityエディタを再起動したなどコネクトが切れた場合、Unityツールバーの左端にあるUnityロゴをクリックし、"Start Unity"で起動しなおすか、すでに起動しているプロセスに"Attach to Unity Process..."でコネクトできます。

f:id:nowsprinting:20200110233103p:plain

Play Mode testsの実行方法

Play Mode testsも、上記と同じ手順でテスト実行することができます。 ただし、"Unit Tests"ウィンドウにあるプルダウンで"Unity Editor - Play Mode"を選択した状態で実行する必要があります。

f:id:nowsprinting:20200110230824p:plain:w500

これを切り替えずに実行すると、上図のように"Inconclusive: Test not run"と表示され、テスト実行されませんので注意してください。

なお、逆に、Edit Mode testsを"Unity Editor - Play Mode"で実行しようとしても同様にテスト実行できません。"Unity Editor - Edit Mode"を選択した状態で実行する必要があります。

所感

Riderから直接Play Mode testsが実行できるようになったことは喜ばしいことです。 しかし、プルダウンでの切り替えが必要ですし、Play Mode testsの最大のメリットであるプレイヤー(iOSAndroidの実機など)での実行ができるわけではありません。 個人的には、引き続きEdit Mode testsを中心に書いていくのがよいと考えています。

Tips

デバッグ実行

Context Actionsメニューに表示される "Debug" を選択すると、テストをデバッグ実行することができます。 もちろん、ブレイクポイント、ステップ実行、変数のインスペクションなども使用できます。

アセットの自動リフレッシュを抑止する

Riderのデフォルト設定では、テスト実行の都度、Unityエディタでアセットのリフレッシュが実行されます。 特にTDD (Test Driven Development: テスト駆動開発) で開発を進める場合など、頻繁に待ち時間が発生してしまいますので、この設定をオフにすることもできます。

Preferences... > Languages & Frameworks > Unity Engine を開き、"Automatically refresh assets in Unity" チェックボックスをoffにします。

www.jetbrains.com

関連記事

www.nowsprinting.com

www.nowsprinting.com

関連書籍

IntelliJ IDEA パーフェクトガイド

IntelliJ IDEA パーフェクトガイド

*1:Unity 2019.2以降パッケージ化された名称。詳しくは https://www.nowsprinting.com/entry/2019/09/28/132800 を参照

*2:Mac OS X 10.5+ Keymapの場合

モブプロはまだ腰痛には効かないがそのうち効くようになる

この記事は、モブプログラミング Advent Calendar 2019の6日目の記事です。 タイトルでお察しの通り、ネタエントリです。

※この記事は個人の感想であり、効果・効能を示すものではありません

腰痛

腰痛の原因には個人差があります。私の場合は同じ姿勢で座りっぱなしで、腰の一部の筋肉にずっと負荷をかけ続けてしまうことだと言われていて、以下のような緩和対策をしています。

  • 椅子に後傾姿勢で座り、背もたれに負荷を分散させる
  • 適度に立ち上がって動かす

このうち、2番目についてはApple Watchの「スタンド」アクティビティが1時間ごとに立ち上がって歩くことを促してくれます。これは心臓疾患などのリスクを回避するためのものらしいのですが、私のケースでは腰痛の緩和にも寄与します。

ただし、アラートに従えばの話。興が乗ってるとチラッと見て無視しますよね…

モブプロ

そこでモブプロです!

ここを読んでいる皆さんは御存知の通り、モブプログラミング(モブワーク)では数分単位でドライバーを交代していきますので、強制的に席を替わるために立ち上がって少し移動しなければなりません。 またすぐ座って再開するものの、ちょっと身体を動かすきっかけには十分ですね。

とはいえ、ただちに「モブプロで腰痛緩和!」とまでは言えません。 席移動しないでモニターだけ切り替える形式だと席移動は発生しませんし、席移動のたびに集中を切らしていては効率が悪くなってしまいそう。うまくモブプロに腰痛対策を組み込んでいければいいなと思っています。

参考文献

WEB+DB PRESS Vol.102

WEB+DB PRESS Vol.102

  • 作者:
  • 出版社/メーカー: 技術評論社
  • 発売日: 2017/12/23
  • メディア: 単行本

.NET Conf in Tokyo 2019に行ってきました #dotnetconf #dotnetconfunity

日本マイクロソフトさんで行われた、.NET Conf in Tokyo 2019 に行ってきました。

vsuc.connpass.com

午後は2部屋に分かれたうちの Room B(Unityトラック)にずっといました。 Room C+D(.NETトラック)が気になる方はハッシュタグ #dotnetconfdotnet を参照。

以下、スライドは拾えたものだけ。Unityトラック分は近日中にUnity Learning Materialsで公開されるはずです。

What’s New in .NET Core 3.0 and Visual Studio 2019 for .NET developers

MicrosoftのSteve Carrollさん

サテライトの音声よくなかったこともあって*1ろくにメモできていません…

デモアプリ等はここに。

https://github.com/dotnet-presentations/dotnetconf2019/tree/master/Technical/keynotegithub.com

Clean Architecture for Unity

www.slideshare.net

  • @monry さん
  • Visual Studio Users Community Japan #1における@nuits_jpさんの『世界一わかりやすいClean Architecture』とかぶった
  • Clean Architecture(以下CA)とはなにか → そんなものはない
    • ざっくりとした指針は示されている
  • CAの図は、あくまで一例。押さえるべきポイントを押さえれば自ずとCAになる
  • SOLID原則とDI
    • SOLIDの元論文は2000年、Robert C. Martin氏
      • CA本の著者
      • その時点ではSOLIDという略称ではない
    • DI
      • DIPを実現するパターン
      • Zenject
        • Unityにおいては、MonoBehaviourに対するinjectが難しい
        • Installerで実体の作り方/探し方を定義
  • UnityにおけるCA
    • ざっくりした方針は2つだけ
      • 依存の向きは外から内のみ
      • 制御の流れは依存と切り離して考える
    • pros: 疎結合、テスタビリティ、慣れると可読性が高い
    • cons: interface/class多い(3-4倍+)、要IDEVSCodeでは厳しそうなレベル)、慣れるまで可読性低い
    • CAFU (Clean Architecture for Unity) を作って使っている(キッズスター社)
    • レイヤ定義
      • Application:
        • CAの文脈から外れる要素はここに置く。他から結構依存される
        • ValueObject
          • マスタデータ用の型、enum
          • 状態管理、transaction
        • Installer
          • ZenjectのInstaller
        • Signal
          • 抽象を用いないで制御を授受するための型。struct
          • UniRx.MessageBroker, Zenject.SignalBusとか
      • Domain: Entity, Use Case
        • Entity: 計算。Use Caseとのみ対話する
        • Use Case: Entityと対話。RepositoryやPresenterをつなぐ。Use Caseのみで完結可能な処理もある(Entity使わない)
      • Data: Repository, Datastore
        • Repository: Datastoreと対話。窓口。CRUDなインタフェース
        • DataStore: 実際に管理。メモリ、DB
      • Presentation: Presenter, View
        • Presenter: ユーザ対話の窓口、Viewと対話
        • View: ユーザとの対話。要するにUnity
    • 処理の起点はUse Caseに担わせるとよさげ
    • Zenject.IInitializable.Initialize()を実装させる
    • 状態をDataレイヤに取り扱わせる(Entityだとめんどくさかった)
    • 特にwriteはDataで行なう
    • Viewをいかに一般化するか。UniFlowを作っている

参考

booth.pm

MagicOnion〜C#でゲームサーバを開発しよう〜

www.slideshare.net

  • @toRisouP さん
  • サーバ: .NET Core, クライアント: Unity or .Net Core という構成
  • gRPCだが、データフォーマットはMessagePack for C#、protoc不要
  • 定義(C#コード)をクライアントとサーバのプロジェクトで共有
  • gRPCコネクションを張って、あとはasync/awaitでメソッドを呼ぶだけ
  • 実装できるAPI: Service, StreamingHub
    • StreamingHub: gRPCのBidirectional Streaming RPC
  • Filter: 通信の前後に処理を追加できる
    • フィルタメソッド定義して、フィルタ有効にしたいメソッドにAttributeつければok
    • 認証とかログとかエラー処理とか
  • Swagger, Telemetry対応
  • 環境構築はむつかしい
  • StreamingHub
    • クラサバ両方で状態を管理する必要があるので複雑になりがち
    • Receiver: サーバ → クライアント
    • Hub: クライアント → サーバ
    • MessagePackObjectを定義
      • サーバ側にMessagePack.UnityShimsを入れると、Vector3とか使えてべんり
    • Group: Hubを束ねる
    • Broadcast: いろいろある
  • 実装時の注意
    • クライアント
      • gRPCのコネクション管理ちゃんとしないとフリーズしたりする。Unmanaged
    • サーバ
      • .NETのServer GCを使うのおすすめ
      • ThreadPoolのサイズを上げる。デフォルト25なので
      • Generic Hostを使う
  • デプロイ
    • Docker, CircleCI, Kubernetesでコンテナ管理がよさげ
    • MagicOnionのサーバ構成
      • ステートフル: インメモリでデータを保持する、Groupはインスタンス縛り、リアルタイムに向く
        • Agonesに期待
      • ステートレス: Load Balanserに繋げばやってくれる。オートスケーリングできる
        • バックエンドにRedisが必要

Riderはいいぞ!

speakerdeck.com

  • @RyotaMurohoshi さん
  • Code Inspection
  • solution-wide analysis
    • preferencesで有効化。デフォルトはerrorのみ?
    • ディレクトリを指定できる
  • Quick Fix
    • 書いているソースだけでなくプロジェクト全体とか特定範囲とかもできる
  • Code Vision
    • Find Unity Usage
  • Live Template
    • preferencesで設定
    • 自分でも登録できる
  • File Template
  • Code Generation
    • MonoBehaviourのメソッドを作ってくれる: Unity Event Functions
  • Performance Indicators: Update()から呼ばれてるメソッドで非効率なコードを書くと怒られる
  • Unity連携、デバッガ*3
  • おすすめショートカット
    • alt + enter : Quick Action*4
    • shift + command + A : Find Action
    • shift + shift : Search
  • チュートリアルがある*5

参考

[.NET/Unity開発者向け] JetBrains .NET Meetup Tokyo #JBRiderTokyo - JetBrains | Doorkeeper におけるJetBrains社のKirill Skryganさんのセッション動画

www.youtube.com www.youtube.com

書籍

C#×LLVM=アセンブラ!? 〜詳説・Burstコンパイラー〜

learning.unity3d.jp

  • Unity 安原さん、名雪さん
  • 以前: C# → IL → Mono(AOT/JIT) → 機械語
  • IL2CPP*6: C# → IL → C++機械語
  • Burst: C# → IL →(Burst)→ IR*7 →(LLVM)→ 機械語
  • なぜBurstが速いのか
    • LLVMがIRをすごい最適化する
      • IL2CPPは互換性重視、インライン展開されにくいなど
    • SIMD*8を使う
      • SSE (Intel), NEON (ARM)
      • プラットフォームによって対応情報は違う。SSE2, SSE4とか
    • メモリエイリアス
      • memcpy()もベクタライズ
      • srcとdstの範囲が重なっている可能性 → 結果が変わってしまう → ビルドエラーが出てくれる
  • 制約
    • C# Job Systemのみ
    • クラスなど参照型が使えない → struct, NativeArray, NativeString
    • 例外処理できない。throwは使える
  • 実演
    • DOTSのプロファイリングはPlayerビルドしてプロファイラつないで見る
    • 25ms → 3msに高速化
  • メニューの Jobs > Burst : エディタ実行するとき設定
    • Enable Compilation
    • Safety Checks
  • Project Settings > Burst AOT Settings : Playerビルドするときはこちらの設定が使われるので注意
  • メニューの Jobs > Burst > Open Inspector...
    • "Refresh Disassembly"をクリックすると表示される
    • このウィンドウ用にコンパイルされるので、"Safty Checks"トグルとかもここだけに影響する(上記2つの設定とはまた別)
    • "Enhanced Disassembly"をonにすると、コメントとしてC#コードが出てくれるはず
  • float4を使うコードに書き換えるなどしないと勝手にベクタライズはされにくい。やっても早くなるとは限らない。LLVMだけでも十分速くなるはず
  • 機種間deterministic
    • 単精度のadd, sub, mul, div, sqrtは保証されている。すごい
  • Unity.Burst.Intrinsics
    • public static m128 load_ps_128(void* ptr) とか

所感

いずれのセッションも濃い話でたいへん勉強になりました。 はじめ、Unity側は(中途半端には)知っている話もあるし.NET側に行こうかとも考えたのですが、Unity側で正解でした。 Burstコンパイラ完全に理解した。

お土産にいただいたピンバッジ。かわいい。C#ステッカーもかわいい。

f:id:nowsprinting:20191027202108j:plain:w300

*1:最初C+Dに入ったのですがどうせ午後Bだからと移動して、そのまま居着いてしまった

*2:作者の@neueccさんのお言葉: https://twitter.com/neuecc/status/1188329065318498305, https://twitter.com/neuecc/status/1188330470515208193

*3:ちなみにEdit Mode testsもデバッガで実行できます。べんり!

*4:ちなみにテストメソッドにフォーカスした状態ではRunとDebugが出てきます。べんり!

*5:Riderのスプラッシュ画面右下のGet Help > Tutorials...

*6:WebGLで動かすためにハックウィークで作ってみたのが発端とか。後になって速度面とかiOSの64bit対応問題でメインストリームになったと

*7:Intermediate Representation: 中間表現

*8:Single Instruction Multiple Data: しむど