Skip to content

Latest commit

 

History

History
595 lines (360 loc) · 31.7 KB

README_ja.md

File metadata and controls

595 lines (360 loc) · 31.7 KB

Anjin

Meta file check openupm

Unity製ゲームのオートパイロットツールです。 次の2つの要素で構成されています。

  1. ゲーム中にロードされたSceneに応じて、対応するAgentを起動するディスパッチャ
  2. Sceneに閉じた自動実行を実現するAgent

Agentとは、UI操作のプレイバックやモンキーテストなど、特定の操作を実行する小さく切り分けられたC#スクリプトです。 ビルトインで提供しているもののほか、ゲームタイトル固有のものを実装して使用できます。

Click English for English page if you need.

インストール方法

主に2通りの方法でインストールできます。

Package Manager ウィンドウを使用する場合

  1. Project Settings ウィンドウ(Editor > Project Settings)にある、Package Manager タブを開きます
  2. Scoped Registries の下にある + ボタンをクリックし、次の項目を設定します(図 1)
    1. Name: package.openupm.com
    2. URL: https://package.openupm.com
    3. Scope(s): com.dena, com.cysharp, and com.nowsprinting
  3. Package Managerウィンドウを開き(Window > Package Manager)、レジストリ選択ドロップダウンで My Registries を選択します(図 2)
  4. com.dena.anjin パッケージの Install ボタンをクリックします

図 1. Project Settings ウィンドウの Package Manager タブ

図 2. Package Manager ウィンドウのレジストリ選択ドロップダウン

Note

scopesに com.cysharpcom.nowsprinting を忘れず追加してください。Anjin内で使用しています。

Note

Anjinパッケージ内のテストを実行する場合(package.jsonの testables に追加するとき)は、Unity Test Framework パッケージ v1.3以上が必要です。

openupm-cli を使用する場合

openupm-cli がインストールされている状態で、ターミナルから次のコマンドを実行します。

openupm add com.dena.anjin

Assembly Definition FileのDefine Constraintsに UNITY_INCLUDE_TESTS || DENA_AUTOPILOT_ENABLE が設定されていますので、原則リリースビルドからは除外されます。

推奨.gitignore

Anjinを起動すると、次のファイルが自動生成されます。 トラッキングする必要はありませんので、プロジェクトの.gitignoreファイルに追加することを推奨します。

/Assets/AutopilotState.asset*

ゲームタイトルごとの設定

ゲームタイトルのプロジェクトにUPMパッケージをインストール後、以下の設定・実装を行います。

  • AutopilotSettings.assetファイルを生成、設定
  • 使用するAgentの.assetファイルを生成・設定
  • 必要に応じて専用Agentの実装
  • 必要に応じて初期化処理の実装

Note

ゲームタイトル固有のオートパイロット向けコードは、属するAssembly Definition FileのDefine Constraintsに UNITY_INCLUDE_TESTS || DENA_AUTOPILOT_ENABLE を設定することで、リリースビルドから除外できます

オートパイロット設定ファイル(.asset)の生成

UnityエディタのProjectウィンドウで右クリックしてコンテキストメニューを開き、 Create > Anjin > Autopilot Settings を選択すると生成できます。 ファイル名は任意で、プロジェクト内に複数作成して使い分けできます。

大きく3つの設定項目があります。

Agent割り当て設定

Scene Agent MappingとフォールバックAgent

Sceneごとに自動実行を行なうAgent設定ファイル(.asset)の対応付けを設定します。

リストになっていますので、SceneAgent の組み合わせを設定してください。並び順は動作に影響しません。 リストに存在しないSceneでは、Fallback Agentに設定されたAgentが使用されます。

たとえば全てのSceneで UGUIMonkeyAgent が動くようにしたければ、Scene Agent Maps は空に、 Fallback Agent には UGUIMonkeyAgent の.assetファイルを設定します。

オブザーバーAgent

Scene Agent MapsFallback Agentとは独立して、常に並列に起動されるAgentを設定します。 v1.0.0時点では EmergencyExitAgent の使用を想定しています。 複数のAgentを並列起動する必要があるときは ParallelCompositeAgent を使用してください。

なお、ここに設定されたAgentは DontDestroyOnLoad ではなく、新しいSceneがロードされる度に破棄・生成される点に注意してください。

オートパイロット実行設定

この項目は、コマンドラインから上書きもできます(後述)。

Lifespan
実行時間上限を秒で指定します。デフォルトは300秒、0を指定すると無制限に動作します
Random Seed
疑似乱数発生器に与えるシードを固定したいときに指定します(省略可)。なお、これはオートパイロットの使用する疑似乱数発生器に関する設定であり、ゲーム本体の疑似乱数発生器シードを固定するにはタイトル側での実装が必要です。
Time Scale
Time.timeScaleを指定します。デフォルトは1.0
JUnit Report Path
JUnit形式のレポートファイル出力パスを指定します(省略可)。オートパイロット実行の成否は、Unityエディターの終了コードでなくこのファイルを見て判断するのが確実です。errors, failuresともに0件であれば正常終了と判断できます。
Logger
オートパイロットが使用するロガー指定します。省略時は Debug.unityLogger がデフォルトとして使用されます
Reporter
対象のアプリケーションで発生したエラーを通知するレポータを指定します

エラーハンドリング設定

異常系ログメッセージを捕捉してレポータで通知するフィルタを設定します。

handle Exception
例外を検知したらレポータで通知します
handle Error
エラーを検知したらレポータで通知します
handle Assert
アサート違反を検知したらレポータで通知します
handle Warning
警告を検知したらレポータで通知します
Ignore Messages
ここに設定した文字列を含むメッセージはレポータで通知しません

Agent設定ファイル(.asset)の生成

ビルトインのAgentを使用する場合でも、タイトル独自Agentを実装した場合でも、Unityエディタでそのインスタンス(.assetファイル)を生成する必要があります。

インスタンスは、UnityエディタのProjectウィンドウで右クリックしてコンテキストメニューを開き、 Create > Anjin > Agent名 を選択すると生成できます。ファイル名は任意です。

生成したファイルを選択すると、インスペクタにAgent固有の設定項目が表示され、カスタマイズが可能です。 同じAgentでも設定の違うものを複数用意して、Sceneによって使い分けることができます。

ロガー設定ファイル(.asset)の生成

ロガーインスタンスは、UnityエディタのProjectウィンドウで右クリックしてコンテキストメニューを開き、 Create > Anjin > Logger名 を選択すると生成できます。ファイル名は任意です。

生成したファイルを選択すると、インスペクタにロガー固有の設定項目が表示され、カスタマイズが可能です。 同じロガーでも設定の違うものを複数用意して使い分けることができます。

レポータ設定ファイル(.asset)の生成

レポータインスタンスは、UnityエディタのProjectウィンドウで右クリックしてコンテキストメニューを開き、 Create > Anjin > Reporter名 を選択すると生成できます。ファイル名は任意です。

生成したファイルを選択すると、インスペクタにレポータ固有の設定項目が表示され、カスタマイズが可能です。 同じレポータでも設定の違うものを複数用意して使い分けることができます。

実行方法

次の2通りの方法でオートパイロットを実行できます。

1. Unityエディタ (GUI) の再生モードから実行

実行したい設定ファイル(AutopilotSettings)をインスペクタで開き、実行ボタンをクリックするとオートパイロットが有効な状態で再生モードに入ります。 設定された実行時間が経過するか、通常の再生モードと同じく再生ボタンクリックで停止します。

2. Play Modeテストから実行

非同期メソッド LauncherFromTest.AutopilotAsync(string) を使用することで、テストコード内でオートパイロットが動作します。 引数には AutopilotSettings ファイルパスを指定します。

[Test]
public async Task LaunchAutopilotFromTest()
{
  await LauncherFromTest.AutopilotAsync("Assets/Path/To/AutopilotSettings.asset");
}

Note

実行中にエラーを検知すると LogError が出力されるため、そのテストは失敗と判定されます。

Warning

テストのデフォルトタイムアウトは3分です。オートパイロットの実行時間が3分を超える場合は Timeout 属性でタイムアウト時間を指定してください。

3. コマンドラインから実行

コマンドラインから実行する場合、以下の引数を指定します。

$(UNITY) \
  -projectPath $(PROJECT_HOME) \
  -batchmode \
  -executeMethod DeNA.Anjin.Editor.Commandline.Bootstrap \
  -AUTOPILOT_SETTINGS Assets/Path/To/AutopilotSettings.asset

なお、

  • UNITYにはUnityエディタへのパス、PROJECT_HOMEには自動実行対象プロジェクトのルートを指定します
  • -AUTOPILOT_SETTINGS には、実行したい設定ファイル(AutopilotSettings)のパスを指定します
  • -quit は指定しないでください(Play modeに入らず終了してしまいます)
  • -nographics は指定しないでください(GameViewウィンドウを表示できません)

また、以下の引数を追加することで一部の設定を上書きできます。 各引数の詳細は前述の「オートパイロット設定ファイル」の同名項目を参照してください。

LIFESPAN_SEC
実行時間上限を秒で指定します
RANDOM_SEED
疑似乱数発生器に与えるシードを固定したいときに指定します
TIME_SCALE
Time.timeScaleを指定します。デフォルトは1.0
JUNIT_REPORT_PATH
JUnit形式のレポートファイル出力パスを指定します
HANDLE_EXCEPTION
例外を検知したときに通知を行なうかを TRUE/ FALSEで上書きします
HANDLE_ERROR
エラーを検知したときに通知を行なうかを TRUE/ FALSEで上書きします
HANDLE_ASSERT
アサート違反を検知したときに通知を行なうかを TRUE/ FALSEで上書きします
HANDLE_WARNING
警告を検知したときに通知を行なうかを TRUE/ FALSEで上書きします

いずれも、キーの先頭に-を付けて-LIFESPAN_SEC 60のように指定してください。

ビルトインAgent

以下のAgentが用意されています。これらをそのまま使用することも、プロジェクト独自のAgentを実装して使用することも可能です。

UGUIMonkeyAgent

uGUIのコンポーネントをランダムに操作するAgentです。 実装にはオープンソースのtest-helper.monkeyパッケージを使用しています。

このAgentのインスタンス(.assetファイル)には以下を設定できます。

実行時間
ランダム操作の実行時間を秒で指定します。0を指定するとほぼ無制限(TimeSpan.MaxValue)に動作します。この設定でAgentが終了してもオートパイロットおよびアプリ自体は終了しません。次にSceneが切り替わるまでなにもしない状態になります
操作間隔
ランダム操作間のウェイト間隔をミリ秒で指定します
コンポーネント探索時間
インタラクティブな要素を探索する秒数を指定します。探索時間がこれを超えるとエラーを発生させます
タッチ&ホールド時間
タッチ&ホールドの継続時間をミリ秒で指定します
Gizmo
もし有効ならモンキー操作中の GameView に Gizmo を表示します。もし無効なら GameView に Gizmo を表示しません

スクリーンショット設定:

有効
スクリーンショット撮影を有効にします
ディレクトリ
デフォルト値を使用: スクリーンショットの保存先のディレクトリ名にデフォルト値を使用します。デフォルト値はコマンドライン引数 "-testHelperScreenshotDirectory" で指定します。コマンドライン引数も省略した場合は、Application.persistentDataPath + "/TestHelper/Screenshots/" が使用されます
パス: スクリーンショットの保存先ディレクトリのパス
ファイル名
デフォルト値を使用: スクリーンショットのファイル名のプレフィックスにデフォルト値を使用します。デフォルト値はAgentの名前です
プレフィックス: スクリーンショットのファイル名のプレフィックスを指定します
拡大係数
解像度をあげるための係数。ステレオキャプチャモードと同時には設定できません
ステレオキャプチャモード
ステレオレンダリングが有効な場合にどちらのカメラを使用するかを指定できます。拡大係数と同時には設定できません

UGUIMonkeyAgent によって操作されたくない GameObject がある場合、 TestHelper.Monkey.Annotations アセンブリに含まれる IgnoreAnnotation コンポーネントをアタッチしておくことで操作を回避できます。 詳しくは後述のAnjin Annotationsを参照してください。

UGUIPlaybackAgent

Automated QAパッケージのRecorded Playback機能でレコーディングしたuGUI操作を再生するAgentです。

Note

Automated QAパッケージはプレビュー段階のため、破壊的変更や、パッケージ自体の開発中止・廃止もありえる点、ご注意ください。

このAgentのインスタンス(.assetファイル)には以下を設定できます。

Recorded Json
再生するレコーディングファイル (.json) を指定します

Automated QAによる操作のレコーディングは、Unityエディターのメニューから Automated QA > Automated QA Hub > Recorded Playback で開くウィンドウから行ないます。 レコーディングファイル(.json)は Assets/Recordings/ フォルダ下に保存されますが、移動・リネームは自由です。

なお、Automated QAのRecorded Playback機能ではScene遷移をまたがって操作を記録ができますが、AnjinではSceneが切り替わったところでAgentも強制的に切り替わるため、再生も中断されてしまいます。 従って、レコーディングはScene単位に区切って行なうようご注意ください。

また、Automated QAによる操作のスクリーンショットをApplication.persistentDataPath/Anjin下に保存しています。 各プラットフォームのApplication.persistentDataPathはUnityマニュアルの Application.persistentDataPath を参照してください。

DoNothingAgent

なにもしないAgentです。

このAgentのインスタンス(.assetファイル)には以下を設定できます。

Lifespan Sec
なにもしない時間を秒で指定します。0を指定すると無制限になにもしません。この設定でAgentが終了してもオートパイロットおよびアプリ自体は終了しません。次にSceneが切り替わるまでなにもしない状態になります

ParallelCompositeAgent

複数のAgentを登録し、それを並列実行するAgentです。

このAgentのインスタンス(.assetファイル)には以下を設定できます。

Agents
並列実行するAgentのリスト。CompositeAgentを指定して入れ子にすることも可能です

SerialCompositeAgent

複数のAgentを登録し、それを直列実行するAgentです。

このAgentのインスタンス(.assetファイル)には以下を設定できます。

Agents
直列実行するAgentのリスト。CompositeAgentを指定して入れ子にすることも可能です

OneTimeAgent

1つの子Agentを登録し、それをAutopilot実行期間を通じて1回だけ実行できるAgentです。 2回目以降の実行はスキップされます。

たとえば、タイトル画面で初回だけ導線が異なる、ホーム画面で初回だけログインボーナス受け取りがあるといったゲームにおいて、 通信エラーなどによるタイトル画面戻しが発生してもそのまま実行するシナリオを構築できます。

このAgentのインスタンス(.assetファイル)には以下を設定できます。

Agent
1回だけ実行できるAgent。CompositeAgentを指定して入れ子にすることも可能です

RepeatAgent

1つの子Agentを登録し、それを無限に繰り返し実行するAgentです。

SerialCompositeAgentと組み合わせることで、シナリオを何周もしたり、シナリオの最後のAgentだけを繰り返し実行することができます。 なお、有限回の繰り返しはサポートしません(SerialCompositeAgentで実現できるため)。

このAgentのインスタンス(.assetファイル)には以下を設定できます。

Agent
繰り返し実行するAgent。CompositeAgentを指定して入れ子にすることも可能です

TimeBombAgent

内包するAgentが終了する前に解除メッセージを受信しないと失敗するAgent。

例えば、アウトゲームのチュートリアル(スマホゲームなどuGUIのタップ操作で完遂できるもの)を突破するには、次のように設定します。

  1. UGUIMonkeyAgentAgent に設定します。進行するボタン以外は操作できないはずです。実行時間 は少し余裕をもって設定してください
  2. チュートリアル完遂時にログに出力されるメッセージを 解除メッセージ に設定します

このAgentのインスタンス(.assetファイル)には以下を設定できます。

Agent
実際に動作するAgent。このAgentが先に終了すると、TimeBombAgentは失敗します。
解除メッセージ
このメッセージが先にログに出力されたら、TimeBombAgentは正常終了します。正規表現でも指定できます。

EmergencyExitAgent

DeNA.Anjin.Annotations アセンブリに含まれる EmergencyExit コンポーネントの出現を監視し、表示されたら即クリックするAgentです。 たとえば通信エラーや日またぎで「タイトル画面に戻る」ボタンのような、テストシナリオ遂行上イレギュラーとなる振る舞いが含まれるゲームで利用できます。

常に、他の(実際にゲーム操作を行なう)Agentと同時に起動しておく必要があります。 ParallelCompositeAgent でも実現できますが、AutopilotSettingsに Observer Agent として設定するほうが簡単です。

ビルトイン ロガー

以下のロガータイプが用意されています。これらをそのまま使用することも、プロジェクト独自のロガーを実装して使用することも可能です。

Composite Logger

複数のロガーを登録し、そのすべてにログ出力を委譲するロガーです。

このロガーのインスタンス(.assetファイル)には以下を設定できます。

Loggers
ログ出力を委譲するLoggerのリスト

Console Logger

ログをコンソールに出力するロガーです。

このロガーのインスタンス(.assetファイル)には以下を設定できます。

フィルタリングLogType
選択したLogType以上のログ出力のみを有効にします

File Logger

ログを指定ファイルに出力するロガーです。

このロガーのインスタンス(.assetファイル)には以下を設定できます。

出力ファイルパス
ログ出力ファイルのパス。プロジェクトルートからの相対パスまたは絶対パスを指定します。プレイヤー実行では相対パスの起点は Application.persistentDataPath になります。 コマンドライン引数 -FILE_LOGGER_OUTPUT_PATH で上書きできますが、複数のFileLoggerを定義しているときに指定すると、すべての出力パスが上書きされますので注意してください。
フィルタリングLogType
選択したLogType以上のログ出力のみを有効にします
タイムスタンプを出力
ログエンティティにタイムスタンプを出力します

ビルトイン レポータ

以下のレポータタイプが用意されています。これらをそのまま使用することも、プロジェクト独自のレポータを実装して使用することも可能です。

Composite Reporter

複数のレポータを登録し、そのすべてにレポート送信を委譲するレポータです。

このレポータのインスタンス(.assetファイル)には以下を設定できます。

Reporters
レポート送信を委譲するReporterのリスト

Slack Reporter

Slackにレポート送信するレポータです。

このレポータのインスタンス(.assetファイル)には以下を設定できます。

Slack Token
Slack通知に使用するWeb APIトークン(省略時は通知されない)。コマンドライン引数 -SLACK_TOKEN で上書きできます。
Slack Channels
Slack通知を送るチャンネル(省略時は通知されない)。カンマ区切りで複数指定できます。コマンドライン引数 -SLACK_CHANNELS で上書きできます。
Mention Sub Team IDs
Slack通知メッセージでメンションするチームのIDをカンマ区切りで指定します
Add Here In Slack Message
Slack通知メッセージに@hereを付けます。デフォルトはoff

ゲームタイトル独自処理の実装

ゲームタイトル固有のAgent等を実装する場合、リリースビルドへの混入を避けるため、専用のアセンブリに分けることをおすすめします。 Assembly Definition File (asmdef) のAuto Referencedをoff、Define Constraintsに UNITY_INCLUDE_TESTS || DENA_AUTOPILOT_ENABLE を設定することで、リリースビルドからは除外できます。

このasmdef及び格納フォルダは、Projectウィンドウの任意の場所でコンテキストメニューを開き Create > Anjin > Title Own Assembly Folder を選択することで生成できます。

タイトル独自Agent

タイトル独自のAgentは、Anjin.Agents.AbstractAgent を継承して作ります。 メソッド UniTask Run(CancellationToken) に、Agentが実行する処理を実装するだけです。

AbstractAgent に定義された以下のフィールドを利用できます。各インスタンスは Run メソッド呼び出し前に設定されています。

  • Logger : UnityEngine.ILogger の実装です。現時点ではコンソール出力ですが、ファイルロガーに差し替える予定があります。ログ出力にはこちらを使ってください
  • Random : Anjin.Utilities.IRandom の実装です。設定ファイルもしくは起動時引数で指定されたシードから作られています

なお、[CreateAssetMenu]アトリビュートを設定しておくとコンテキストメニューからインスタンス生成ができて便利です。

タイトル独自事前処理

タイトル独自の初期化処理が必要な場合、初期化を行なうstaticメソッドに InitializeOnLaunchAutopilot 属性を付与してください。 オートパイロットの起動処理の中でメソッドを呼び出します。

なお、オートパイロットの起動処理は、RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)RuntimeInitializeOnLoadMethodのデフォルト)で実行しています。 またRuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)で、Configurable Enter Play Modeのための初期化処理を実装しています。

Anjin Annotations

Anjinの操作を制御するためのアノテーションを定義しています。 DeNA.Anjin.Annotations アセンブリをAssembly Definition Referencesに追加して使用してください。 仕組み上、リリースビルドに含まれることになりますのでご注意ください。

Note

アノテーションアセンブリをリリースビルドから除いても、アセットバンドルビルドされたSceneやPrefabにはアノテーションコンポーネントへのリンクが残ります。 そのため、インスタンス化の際に警告ログが出力されてしまいます。 これを回避するため、リリースビルドにアノテーションアセンブリを含めるようにしています。

IgnoreAnnotation

このコンポーネントがアタッチされたGameObjectは、UGUIMonkeyAgentによって操作されることを避けることができます。

EmergencyExit

このコンポーネントがアタッチされたButtonが表示されると、EmergencyExitAgentはすぐにクリックを試みます。 通信エラーや日またぎで「タイトル画面に戻る」ボタンのような、テストシナリオ遂行上イレギュラーとなるボタンに付けることを想定しています。

トラブルシューティング

プロジェクトを再生モードにすると勝手にオートパイロットが動いてしまう

Anjinの実行状態を永続化している AutopilotState.asset が不正な状態になっている恐れがあります。 インスペクタで開いてResetボタンをクリックしてください。

それでも解決しない場合、 AutopilotState.asset を削除してみてください。

[CompilerError] Argument 1: Cannot convert to 'System.Threading.CancellationToken'

次のコンパイルエラーが発生するケースが報告されています。

[CompilerError] Argument 1:.
Cannot convert from 'DeNA.Anjin.Reporters.SlackReporter.CoroutineRunner' to 'System.Threading.CancellationToken'
Compiler Error at Library\PackageCache\com.dena.anjin@1.0.1\Runtime\Reporters\SlackReporter.cs:66 column 53

これは、プロジェクトにインストールされているUniTaskがv2.3.0未満のときに発生します。 この箇所で使用している UniTask.WaitForEndOfFrame(MonoBehaviour) は、UniTask v2.3.1で追加されたAPIです。

通常、インストール方法に従っていれば適正なバージョンのUniTaskがインストールされます。 しかし、プロジェクトに埋め込みパッケージとしてUniTaskが配置されていたりすればそちらが優先されてしまいます。 Unityエディターが生成するPackages/packages-lock.jsonの中身を確認するか、お使いのIDEのコード定義ジャンプ機能で UniTask.WaitForEndOfFrame() のソースファイルがどこにあるかを確認するなどして、古いUniTaskがインストールされている原因を突き止められます。

ライセンス

MIT License

コントリビュート

IssueやPull requestを歓迎します。

Pull requestには enhancement, bug, chore, documentation といったラベルを付けてもらえるとありがたいです。 ブランチ名から自動的にラベルを付ける設定もあります。PR Labeler settings を参照してください。

開発方法

本リポジトリをUnityプロジェクトのサブモジュールとして Packages/ ディレクトリ下に置いてください。

ターミナルから次のコマンドを実行します。

git submodule add https://github.com/dena/Anjin.git Packages/com.dena.anjin

Warning

Anjinパッケージ内のテストを実行するためには、次のパッケージのインストールが必要です。

テスト専用のUnityプロジェクトを生成し、Unityバージョンを指定してテストを実行するには、次のコマンドを実行します。

make create_project
UNITY_VERSION=2019.4.40f1 make -k test

リリースワークフロー

Actions > Create release pull request > Run workflow を実行し、作られたpull requestをデフォルトブランチにマージすることでリリース処理が実行されます。 (もしくは、デフォルトブランチのpackage.json内のバージョン番号を書き換えます)

リリース処理は、Releaseワークフローで自動的に行われます。 tagが付与されると、OpenUPMがtagを収集して更新してくれます。

以下の操作は手動で行わないでください。

  • リリースタグの作成
  • ドラフトリリースの公開