Raspberlyのブログ

Raspberlyのブログ

Unityネタをメインとした技術系ブログです。にゃんこ大戦争や日常なども。そろそろブログタイトル決めたい

【勉強会レポ】: .NET Conf in Tokyo 2019 (Unity Track)

勉強会のレポート(メモ)です。
参加したのはこちら、「.NET Conf in Tokyo 2019」
会場はマイクロソフトさんです。

vsuc.connpass.com

ハッシュタグは3種類あります。
共通 : #dotnetconf
.NET Track : #dotnetconfdotnet
Unity Track : #dotnetconfunity

 

f:id:Raspberly:20191027190126p:plain

 

本イベントは.NETに関する.NET TrackとUnityに関するUnity Trackの2つに分かれています。
このレポではUnity Trackをメインでお送りします。

 

 

Room B (Unity Track)

時間 タイトル 発表者
11:00-11:05 Opening .NET Conf 2019 in Tokyo Hiroyuki Mori (@hiroyuki_mori)
11:00-12:20 What’s New in .NET Core 3.0 and Visual Studio 2019 for .NET developers(サテライト会場) Steve Carroll
13:20-14:10 Clean Architecture for Unity Tetsuya Mori (@monry)
14:20-15:10 MagicOnion〜C#でゲームサーバを開発しよう〜 torisoup (@toRisouP)
15:30-16:20 Riderはいいぞ! Ryota Murohoshi (@RyotaMurohoshi)
16:30-17:20 C#×LLVM=アセンブラ!? 〜詳説・Burstコンパイラー〜 ユニティ・テクノロジーズ・ジャパン 安原祐二・名雪
17:20-17:30 Closing Tetsuya Mori (@monry) and torisoup (@toRisouP)

 

 

 

 

 

 

 

 

#1. Clean Architecture for Unity

f:id:Raspberly:20191027193743p:plain

対象者

Unityでもしっかりと設計したい人
Clean Architectureの導入事例を聞きたい人
マサカリを研いでいない人 

話すこと

設計に関する基本
Clean Architectureの例の図
Unityに適応してみた話

 

オススメ資料
世界一わかりやすいClean Architecture

www.nuits.jp

お仕事の宣伝

キッズスターでごっこランドという職業体験アプリを作っています

biz.kidsstar.co.jp

ここで得た知見をお話します

 

Clean Architectureとは

f:id:Raspberly:20191027190748p:plain

厳密に定義されたものは存在しません。ざっくりとした指針はあります。
みんなが思う最高のClean Architectureを作りましょう


この図を見たことはありますか?


この図にはいろいろ書かれていますがこれは一例です。
抑えるポイントを守ると自然とこの図になります。今日はこのポイントを覚えて帰ってください。

SOLID原則とDI

Clean Architectureと切っては切れないもの。
SOLID原則は保守性の高いソフトウェアを開発運用する上で基本となる考え方。
守れば保守性の高いコードが書けます。

SOLID原則とは何か

5つの原則をまとめたものです。

単一責任原則

クラスが担う責務は一つだけにしなさいというルール。
なんちゃらManagerやなんちゃらControllerなど主語がでかい名前をつけるとこれを守りづらくなります。
責務が狭い名前をつけましょう。

オープンクローズド原則

拡張に開いて修正に閉じる。
拡張しやすく、ただしそれぞれのメソッドに修正が発生しないようにすること。
インターフェースやアブストラクトを使いましょう。

リスコフの置換原則

親クラスと子クラスは置換可能であるということ。
C#の場合、newによる上書きで違反しやすい。

インターフェース分離の法則

いらないメソッド・プロパティは実装しないさせないこと。
C#は複数インターフェースを実装できるが、これらのインターフェースは分離しましょう。
ここは単一責任原則にもつながるところ。
多機能なインターフェースを実装すると破られます。

依存性逆転の原則

一番重要
抽象に依存し実装に依存させないということ。
ざっくりいうとインターフェースを引数にとり、実クラスには関心を持たせない。
DIはこれを実現するためにある。

Dependency Injection(DI)

依存性逆転を実現させるためにあるもの。
UnityではZenjectが有名。Mono Behaviourへの注入をいい感じにやってくれる。
Mono BehaviourはnewができないしPropertyをInjectionすることができない。
そこをZenjectが裏で頑張っていい感じにやってくれます。
Zenjectの場合、Installerでルールを定義できるようになっています。

 

詳しくはZenjectチョットワカルBookがおすすめ

booth.pm

UnityにおけるClean Architectureをどう実現するか

Clean Architectureは2012年にロバート・C. マーチンさんがブログで発表したもので
ざっくりとした方針だけ定義しました。
方針はこの2つ
・依存の向きは外から内のみ
・制御の流れは依存と切り分けて考える

 

依存の向きとは何か

図の矢印の向きのこと。

f:id:Raspberly:20191027214824p:plain

外から内にのみ向くようにしましょう。
ちなみに図にある名前は、あくまで目安です。そういう名前にしなさいというものではない。

制御の流れ

データの流れは内から外にだが制御の流れはどっちでも大丈夫。
内から外にいくのは割とシンプルになるが、入力はObserberパターンを使わないとしんどくなる。

 

なぜクリーンアーキテクチャをつかうのか

注意、こっからは一例です。

ごっこランドには50個以上のミニゲームが入っています。
それぞれのミニゲームは1つ1つのUnityプロジェクトであり、最後に1つのプロジェクトにマージ。
いろいろな人が開発にかかわるが、書き方を統一したかった。

導入したメリット

疎結合、テスタビリティが高い
慣れると可読性が高い

デメリット

インターフェース、クラスが多くなる。
VSやRiderなどIDEによる管理が必要
慣れるまでは可読性が低い


キッズスターではクリーンアーキテクチャ開発をするうえでブラッシュアップをし、
今はCAFUという名前で開発しています。

 

レイヤー定義とかはスライドを見てください。

まとめ

依存の向きは外から内にすること
これはキッズスターでの事例です
境界を区別することが重要

 

 

 

 

 

 

 

 

 

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

f:id:Raspberly:20191027193912p:plain

今回MagicOnionについてお話します。

スライドが脅威の180枚なので詳しくはそちらをどうぞ。

MagicOnionは何なのか

ネットワーク通信のフレームワーク。サーバーはC#で書けます。
定義した共有ファイルを介することすることで通信する。
通信レイヤを気にせずサーバーを呼び出せるのが特徴

 

MagicOnionの機能

実装パターンは2つ

Service

シンプルな単発通信
1リクエストに1レスポンス

SreamingHub

リアルタイム通信向け
コネクションを張ったまま維持し自由にメッセージを送信できる

Filter

通信の前後に処理を追加する機能
かなり用途があります。

環境構築

環境構築は大変

ライブラリの追加

クライアント(unity)に各ライブラリを手動で導入。
PlayerSettingも設定が必要。

(ついでにUniRxとUniTaskも便利なのでオススメ)

コードの共有

おすすめの方法はサーバー側のスクリプトにUnity/Assets以下を参照するよう記述。
プロジェクト構成も見直しましょう。Git管理する時は全部まとめてやる。

このやり方なら設定が楽で環境に依存しない。
ただし、リポジトリが1つなるので開発フローの整理が難しくなる。

これらのデメリットをなくすには、
サーバーとゲーム本体でリポジトリとして分けて接続部分は生成したunitypackageをインポートする。

コードジェネレート

MagicOnionではコードジェネレートが2回必要。
ジェネレータはそれぞれgithubから持ってきましょう。
ボタン一発でジェネレートできるエディター拡張もあるよ

環境構築まとめ

・環境構築が大変
・開発フローはよく考えよう
リポジトリをどうわけるかなどはチーム内でよく話し合いましょう

実装例の紹介

詳しい手順はスライドを見てどうぞ

実装時の注意点 おぼえておくといいテクニック

gRPCのコネクション管理をちゃんとやりましょう

C#のgRPCはunmanaged、Disposeしないとすぐリークします、忘れないようにしましょう。
マネージャを自分で作って管理するとよい。

サーバー側でやっておくといい設定

GCモードをServerに切り替えよう
・ThreadPoolのサイズを上げておこう。
・GenericHostを使おう
 これはアプリケーション開発に便利なものをまとめたもの
 MagicOnionもこの上で動かしましょう

実装の注意点のまとめ

・コネクション管理じゃ気を付けよう
・GenericHostを使おう。

デプロイ

サーバーで動かすならDockerビルド。
Kubernetesでコンテナ管理がよい。

MagicOnionのサーバー構成

2つの構成が選べます
事実上ステートフル一択

ステートフル構成

インメモリでデータを保持する実装。
リアルタイム通信に向いている、インメモリですむので外部ストレージも使わない。
Kubernetesと相性が悪い。

ステートレス構成

プロセス上に状態を持たない構成。プロセス同士がバックエンドで動く。

構成のまとめ

リアルタイム通信はステートフルがおすすめ。
ただしKubernetesがきびしい。

 

まとめ

・サーバサイドもC#でいい感じにつくれる
・クライアントとサーバをC#で統一できる
・開発フローの整備が課題
・サーバーサイドの開発知識はある程度必要

 

MagicOnionはいいぞ

 

 

 

 

 

 

 

 

 

 

 

 

#3. Riderはいいぞ!

f:id:Raspberly:20191027193826p:plain

Unityプログラマの皆様にRiderを使ってみたくなるような紹介セッションをします

 

デモタイム

Riderはコードを書く上でのわかりにくい改善ポイントを指摘してくれます。
こういう便利な機能がたくさんあります。

JetBrains

チェコにある会社です
様々な言語・プラットフォームのIDEを作っている会社です。Riderはその中の1つ。


Riderはクロスプラットフォームに対応しています。
さらにUnityのサポートが手厚い。

C#やUnityを始めた人に特におすすめ
教える側の人にもおすすめ

Riderの機能紹介

いい感じのコードに書き換えてくれるので、一部の人から赤ペン先生と呼ばれます。
それぞれ機能に名前がついています。

たくさんあるので詳しくはスライドを。

Code Inspections

・新しいC#に置き換えられるところを指摘してくれる
・エラーになっているところやなりそうなところの指摘
・到達しないコードや不必要なコードの指摘
・タイポの指摘

さらにレベルの概念があります。(エラー・警告・提案・ヒント)

・なんでよくないかも教えてくれる
・ソリューション全体や特定のディレクトリのみなど特定のスコープで探索もできる
・アセットやSDKの中のコードも分析対象になってしまうので、設定で無視するようにした方がいいです

Run Inspection by Name

特定のインスペクション項目のみ探す機能
コードの一括変換などに便利。

Qucik Fix

Code Inspectionsで指摘されたコードをサクッと修正できる機能

Code Vision

このコンポーネントどこで使われているかを見ることができる
どこのシーンのどこのプレハブで使われているか、インスペクターでどんな値が設定されているかも見れる。

Live Template

よくあるお決まりコードを作ってくれるが、同時に型や名前を同時に設定できる。
Unity用のテンプレートがたくさん用意されています。
さらに自分でテンプレートを作ることもできますし、共有できます。

Code Generation

よくあるコードやUnity標準のイベントファンクションズ(Startとか)も簡単に作れる

Perfomane Indicators

パフォーマンスチューニングをしてくれます。
明らかに非効率でやっちゃいけないところを指摘してくれる機能。
Update内でGetComponentを呼ぶなど 

UnityEditorとの連携

RiderからUnityを制御でき。RiderからDebugLogを見ることができる。
BreakPoint内で変数を見ることができる

とりあえず覚えてほしいショートカット

Show Action List

option+enterまたはalt+enter

その文脈でできることを表示してくれる。

Find Action

Ctrl+Shift+A
Riderはできることがたくさんあるが、覚えれないことがある
それを検索できる

Serach Everywhere

Shift+Shift

コードもクラスもファイルもアクションなども全て検索できる

 

 

 

 


Code Inspectionsの提案理由はGitHubに一覧があるのでぜひ見てください。

github.com

Riderのチュートリアルもあります

Riderはいいぞ

 

 

 

 

 

 

 

 

 

 

 

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

learning.unity3d.jp

f:id:Raspberly:20191027193545p:plain

資料、動画は後日公開予定です。Burstコンパイラのお話をします。 

コンパイラの話

書かれたC#は実行されるときは機械語になります。
その中間には何があるのか、普通はILがあります。
C#などはいったんILに変換され、AOTかJITで実行します。

 

現在は、IL2CPPの登場でLIからC++に変換します(WebGLで動かすために作られた)
今ではIL2CPPが基本になっている。

Burstコンパイラでもっと早くする

C#からILになるところは同じだが、そこからBurstコンパイラIRに変換
そこかLLVM機械語に変更します

LLVMとは

様々なプログラミング言語に対応可能なコンパイラ基盤。
昔は「Low Level Virtual Machine」という略称があったが今はない。

IR(Intermediate Representation 中間表現)

LLVMが扱う中間言語
プログラミング言語、CPUアーキテクチャから独立している。
LLVM機械語にする前にIRを最適化する。

 

なぜBurstは早いのか

LLVMの最適化が効くため

すごい最適化をしてくれる。人類が考えるあらゆる最適化が含まれている。
IRには最適化前と最適化後の2種類あります。

BurstはLLVMの読み込みやUnityとの連携をしてくれる。まさに人類の英知

f:id:Raspberly:20191027193416p:plain

 

SIMD(シムド)

single instraction multiple data
ひとつの命令で複数の計算を行う仕組み。
SSE(Intel CPU) NEON(ARM UPC)など。
機械語の命令語のひとつ。

 

Burstの制約

1.C# Job Systemでしか使えない
2.クラスが使えない

ガベージコレクションを避けるためマネージドヒープを使う参照型は使えない
ただし代わりに構造体、NativeArrayが用意されています

3.例外処理ができない

try・catch・finallyが使えない、throwは使える(jobは止まる)

 

実演 波動方程式を使って波紋を出すデモ

NativeArrayはUnityエディタでの計測は信用できないので、ビルドして確認します。
結果8倍くらいはやくなる。

↓デモプロジェクト

github.com

注意点

Burstを動かす設定ですが、エディター実行時とビルド時で個別で設定する必要があります。
ビルドする時はProjectSettingから設定しましょう。
BurstInspectorも同様です。

ベクタライズは手動でやる必要があります。自動ではやってくれない。

まとめ

IL2CPPは汎用性が高かったが高速化ができなかった。
Burstは制約を設けることで高速化できた。
Burstは特にDOTSで威力を発揮します。

 

 

 

 

 

 

 

 

 

 

.NET Trackの資料

Unity Trackとは別室で行われていた.NET Trackの資料も載せておきます。

 

 

 

 

 

 

 

関連資料

CAFU

CAFU v3 完全に理解した / Updates for CAFU v3 - Speaker Deck

 

先日のRoppongi.unity #5にてUniFlowに関するLTがありました

raspberly.hateblo.jp

 

SOLID原則についておすすめの資料

www.slideshare.net

 

 

とりすーぷさん主催のMagicOnion勉強会のレポ

raspberly.hateblo.jp

 

 むろほしさんJetBrains .NET Meetup Tokyoにてされた講演資料

learning.unity3d.jp

 

 Burstコンパイラではありませんが関係のあるDOTSの資料

learning.unity3d.jp

 

 

 

 

他の方の感想ブログとか

www.nowsprinting.com

tech-blog.cloud-config.jp

 

 

 

 

 

 

いろいろ理解が足りていないため間違っている箇所がありましたら、コメントにお願いします。