やらなイカ?

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

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

この記事は、モブプログラミング 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: しむど

UWA GOTでUnityアプリのプロファイリング(Android編)

UWA*1 GOT*2は、Unityアプリのプロファイリングを行なう商用ツールです。 CEDEC 2019のセッション『あなたのモバイルゲーム開発の最適化時間を数ヶ月節約する方法』で紹介されました。

セッション後にUWAのブースやメール*3で問い合わせた内容も含め、簡単な使い方をまとめます。

jp.uwa4d.com

UWA GOTは、Unity 4.6以降で使用できます。ただし、後述のUWA GOT オンラインを利用する場合は、Unity 5.6以上が推奨とのこと。

プロファイリング対象プラットフォームは、CEDEC 2019時点のv2.0.0ではAndroid (Mono)とWindows (Mono)でしたが、最近リリースされたv2.0.1でiOS (IL2CPP)も対象となりました*4

プロファイリングは、以下の流れで行ないます。

  1. プラグインを組み込んでビルドしたアプリを端末にインストール
  2. アプリを実行・計測し、別の専用アプリでデータをプロファイラ(ローカルとオンラインの2種類から選択できます)に送信
  3. プロファイラで測定データを表示し、性能ボトルネックを調査

計測をアプリ単体で行なうことができるため、テスター・デバッガの手で実行することができます。反面、現状どうしても手作業が必要になるため、デバイスファーム等で大量の自動テストを実行しながらプロファイリングを行なうようなユースケースには向きません*5

UWA GOTの構成

構成要素がいくつかありますので、先に説明します。

GOT SDK

UWA GOT公式サイトからダウンロードできます。プラットフォームごとにunitypackageが分かれており、いずれかをインポートします。内容は以下。

  • GOT Editor: Unityエディタ拡張。2つの機能を持っています
    • 対象アプリへのGOTプラグインのインテグレーションサポート
    • ローカルサーバ機能
  • GOT プラグイン: 各プラットフォーム向けのプラグイン
  • ドキュメント: 少々古いものなので、ドキュメントは公式サイトからダウンロードできる日本語版を参照

GOT App

計測結果をプロファイラ(ビューア)にアップロードするためのアプリで、Android版とWindows版がzipに同梱されています。計測対象アプリとともに端末にインストールする必要があります。

iOSではプラグインにデータ送信機能が備わっているため、GOT Appは必要ありません。

GOT ローカルサーバ(ローカルテストツール)

Unityエディタ上で動作します。アプリで計測したプロファイリングデータを受信し、表示を行なうビューアです。

GOT オンライン

オンラインでプロファイリング表示を行なうサービスです。 ローカルサーバでのプロファイリング表示に比べ、表示できる項目が多く、また他のアプリの実測値をもとにしたサジェスト機能もあります。

料金体系

ローカルサーバは、使用するマシン1台ごとに¥11,500/年。15日間のトライアルが可能です。

オンラインは、計測データをアップロードできる時間(アプリの実行時間)に対する課金で、¥5,000/時間。 トライアルはありませんが、公式サイトでデモデータを閲覧できます*6

プラグインを組み込むアプリ数、アプリをインストールする端末数、計測回数および時間に制限はありません。

利用手順

まず、UWAのWebサイトで ログイン > 新規登録 から、新規ユーザ登録を行ないます。確認メールが届くまで数分かかります。 ログインできたら、ダウンロードページからSDKと日本語マニュアルをダウンロードできます。

以下、マニュアルを参照してください。以下、わかりにくいところだけ説明します。

SDKインテグレーション

  • ライセンスキーは購入*7後、Webサイト右上のアイコン > アカウント設定 > アカウントの残額 ページの「購入済ライセンス」に表示されます。メールで送られたりしませんのでご注意ください
  • アカウントの残額 ページでは、ライセンスと開発マシンの紐付けを解除して別のマシンに付け替えることも可能です。解除しようとすると「以下のライセンスとアカウントの紐付き関係を解除しますが、操作の取り消しできないため、継続しますか?」というメッセージが表示されますが、オンライン認証であれば特に制限なく解除・付け替え可能とのことです
  • UWA/Prefabs/UWA_AndroidもしくはUWA_IOSを最初に開くSceneのヒエラルキに追加するように書かれていますが、APIでも初期化が可能です。[RuntimeInitializeOnLoadMethod]アトリビュートを付けたメソッドからUWAEngine.StaticInit()を呼び出せば実現できます。APIについてはマニュアルの付録に記載があります
  • GOT Editor > "SDK インテグレーション" > "Build here"でビルドできますが、前提条件を満たしていれば普通にPlayerのビルドを行ってもUWA GOTが組み込まれたビルドとなります
  • ビルドに何らかの原因で失敗しても特にダイアログ等が出るわけではないので、コンソールを見る必要があります
  • UnityエディタのPlayモードではプロファイリングは実行できません
  • デフォルトのビルド出力先UWA_Builds/と、プロファイルデータ格納先TestData/をバージョン管理のトラッキングから外しておくのがいいでしょう
  • Androidでは、デバイスのファイルアクセスを許可する必要があります。v2.0.1ではアプリ起動時にダイアログが出ますが、v2.0.0では設定画面かadbコマンドで許可する必要があります

計測

UWA GOTをバンドルしたアプリを起動すると、下図のGUIがオーバーレイされます。

f:id:nowsprinting:20191025071100p:plain

"Overview", "Mono", "Assets"いずれかをタップすると計測がはじまります。ボタンによって採取できるプロファイルが異なります(後述)。

"Direct Mode"は、onにするとアプリが終了し、再起動するところから計測を開始できます。offのときは、"Overview", "Mono", "Assets"いずれかをタップしたタイミングで計測を開始します。

計測が開始されると"Stop"ボタンが表示されるので、一通り動作させたらこれをタップして計測を終了します。 一度計測を行ったら、アプリを再起動しなければ次の(他の)計測はできません*8

計測データのアップロード

計測データは端末に保存されますので、UWA GOT Appを起動してアップロードします。

f:id:nowsprinting:20191025071124p:plain:w400

"UWAローカルサーバ"は、Unityエディタ上でGOT Editorを開き、"WIFI"ボタンをクリックすると起動します(IPアドレスが表示されます)。 ローカルサーバを起動した状態でGOT AppにIPアドレスを入力(ポート番号は不要)し、"チェックする"をタップします。問題なければ左のマークが緑色になります。

"自分のデータ"の下に計測したデータが並びますので、アップロード先の"Online"もしくは"Local Server"をタップ、最後に"データ提出"をタップするとアップロードできます。

なお、ローカルサーバに上げたデータをGOT Editorからオンラインにアップロードすることもできます。

計測データの表示

GOT Editorの"Overview", "Mono", "Assets"いずれかをクリックするとウィンドウが開くので、右上の"バージョン"でアップロードした計測データを選択します。

f:id:nowsprinting:20191025071430p:plain:w400

f:id:nowsprinting:20191025073622p:plain:w400

"Overview"では、"ファンクション"でCPU, FPS, MonoHeap, Hardware, markerを切り替えて表示できます。

それぞれの数値のグラフ表示、選択した場所(上図の赤い縦線のところ)のスクリーンショット*9、また、メソッド単位でヒープ使用量やオブジェクトカウントの表示*10などが便利な点です。

また、オンライン版では、DrawCall*11Canvas Batching*12なども表示できます。

*1:ゆーわ: 会社名

*2:ごーと: Game Optimization Toolkitの略

*3:UWA Technologiesは中国の会社ですが、日本に代理店があるので日本語で質問できます

*4:AndroidWindowsは引き続きMonoのみですが、近日中にIL2CPP対応されるとのこと

*5:大量のプロファイリングを行ないたい場合は、同じくCEDEC 2019のセッション『Android向けUnity製ゲーム最適化のためのCI/CDと連携した自動プロファイリングシステム』の方式が向いていそうです

*6:プロジェクト > Overview等 > デモプロジェクトを選択。オペレーション列の[確認]クリックで詳細を見ることができます

*7:PayPalで購入できます

*8:改善要望はしており、修正予定はあるそうです

*9:30fpsで撮られていますが、アプリ実行に遅延を感じること無く高速に撮影されているようです

*10:数値は10フレームごとの最大値を出しているそうです

*11:Overview > レンダリングモジュール

*12:Overview > UIモジュール

Roppongi.unity#5 in メルカリ@六本木ヒルズ に行ってきました #roppongiunity

メルカリさんで行われた、Roppongi.unity #5 in メルカリ@六本木ヒルズに行ってきました。

roppongiunity.connpass.com

以下、雑なメモ。スライドは拾えたものだけ。

楽しい!LWRP + 2D Light @lycoris102

speakerdeck.com

  • 新規プロジェクトのテンプレにLWRPがある
  • 既存プロジェクトでは、PackageManagerで追加 → コンテキストメニューでLWRPアセットを追加 → Settings > Graphics で選択できるようになる
  • 2D Renderer
  • Global light 2D
    • sorting layer単位に適用できる
  • Point light 2D

Unityでブロックチェーンアプリを作る @takayukib

  • 分散DBとの違い:非中央集権、改ざん耐性あり
  • .NET向けライブラリがあり、Unityからも使える

nethereum.com

ぼくとAddressablesの戦いの歴史 @akinama3

  • fast/virtual/packed mode
  • 0.1.2のとき
    • バグを報告してエコシステムに貢献するぞ!
  • 0.2.1
    • 破壊的変更
  • 0.3.4
    • 破壊的変更
  • 0.5.x
    • 自分で実装することを考えはじめた
  • Mini Addressablesを作ってみた → 無事リリース
  • previewが外れたらしいのでまた触ってみたい

Zenject.SceneTestFixtureと向き合った @naninuneno_y

speakerdeck.com

LINQ to NativeArray @pCYSl5EDgo

speakerdeck.com

github.com

  • NativeArray GCが一切走らない
  • LINQ WhereでGC Allocate
  • UniNativeLinqを作った
    • MIT, GPLv3
    • manifest.jsonに追加すれば使える
  • AsRefEnumerable()
  • の戻りが参照
  • byteへの変換が簡単
  • LINQより30%高速
  • unmanagedな総称型もある程度使える

Unity花火ワークショップ(小中学生)をやった件について。 @tomotomospot

docs.google.com

  • ゲームエフェクトに興味のあるお子さんが発端
  • 参加者:パーティクル作るだけ
  • モニターorスクリーンで上映会
  • ほかの.unity立ち上げ。参加者・登壇者ともに募集中*1。岩手も深夜バスを使えば安く行ける

iwateunity.connpass.com

yokohamaunity.connpass.com

Visual Scripting ライブラリ「UniFlow」のご紹介 @monry

speakerdeck.com

github.com

  • 処理の逐次実行
  • イベント待受
  • シグナルによるドメイン接続
  • を、UIElementsのGraphViewでやるライブラリを作った
  • MIT License
  • AssetBundle/Addressableにも対応
  • UPMでも提供
  • UnityでできることはUniFlowで、できないことはC#

Animation Riggingで簡単リアルタイムリターゲット @karukaru

speakerdeck.com

  • ボーンの異なるHumanoidに同じアニメーションを適用したい
  • モーキャプのデータは直接ボーンに設定するので、Mecanimのリターゲット機能が使えない
  • 脚が浮いている、接地感がない
  • Animation Rigging
  • multi position constraint: Hipの移動に利用
    • 最大1fだが、position constraintを挟むことで1fを超える値を設定可能
  • multi rotation constraint
  • Animator.HumanScaleを利用して移動量の倍率を変える
  • Animaiton Riggingにはヒューマノイドに必要なものはだいたいある。足りなければ自分で書ける

展示

@warapuriさんの『立体視VRで巨人体験』だけ体験。以前、自分で似たようなもの作ったときはIPD(瞳孔間距離)を大きくしても巨大感が出なかった(ただ飛び上がったように見えた)のですが、こちらはかなり巨大感ありました*2。あとなんかビームが撃てて最高。

所感

すっかりLT会形式が定着した".unity"ですが、機能が多いUnityにはとても合っている形式だと思っています。今回も普段触れない機能やライブラリ、preview packageの話など聞けて楽しかった。

Roppongi.unityも、Gotanda.unityに続いて "流浪の.unity" となるのか、今後の動向に注目ですね。

*1:yokohama.unityにはLT登壇で申し込みました!

*2:IPDはだいぶ大きく取っているという話だったのと、実写なのが要因なのかも?

PlayFab Meetup#1 in Microsoftに行ってきました #PlayFab

日本マイクロソフトさんで行われた、PlayFab Meetup #1 in Microsoftに行ってきました。

connpass.com

以下、雑なメモ。スライドは拾えたものだけ。

Unite 振り返り - 日本マイクロソフト / 南

Unite 2019でのセッション振り返りと、+αのお話。

learning.unity3d.jp

Unity SDKはPlayFab公式サイトからダウンロードできるが、SDKを直接入れるよりもエディタ拡張機能を入れるのがおすすめ。ログイン後、エディタ拡張からSDKをインテグレーションできる。

docs.microsoft.com

PlayFab with HoloLens - JackMasaki

  • PlayFabは様々なユーザ認証APIが提供されているが、Twitterログインは無い
  • xRはID・パスワードの入力がつらい
  • HoloLensのUDIDは使えない
  • xRではLoginWithEmailAddressがベターでは

PlayFab:現実のお金とゲーム内仮想通貨 - Simplestar

スライド: PlayFab:現実のお金とゲーム内仮想通貨

  • 課金プラットフォームざっくり比較してみた
    • Game Sparks: モバイル特化みたい(に見えた)
    • Firebase: Stripeというサービスも使わなければならず、めんどくさそう
    • PlayFabならPayPalが使える
  • Add-ons > PayPal
    • マーチャントID、return linkを設定
  • ゲーム内通貨
    • Economy > Currency > new Currency で追加
    • 通貨コード2桁を指定
  • カタログ:リアルマネーとゲーム内通貨の交換レートを定義。Catalog Bundleを使うと便利
  • PayPalは自分のビジネスアカウントと同一アカウントから支払えない
  • PayPalの履歴には、ゲームタイトルの名前で入る
  • PayPalでUSDをJPYに変換してから払い出し。5営業日くらいで出金(銀行口座に入金)される

リアルタイムコマンドバトルのゲームで PlayFab を使ってみた - 南

www.slideshare.net

  • ゲーム会社でサーバサイド → 辞めてWeb企業に入ったので、個人開発で一式自前で作ってみた
  • コストなどの問題
  • まずDataStoreをPlayFabに移行
  • C# SDK
    • Unity SDKと異なりWebGLとかで動かないが、async/awaitが使えたりする
  • Game Server
    • アウトゲーム系、RESTのものは移行できる
    • gRPCなどリアルタイム系は以前のまま
      • ロードマップではPubSubがprivate previewなのでそのうち
    • 自前サーバコードのホスティングもできない
      • public previewの機能でできそうなのでそのうち
  • まとめ
    • 無料のDataStoreとしてだけでもメリットはある
    • ランキング、マッチング、ショップ
    • リアルタイム通信はまだできない

PlayFabのカタログとマスタデータ - Yoshitaka Kimisaki

スライド: PlayFabのカタログとマスタデータ

  • PlayFabのタイトルデータは、KVSでValue=json。このままマスター管理するのはつらい
  • テーブルで管理したい
  • Airtable というWebサービスを使った
    • Google Spread Sheetのようにブラウザで編集できる
    • APIアクセスできるので、AirtableからPlayFabにデータを移すスクリプトを書けばいい
  • mBaaSの不得手なところは頑張らない

airtable.com

PlayFab の最新ロードマップについて - 梅津(日本マイクロソフト

先日公開されたロードマップについての説明

blog.playfab.com

Whats' new

直近の予定

  • 中国本土での一分機能利用
  • マルチプレイサーバ関係
  • C#CloudScriptの実装、年内予定

2020前半の予定

  • 中国本土での全機能利用
  • User Generated Contentのパブリックプレビュー開始(マインクラフトで使っているもの)
  • PlayFab Insightの機能拡張
  • マルチプレイ、マッチング、パーティ、新しいランキングシステムの一般公開

所感

機能は多いし、大手の適用事例もあるし、安定のマイクロソフトさんに買収されたし、かなり有力なmBaaS*1なのではないでしょうか。

Unite 2019での齋藤さん・南さんのセッションは裏で自分が登壇だったので聴講できなかったのですが気になっていたサービスなので、良いタイミングで色々話を聞けてよかったです。

*1:モバイルに限らない気がするのでBaaSでいいのかも? でもモバイル向けのほうが機能が多いので包括してるのがmBaaS説も。むつかしい…

Unity Test RunnerのPlay Mode testsを実機上で実行する #UniteTokyo

9/25, 26に開催されたUnite Tokyo 2019の『Unity Test Runnerを活用して内部品質を向上しよう』というセッションの中で、テストはPlayer(Android端末など)でも実行できる旨をきちんとお伝えできていませんでした*1

以下の質問をいただいたので、これに回答する形でまとめます。

なお、本セッションのスライドはすでにUnity Learning Materialsで公開中。動画は後日公開される予定です。

learning.unity3d.jp togetter.com

セッション全体のフォローアップ記事はこちら。

www.nowsprinting.com

ネイティブプラグイン自体のテストについて

いきなりオフトピですが、ネイティブプラグイン自体のテストは、C++であればGoogletestXcodeを使ってC++のレイヤでユニットテストを書くべきです。

以下に紹介する、Unity Test RunnerのPlay Mode tests実機実行は素早く実行できるものではなく*2、Unityプロジェクトとのインテグレーション(結合・統合)を確認するためのテストケースだけに留めておくのが賢明です。

Play Mode testsをPlayer(実機)で実行する

Test Runnerウィンドウ

Play Mode testsは、Player(実機)で実行することができます。逆に言うと、Edit Mode testsは実行できません。しかし、すべてのテストを実機で実行する必要はないはずですので、一般的なロジックのテストはEdit Modeで、特別に実機でも動作させたいテスト*3のみPlay Modeで書くことをおすすめします。

ビルドターゲットを"Android"に切り替えた状態でTest RunnerウィンドウのPlayModeタブを開くと、右上に "Run all in player(Android)" と書かれたボタンが表示されます。 Android端末をUSB接続した状態でこのボタンをクリックすると、すべてのPlay ModeテストがAndroid端末上で実行されます*4

f:id:nowsprinting:20191001091335p:plain

コマンドライン

コマンドラインからのテスト実行では、引数-testPlatformに(playmodeの代わりに)実行するBuildTarget文字列を指定することで実行できます。

特定プラットフォームでのみ実行されるテスト

「このテストコードは特定のプラットフォームでのみ実行したい」というケースがあるはずです。 その場合、テストメソッドに[UnityPlatform()] アトリビュートを付与し、引数にRuntimePlatformを指定できます。

下例の場合、Test RunnerウィンドウではPlay Modeで”Run all in player(Android)”をクリックしたときのみ、コマンドラインでは引数に-testPlatform Androidを指定したときのみ実行されます。

/// <summary>
/// Android playerでのみ実行されるテスト
/// </summary>
[Test]
[UnityPlatform(RuntimePlatform.Android)]
public void RunOnlyAndroid()
{
    var platform = Application.platform;
    Assert.That(platform, Is.EqualTo(RuntimePlatform.Android));
}

なお、[UnityPlatform]アトリビュートに指定するのは、RuntimePlatformです。 コマンドライン引数-testPlatformに指定するBuildTargetとは文字列が異なるものもありますので注意してください。

iOS Playerの場合

今回Androidを例にしました。iOSの場合、例の如くXcodeプロジェクトが生成されてXcodeが起動します。このときiOS端末がUSB接続されていれば、そのまま自動でインストール・実行されます。

ただし、iOS端末は開発機としてUDIDが登録されているもので、Unityプロジェクト側にTeam IDが設定されている必要があります(要するに普通にXcodeでアプリをBuild and Runできるようにしておく必要があります)。 [1/14追記]

*1:スライドp.34には「Player(実機)」とだけ書いてありましたが特に触れなかった模様

*2:Play Mode testsが遅いだけでなく、実機で動作させるためのビルドが行われます

*3:ネイティブプラグインのほか、パフォーマンス計測など

*4:以前はUnityエディタを起動しているPCとAndroid端末が同じLAN(セグメント)に接続されていなければテスト実行結果がTest Runnerウィンドウに反映されなかったはずですが、Unity 2018.4ではUSB接続だけで反映されました

Unite Tokyo 2019『Unity Test Runnerを活用して内部品質を向上しよう』のフォローアップ #UniteTokyo

9/25, 26に開催されたUnite Tokyo 2019 Day 2に『Unity Test Runnerを活用して内部品質を向上しよう』というタイトルで登壇させていただきました。

スライドはすでにUnity Learning Materialsで公開中。動画は後日公開される予定です。

learning.unity3d.jp togetter.com

以下、説明が足りなかったところ、質疑応答やTwitterでコメントいただいた点など補足していきます。

CEDEC 2019『組織にテストを書く文化を根付かせる戦略と戦術』 (p.6)

いきなり、TDD(テスト駆動開発)の大家、@t_wadaさんによるCEDEC 2019でのセッションを紹介しました。 私はUnity製ゲームに特化した話をしましたが、そのベースとなる、より一般的な視点での開発者テストについて語られています。 ぜひ併せて読んでいただくことをおすすめします。

cedil.cesa.or.jp

当日「すでに見た」という方に挙手いただきましたが、2割いないくらいで驚きました。こちらを見てテストに興味を持って来る方が大多数だと思っていたので、その前段階なしでテストのセッションに興味を持ってたくさん来ていただいたのは良い意味で予想外でした。

Unity Test Framework (p.33)

Unity 2019.2からUnity Test Runnerがpackage化されたことに触れましたが、それにまつわる変更についてコメントいただきましたので確認して別記事にまとめました。

www.nowsprinting.com

Player(実機)でのテスト実行 (p.34)

実機でのテスト実行についてセッションで触れなかったので、別記事にまとめました【10.2追記】

www.nowsprinting.com

インテグレーションテスト (p.52)

スライドで紹介した、Sceneベースのテストフレームワークはこちら。

github.com gitlab.com

AltUnityTesterについては、以前Gotanda.unityでお話したスライドも参考にしてください。

www.slideshare.net

インライン化 (p.65)

これはきちんと検証できていないので情報のみですが、インライン化してほしいメソッドに [MethodImpl(MethodImplOptions.AggressiveInlining)] アノテーションをつけることで積極的なインライン化を指示できるはずです。

ただし、Unityエディタ上では無効、MonoおよびIL2CPPでは有効なようです。

このあたり情報源はForumのこのスレッドを読んだだけなので、追って検証していくつもりです。

検証しました。次の記事を参照してください。 [2021/12/16追記] www.nowsprinting.com

AllocatingGCMemory (p.68)

Unity 2018.3で追加されたAPIです。ドキュメントはこちら。

Class AllocatingGCMemoryConstraint | Test Framework | 1.1.30

使用例はこんな感じ。下はsut.UsePrimitive()の中でGCされるメモリ(ヒープ)を確保していたら(Is.Notなので)failするテストです。

[Test]
public void UsePrimitive_isNotAllocatingGCMemory()
{
    Assert.That(() => sut.UsePrimitive(), Is.Not.AllocatingGCMemory());
}

AllocatingGCMemoryについては、お伝え忘れていた重要なトピックがあります。対象のメソッド内(上例ではUsePrimitive())でDebug.Log()を使用していると、その中でメモリ確保が行われるためfailしてしまいます。

性能を要求されるメソッド内でDebug.Log()を使うことは無いとは思うのですが、ご注意ください。

依存オブジェクト (p.70)

依存オブジェクトを持つコンポーネントのテストを行なうためのパターンとして、「Dependency Injectionパターン」や「Test Doubleパターン」があります。

そのパターンを踏まえて、少ないコードで実現させるフレームワークが存在します。確かに便利なのですが、ツール・フレームワークに振り回されることがないように、基本を知っておくことは大事です。

スライドでもご紹介した『xUnit Test Patterns』、Kindle版がセール中のようです。この機会に買って積んでみてはいかがでしょうか。

テストダブル (p.71)

Test Doubleパターンについては、@goyokiさんのこちらの記事が参考になります。

goyoki.hatenablog.com

もしくは拙著『iOSアプリテスト自動化入門』(絶版)がお手元にあれば、「2.3.5 テストダブル」を参照してください。

YAGNI (p.77)

Wikipediaさんにも載っているYAGNI*1。"You ain't gonna need it"の略で、今必要ないものは考えない・実装しない、という意味で使います。技術者なら言いたいセリフ「こんなこともあろうかと」とは対極にある言葉です。

ja.wikipedia.org

シンプルに「今は必要ないから考慮しない」という意味でも使えますが、テストコードがあることによって後々の仕様変更のコストとリスクが減るために取れる選択肢でもあります。

また、これはセッションでは取り上げなかったのですが、XPやアジャイル開発の文脈で言われる「ドキュメントは書かない」も、本来はテストコードがドキュメントの役割をなす "Test as Documentation" が前提だったりします。

境界値を攻めすぎない (p.80)

前提となる「境界値テスト」の話を端折ってしまったので補足します。

例えば、HPゲージが通常はグリーン、HP 50%以下はイエロー、HP 20%以下はレッド、という色を返すメソッドを例にします。

public static Color GaugeColor(int hp, int maxHp)
{
    var percent = hp / maxHp;
    if (percent <= 20)
    {
        return Color.red;
    }
    if (percent <= 50)
    {
        return Color.yellow;
    }
    return Color.green;
}

このとき、結果が分岐する条件となる入力値である「0〜20%」「21〜50%」「51〜100%」はテスト用語で「同値クラス」と呼ばれます。 そして同値クラス同士の隣接した値、ここでは 20, 21, 50, 51 が「境界値」です。

境界値にはバグが発生しやすいので*2、通常のテストではよく境界値のテストを実施します。しかしゲームの世界では、「やっぱりHP 30%で赤にしよう」といった変更もあるのではないでしょうか。

同じ境界値でも、「HPが0になったら死ぬ」といった境界値は厳密にテストしていいのですが、HPゲージの見た目であれば「10%」「40%」「80%」くらいのゆるい値でテストしておけば、最低限色が変わることは保証できますし、しきい値が調整されてもテストコードを修正する手間もありません。

つまり、境界値を厳密に評価する必要があるテストなのかどうか、という「出力」の見極めが大事ということです。

なお、上例では、引数がhp > maxHpmaxHp=0で呼ばれる可能性を考慮していません。テストを書く過程でこうしたことに気付けるケースもよくあります。

テストコードの構造化 (p.82)

@goyokiさんのスライドが参考になります。

www.slideshare.net

ただし、過度の構造化によってテストコードの可読性が損なわれたり、プロダクトコード側にテストのためのコードが紛れ込んでしまうアンチパターンもありますので注意が必要です。

あくまでも目的は、テストコードが壊れにくくなる、堅牢性 (robustness) のための構造化です。

質疑応答

講演後の質疑応答には10名ほど来てくださり、30分ほどQ&Aさせていただきました。以下、覚えている範囲で*3

Unity Test Runner以外のテストツール・フレームワークは使っていないのか?(Miyamasuとか)

  • ユニットテストとしてはEdit mode testsに絞っているので、Unity Test Runnerのみ
  • もう少し上層の(結合度の)テストは、ツールから分けている

MonoBehaviourのテストをどうしているか(Play mode testsでしかできないのか)

  • MonoBehaviourのテストであっても、Edit mode testsでのテストは可能
  • ただし、責務が分離されていないとテストしづらいのはお話した通り。コンポーネントごとの分離も必要だし、MonoBehaviourと、個々の処理を分離することも必要。例えば、Update()にすべて書くのではなくメソッドを分けていく
  • テスタビリティを上げるためのデザインパターンとしてHumble Object Patternが知られています。これも『xUnit Test Patterns』に書かれています

Humble Object Patternについては、@adarapataさんのスライドも参考になります。

www.slideshare.net

静的解析ツールはあるのか

  • JetBrainsさんが "ReSharper Command Line Tools" を提供しています。インスペクション、重複コードの検出、コードクリーンナップをコマンドラインから実行できます
  • 実行にUnityエディタライセンスもReSharperライセンスも不要ですが、WIndows版のみ

www.jetbrains.com

所感

テストのセッションということでどのくらい来ていただけるか不安でしたが、400人部屋の8割くらい埋まっていたように見えました。ありがとうございました。

セッションのほうは、後半急ぎ足になってしまい反省しています。これでも直前になっていくつかトピックを削ったりTipsにまわしたりしたのですが…。

なお、壇上から客席まで距離があり、かつ照明の関係で暗く、客席の反応がほとんどわからなかったので戸惑いました。冒頭で笑いを取ってペースを掴むのが常套手段なのですが、ウケているのかどうかわからないのはつらかったです。

Unite Tokyo 2019全体について。皆さんTwitter等で書かれていますが、とても素晴らしい会場とホスピタリティで、たいへん満足度の高いカンファレンスでした。スピーカー特典で利用できたVIPルームおよびVIP席もものすごく快適で、来年は登壇しなくてもVIPチケットは確保しようと心に決めました。

最後に。今回のUniteのセッション公募、気づいたのは締め切り4.5h前でした。@nkjzmさんに感謝。

参考文献

*1:読みは「ヤグニ」でいいはず。みんなそう言ってるので…

*2:実装以前に、仕様書の段階で「以下」と「未満」があいまいであったり矛盾があったりもありがちなバグです

*3:こんな質問もしたよ!というのがあればTwitter等で教えて下さい