やらなイカ?

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

Unity製ゲームをWebGLビルドしてGitHub Pagesに公開するワークフロー

Unityプロジェクトのバージョン管理にGitHubを使用している場合、GitHub ActionsワークフローでWebGLビルドを行ない、そのままGitHub Pagesに公開する方法を紹介します。

GitHub Pagesは、GitHubリポジトリに紐づく静的コンテンツをホスティングできる機能です。 公開できるサイズが10GB以下ということと、たとえprivateリポジトリであってもGitHub Pagesにはアクセス制限はかけらない*1という制限がありますので注意してください。

Unity - Builder アクション

ビルドには、GameCIの提供するUnity - Builder アクションを使用しています。 利用方法は公式サイトか、検索すれば日本語情報もありますので割愛します。

github.com

なお、CIをキックするユーザーはUnityのライセンスを持っている必要があります*2。publicなリポジトリで使用する場合は特に注意してください*3

また、現在パーソナルライセンスのCLIによる新規アクティベーションは塞がれています。次のIssueを参照してください。

alf->ulf license activation no longer possible for personal licenses · Issue #408 · game-ci/documentation · GitHub

GitHub Pages

GitHub Pagesで公開するコンテンツは、リポジトリの特定ブランチにあらかじめチェックインするか、GitHub Actionsによってアーティファクトにアップロードしたものを使用できます。

後者であれば、リポジトリにビルド成果物をチェックインする必要がなく便利です。 本例ではこの方法を紹介します。

まず、GitHubリポジトリSettings > Pagesを開き、SourceはGitHub Actionsを選択します。

すると、リポジトリのEnvironmentsにgithub-pagesが追加されます。 あとはワークフローで、WebGLビルド出力をtarで固めてgzipしたものをgithub-pagesという名前でアーティファクトにアップロードすることで、動作するゲームが https://OWNER.github.io/REPO/ で公開されます。

なお、GitHub Pagesで公開するWebGLは、Compression FormatをDisabledに設定しなければなりません。公開は行われますが実行時に次のエラーが出ます。

Unable to parse Build/WebGL.framework.js.gz! This can happen if build compression was enabled but web server hosting the content was misconfigured to not serve the file with HTTP Response Header "Content-Encoding: gzip" present. Check browser Console and Devtools Network tab to debug.

しかし、ゲームをunityroomで公開する場合、Compression FormatはGzipに設定する必要があります。 これを手動で切り替えるのは事故の元ですので、ワークフロー内でビルド前に書き換えています。

詳しくは、下記実装例を参照してください。

ワークフロー実装例

次のワークフローをリポジトリの.github/workflows下に置くことで、masterブランチにpush(もしくはPRをマージ)されるたびにWebGLビルドが実行され、GitHub Pagesで公開されます。

name: Deploy to GitHub Pages

on:
  push:
    branches:
      - master
  # masterブランチにpushされるたびにWebGLビルドして公開。条件はプロジェクトのニーズによって調整してください

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
  # 先行ジョブがあればキャンセル

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      - uses: actions/checkout@v4

      - name: Set CompressionFormat to Disabled
        run: |
          sed -i -e 's/webGLCompressionFormat: ./webGLCompressionFormat: 2/' ProjectSettings/ProjectSettings.asset
        # Compression Formatを`Disabled`に書き換え

      - uses: game-ci/unity-builder@v3
        with:
          targetPlatform: WebGL
          allowDirtyBuild: true # 上でProjectSettings.assetを変更しているため指定
        env:
          UNITY_LICENSE: ${{ secrets[UNITY_LICENSE_2022] }}

      - uses: actions/upload-pages-artifact@v2
        with:
          path: build/WebGL/WebGL
        # WebGLビルド出力をアーティファクトにアップロード

  deploy:
    runs-on: ubuntu-latest
    needs: build
    permissions:
      id-token: write
      pages: write
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}

    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v2
        # GitHub Pagesに公開

*1:GitHub Enterprise契約であればできます

*2:Proライセンスが必要なプロジェクトであれば全員Proライセンスが必要です

*3:public forkからのPull Requestの実行を抑止することで不特定ユーザーによるキックを防ぐことはできます。ただしこれもUnity社のお墨付きというわけではないので保証の限りではありません

#C102 ありがとうございました

コミックマーケット102、無事終わりました。 ご購入いただいた方々、また、スペースにお立ち寄りいただいた方々、ありがとうございました。

頒布した書籍の詳細・フォローアップは次の記事を参照してください。

www.nowsprinting.com

www.nowsprinting.com

いずれも、BOOTHで電子版および物理本を頒布しています。買いそびれた方はご利用ください。

ikagoya.booth.pm

またTAROMAN本はメロンブックスさんにも委託あります。 https://www.melonbooks.co.jp/detail/detail.php?product_id=2037143

今回、強気で多めに刷ったので、だいぶ在庫あります。 強気の分だけ丸々残っている感。 Unity本などと比べて情報が風化しにくいはずなので、しばらく既刊として持っていくつもりです。

ところで、今回はポスターも用意しましたが、やっぱり縦に使うべきだったかな、という反省。

テスト自動化で大切なことはTAROMANが教えてくれた

テスト自動化のノウハウ・ベストプラクティスを岡本太郎の言葉で紐解く、そんな同人誌をコミックマーケット102の2日目(日曜)西お40b「いか小屋」で頒布します。

想定読者

  • テスト自動化エンジニア及びSET
  • 自動テストの導入を検討しているプロジェクトのオーナー、マネージャー、 QA 担当者(主に第1章「テスト戦略編」)
  • ソフトウェアエンジニア、プログラマ(主に第2章「テスト実装編」)

目次の紹介

各章の内容は次のとおりです。

第1章 テスト戦略編

『TAROMAN』各話タイトルとなっているものを中心に、主にテスト自動化に取り組む際の戦略・計画に役立つ岡本太郎氏の言葉を紹介しています。

  • でたらめをやってごらん
  • 自分の歌を歌えばいいんだよ
  • 一度死んだ人間になれ
  • 同じことをくりかえすくらいなら、死んでしまえ
  • 人生は他人を負かすためにあるのではない
  • 目的を捨ててごらん

第2章 テスト実装編

『TAROMAN』各話タイトルとなっているものを中心に、主に自動テストを実装する際に役立つ岡本太郎氏の言葉を紹介しています。

  • 真剣に、命がけで遊べ
  • マイナスに飛び込め
  • 美ってものは、見方次第なんだよ
  • 捨てる主義のすすめ
  • 好かれるヤツほどダメになる
  • 孤独こそ人間が強烈に生きるバネだ
  • なま身の自分に賭ける
  • 芸術は爆発だ

なお、1・2章で、2022年に再放送された『TAROMAN』全10話のタイトルを網羅しています*1。 普段テスト自動化に携わっている方なら7-8割方は何を書いているか予測がつくと思いますが、さすがに苦しいこじつけもあります。ゆるして…

第3章 「タローマンと 3 つのちかい」と「テスト自動化の 8 原則」

テスト自動化の8原則のベースとなったとされる「タローマンと3つのちかい」。両者の関連を解説しています。

  • うまくあるな
  • きれいであるな
  • ここちよくあるな

付録A オープンソース開発で大切なことも岡本太郎が教えてくれた

『TAROMAN』とは関係ない岡本太郎の言葉の中から、オープンソース開発につながる言葉を紹介しています。

付録B 真実の「メインフレーム時代の自動テスト」

本書は「岡本太郎はテスト自動化エバンジェリストだった」というテイで書かれています。 『TAROMAN』の放映された1970年代はメインフレームの時代ですが、実際にメインフレームのプロダクト開発で行われていた*2テスト自動化について簡単に紹介しています。

表紙について

ヤサカナエさん(サークル「あまどや」さん)にお願いしました。 色々アイデア出していただいてありがたかったです。最終的に「勢いのあるやつ」に。

スペース

2日目(日曜)西お40b「いか小屋」でお待ちしております。 西2手前側の入り口が最寄り。

技術書典14新刊『Unity Test Framework完全攻略ガイド 統合テスト編』の在庫も持っていきます。

www.nowsprinting.com

信販売・電子版について

C102後、BOOTHおよびメロンブックスさんに委託予定です。 二次創作なので技術書典およびKDPには出しません。

メロンブックスさん予約はじまっています → https://www.melonbooks.co.jp/detail/detail.php?product_id=2037143

BOOTHでも頒布開始しました [8/14]

ikagoya.booth.pm

参考

*1:入稿後にNHKで『捨てる主義のすすめ』が復刻再放送されたようですが、子供の頃に見たテイで書いています

*2:1970年代ではなく1990年代の話ですが

Unityバイブル R5夏号

8月29日に発売される『Unityバイブル R5夏号』の予約受付中です。Amazonに書影も出ました。

鈍器とか質量兵器とか言われた『Unityゲーム プログラミング・バイブル 2nd Generation』とは異なり、1冊のボリュームを抑えて年2冊発行されるようになったそうです。

掲載されているのは次の10トピックです。

【特集記事】

  • 高品質なグラフィックスを表現するためのUniversal RPの各種機能の解説
  • Shader Graphの基本操作から発展的なテクニックまで
  • Timelineを利用してリッチな演出を作成する手順や考え方
  • Photon Fusionによるリアルタイムネットワークゲーム
  • Unity Localizationを利用したシンプルな多言語化

【一般記事】

  • ゲームプレイの自動テスト
  • Unity開発を効率的にする.NET向けIDE「JetBrains Rider」の活用
  • Editor拡張で作業効率を上げよう
  • すぐに使えるゲームサウンド演出
  • VRアプリケーションにおけるVRMアバターの導入

このうち「ゲームプレイの自動テスト」のセクションを執筆させていただきました。商業出版も共著も、実に10年ぶりでした。

ゲームプレイの自動テスト

扱っている範囲は同人誌『Unity Test Framework完全攻略ガイド 統合テスト編』と同じく統合テスト中心ですが、同人誌では統合テストの手法について広く書いているのに対し、本書は実際に動作するゲームに対してテストを書いていく、より実践的な内容となっています*1

サンプルゲームはローグライクのダンジョン探索ゲームです。 あえて*2無計画に作りはじめて、テストがあればいくら変更しても大丈夫とばかり、機能追加、仕様変更、リファクタリングを何度も重ねた過程がコミットログから読みとれるはずです。 プロジェクトは本書発売に合わせて公開予定です。

本文では、主に次の内容を紹介しています。

  • ダンジョン自動生成ロジックのテスト
    • マップ生成のテスト
    • 3D要素配置のテスト
  • インゲームのテスト
    • InputSystem.TestFrameworkを使用したテスト実装
    • インゲームのモンキーテスト
    • インゲームのシナリオテスト(パッド/キー操作のキャプチャ/プレイバック)
  • アウトゲームのテスト
    • UI要素を操作するテスト
    • アウトゲームのモンキーテスト
    • アウトゲームのシナリオテスト(Automated QAパッケージによるキャプチャ/プレイバック)

ぜひご予約の上、発売をお待ち下さい!*3

物理本のほか、ボーンデジタル オンラインブックストアでPDF版を購入できます。 [8/22]

www.borndigital.co.jp

サンプルプロジェクト

サンプルプロジェクトを公開しました [8/22]

github.com

関連

www.nowsprinting.com

www.nowsprinting.com

www.nowsprinting.com

*1:実践的な反面、網羅性はなくなっています。ぜひ『Unity Test Framework完全攻略ガイド 統合テスト編』と合わせてお読みください

*2:本当ですよ?

*3:CEDEC2023で先行販売があるそうです

PlayModeWindowでGameビューの解像度を指定する

PlayModeWindowは、Unity 2022.2で追加されたクラスです。 従来、UnityエディターのGameビューをスクリプトから操作するにはリフレクションによる非公開APIの使用が必要でした。 Unity 2022.2からは、PlayModeWindowクラスの静的メソッドで操作できます。

PlayModeWindowクラスは、PlayModeViewクラス*1を制御する機能を持ち、GameビューとSimulatorビューを切り替えたり、解像度を変更するAPIが提供されています。

docs.unity3d.com

Gameビューへの切り替え

解像度の指定は、SimulatorビューではなくGameビュー表示である必要があります。 次のように切り替えます。

PlayModeWindow.SetViewType(PlayModeWindow.PlayModeViewTypes.GameView);

引数には、GameViewもしくはSimulatorViewを指定できます。

解像度の指定

解像度はSetCustomRenderingResolutionメソッドで変更できます。 Full HD(1920×1080)に変更する場合、次のように指定します。

PlayModeWindow.SetCustomRenderingResolution(1920, 1080, "Full HD");

テスト実行時の解像度を固定する方法1(ICallbacks)

たとえば、すべてのテストで解像度をFull HD(1920×1080)に固定したければ、ICallbacksを使用して次のように実装します。

public class OpenGameViewAtRunStarted : ICallbacks
{
  [InitializeOnLoadMethod]
  private static void SetupTestCallbacks()
  {
    var api = ScriptableObject.CreateInstance<TestRunnerApi>();
    api.RegisterCallbacks(new OpenGameViewAtRunStarted());
  }

  public void RunStarted(ITestAdaptor testsToRun)
  {
    PlayModeWindow.SetViewType(PlayModeWindow.PlayModeViewTypes.GameView);
    PlayModeWindow.SetCustomRenderingResolution(1920, 1080, "Full HD");
  }

  // snip
}

テスト実行時の解像度を固定する方法2(GameViewResolution属性)

テスト実行時に解像度指定する場合は、Test Helperパッケージに含まれるGameViewResolution属性が便利です*2

この属性はテストアセンブリ・クラス・メソッドいずれかに付けることができ、どこにつけても各テストメソッドの実行前(SetUpの前)に処理されます。

すべてのテストで同じ解像度でよければ、次のようにテストアセンブリに付与します*3

[assembly: GameViewResolution(1920, 1080, "Full HD")]

テストごとに個別に指定したいときには、次のようにテストクラスやメソッドに付与できます。

[TestFixture]
public class MyTestClass
{
  [UnityTest]
  [GameViewResolution(1920, 1080, "Full HD")]
  public IEnumerator MyTestMethod()
  {
    // test
  }
}

Test Helperパッケージは、Unity 2019.4以降で利用できます。 Unity 2022.2未満のときはリフレクションによる非公開APIを使用していますので、自分で実装するときの参考にもなるはずです。

github.com

補足

本記事は、拙著『Unity Test Framework完全攻略ガイド 統合テスト編』の第5章「ビジュアルリグレッションテスト」からの抜粋です。

www.nowsprinting.com

テストの基本から知りたい! という方は、『Unity Test Framework完全攻略ガイド 第2版』からお読みください!

www.nowsprinting.com

*1:GameViewクラスおよび、旧Device SimulatorパッケージのSimulatorWindowクラスの親クラス。Device SimulatorがUnity 2021.1からビルトインされて変更されましたが、概念としては変わらず2つのビューの抽象

*2:この属性は、Unity 2022.2未満ではリフレクションで非公開APIを使用して動作します

*3:Play Modeテストアセンブリが複数あるプロジェクトであれば、アセンブリごとに指定が必要です

バッチモードでUnityを実行するときの制限事項と回避方法

本記事は、拙著『Unity Test Framework完全攻略ガイド 統合テスト編』の付録Bから抜粋したものです。

バッチモードとは

バッチモードとは、Unityエディターをコマンドラインから起動するときに -batchmode オプションを付けることでヘッドレス動作するモードです。 ウィンドウモード*1のUnityエディターは実行中さまざまな、人間が応答しなければならないポップアップウィンドウが表示されますが、バッチモードでは表示されません。そのため、CIでテスト実行するときなどに使用されます。

バッチモードの制限事項

本記事執筆時点で判明している、バッチモード実行時の制限事項は次のとおりです。

  • スクリーンサイズは640×480
  • WaitForEndOfFrame を使用できない*2
  • InputSystem.TestFramework を長時間(数十秒)動作させたとき、途中で操作が止まってしまう
  • UnityEngine.InputSystem.LowLevel.InputEventTrace を使用できない
  • -testPlatform オプションでスタンドアロンプレイヤーを指定したとき、バッチモードでなく常にウィンドウモードで起動する

制限事項の回避方法1

バッチモード実行中であっても、EditorWindow.GetWindow() メソッドでUnityエディターのGameビューを開くことで前述の制限を回避できます。

ヘッドレスとは言ったがウィンドウを表示できないとは言っていない

とのこと。

次のコードは、テスト実行前にGameビューを開く ICallbacks の実装例です。

public class OpenGameViewAtRunStarted : ICallbacks
{
  [InitializeOnLoadMethod]
  private static void SetupTestCallbacks()
  {
    var api = ScriptableObject.CreateInstance<TestRunnerApi>();
    api.RegisterCallbacks(new OpenGameViewAtRunStarted());
  }

  public void RunStarted(ITestAdaptor testsToRun)
  {
    var assembly = Assembly.Load("UnityEditor.dll");
    var viewClass = Application.isBatchMode
        ? "UnityEditor.GameView"
        : "UnityEditor.PlayModeView";
    var gameView = assembly.GetType(viewClass);
    EditorWindow.GetWindow(gameView, false, null, true);
  }

  // snip
}

GameView および親クラスである PlayModeView は可視性が internal のため、リフレクションを使用しています。そのため、今後Unityエディターの内部実装変更によって動作しなくなる恐れがあります。

ただし、グラフィックボード・ビデオカードを搭載していないマシン、もしくは -nographics オプションを指定しているときには、EditorWindow.GetWindow() メソッドは機能しません。 エラーにはなりませんがウィンドウも開きません。

なお、当然ですが本当にGameビューが開きます。開発に使用しているPCで動作させたとき、フォーカスを持っていかれたり、そのままキーボード操作がテストに干渉する恐れがありますのでご注意ください。

制限事項の回避方法2

下記リポジトリで公開しているTest Helperパッケージに含まれる FocusGameView 属性も同様の実装をしています。 したがって、この属性をテストアセンブリ・クラス・メソッドいずれかに付けるだけでバッチモードの制限事項を回避できます。

また、Gameビューの解像度を指定する GameViewResolution 属性も同じ処理を含みますので、こちらでも回避できます。

github.com

まとめ

いかがでしたでしょうか?(構文)

この記事が役にたった! という方は、ぜひ『Unity Test Framework完全攻略ガイド 統合テスト編』をお買い求めください!

www.nowsprinting.com

テストの基本から知りたい! という方は、『Unity Test Framework完全攻略ガイド 第2版』からお読みください!

www.nowsprinting.com

*1:便宜上、通常のGUIで動作するUnityエディターを指します。公式の名称ではありません

*2:https://docs.unity3d.com/Manual/CLIBatchmodeCoroutines.html

疾走するめ

当ブログおよびサークル「いか小屋」のアイコンをリニューアルしました!

題して「疾走するめ(dashing surume)」。

デザインおよび一枚絵は『わかるイカ』の、あんまりひどい(@hidoianmari)さんにお願いしました。 さすがのイカリテラシーで、こだわり*1の詰まった一枚に仕上げていただきました。

ちなみに『わかるイカ』最高なので、全人類・頭足類に読んでほしい。

昨年末、某有名画家の展覧会で某作品を生で見て、この「疾走するめ」を着想したときはまさに「ユリイカ!」でした。

なお、Twitterなど個人アイコンは変更なしです。 以前から、アウトプットは出した時点で止まったものだと思っていて*2、サークルのアイコンはするめのシルエットを使っていました。

最近読んだ本に次の一節があり、まさに我が意を得たり、といったところ。

自分から出た瞬間に、作品はすでに他者。
それはぼくにとって、もはや道ばたの石っころと何も変わらない。

そう、岡本太郎もいっていた*3

*1:腹開きで背側が正面になっていたり、吸盤の付き方だったり

*2:そうは言っても過去記事はできるだけ更新したり、同人誌は改版したりはしていますが

*3:『壁を破る言葉』(岡本太郎, イースト・プレス, 2005)