Skip to content

Commit

Permalink
Merge pull request #108 from nowsprinting/feature/emergency_exit_agent
Browse files Browse the repository at this point in the history
Rename and enhancement UGUIEmergencyExitAgent
  • Loading branch information
bo40 authored Nov 19, 2024
2 parents d52a58c + da2f782 commit 6a913f2
Show file tree
Hide file tree
Showing 13 changed files with 269 additions and 124 deletions.
2 changes: 1 addition & 1 deletion Annotations/EmergencyExitAnnotation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace DeNA.Anjin.Annotations
{
/// <summary>
/// Attach this component to the "Return to Title Scene" button or each other buttons that are displayed in the event of communication errors.
/// As soon as the component appears on the screen, it is click by <c>EmergencyExitAgent</c>
/// As soon as the component appears on the screen, it is click by <c>UGUIEmergencyExitAgent</c>
/// </summary>
[RequireComponent(typeof(Button))]
public class EmergencyExitAnnotation : MonoBehaviour
Expand Down
19 changes: 19 additions & 0 deletions Editor/Localization/ja.po
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,25 @@ msgid "Agents to serial execution"
msgstr "連続実行するAgentを指定します"


#: Editor/UI/Agents/UGUIEmergencyExitAgentEditor.cs

# intervalMillis
msgid "Interval [ms]"
msgstr "間隔[ミリ秒]"

# intervalMillis tooltip
msgid "Interval in milliseconds to check for the appearance of the EmergencyExitAnnotation component."
msgstr "EmergencyExitAnnotationコンポーネントの出現を確認する間隔をミリ秒で指定します"

# screenshot
msgid "Screenshot"
msgstr "スクリーンショット"

# screenshot tooltip
msgid "Take a screenshot when click the EmergencyExit button."
msgstr "EmergencyExitボタンクリック時にスクリーンショットを撮影します"


#: Editor/UI/Agents/UGUIMonkeyAgentEditor.cs

# lifespanSec (same as DoNothingAgentEditor.cs)
Expand Down
30 changes: 0 additions & 30 deletions Editor/UI/Agents/EmergencyExitAgentEditor.cs

This file was deleted.

66 changes: 66 additions & 0 deletions Editor/UI/Agents/UGUIEmergencyExitAgentEditor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) 2023-2024 DeNA Co., Ltd.
// This software is released under the MIT License.

using DeNA.Anjin.Agents;
using UnityEditor;
using UnityEngine;

namespace DeNA.Anjin.Editor.UI.Agents
{
/// <summary>
/// Editor GUI for UGUIEmergencyExitAgent
/// </summary>
[CustomEditor(typeof(UGUIEmergencyExitAgent))]
public class UGUIEmergencyExitAgentEditor : UnityEditor.Editor
{
private const float SpacerPixels = 10f;

// @formatter:off
private static readonly string s_description = L10n.Tr("Description");
private static readonly string s_descriptionTooltip = L10n.Tr("Description about this agent instance");
private SerializedProperty _descriptionProp;
private GUIContent _descriptionLabel;

private static readonly string s_intervalMillis = L10n.Tr("Interval [ms]");
private static readonly string s_intervalMillisTooltip = L10n.Tr("Interval in milliseconds to check for the appearance of the EmergencyExitAnnotation component.");
private SerializedProperty _intervalMillisProp;
private GUIContent _intervalMillisLabel;

private static readonly string s_screenshot = L10n.Tr("Screenshot");
private static readonly string s_screenshotTooltip = L10n.Tr("Take a screenshot when click the EmergencyExit button.");
private SerializedProperty _screenshotProp;
private GUIContent _screenshotLabel;
// @formatter:on

private void OnEnable()
{
Initialize();
}

private void Initialize()
{
_descriptionProp = serializedObject.FindProperty(nameof(UGUIEmergencyExitAgent.description));
_descriptionLabel = new GUIContent(s_description, s_descriptionTooltip);

_intervalMillisProp = serializedObject.FindProperty(nameof(UGUIEmergencyExitAgent.intervalMillis));
_intervalMillisLabel = new GUIContent(s_intervalMillis, s_intervalMillisTooltip);

_screenshotProp = serializedObject.FindProperty(nameof(UGUIEmergencyExitAgent.screenshot));
_screenshotLabel = new GUIContent(s_screenshot, s_screenshotTooltip);
}

/// <inheritdoc/>
public override void OnInspectorGUI()
{
serializedObject.Update();

EditorGUILayout.PropertyField(_descriptionProp, _descriptionLabel);
GUILayout.Space(SpacerPixels);

EditorGUILayout.PropertyField(_intervalMillisProp, _intervalMillisLabel);
EditorGUILayout.PropertyField(_screenshotProp, _screenshotLabel);

serializedObject.ApplyModifiedProperties();
}
}
}
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -415,13 +415,21 @@ This Agent instance (.asset file) can contain the following.
> Recommend enabling a `Handle Exception` to interrupt Autopilot if an exception occurs during execution.

### EmergencyExitAgent
### UGUIEmergencyExitAgent

An Agent that monitors the appearance of the `EmergencyExitAnnotations` component in the `DeNA.Anjin.Annotations` assembly and clicks on it as soon as it appears.
This can be used in games that contain behavior that is irregular in the execution of the test scenario, for example, communication errors or "return to title screen" buttons that are triggered by a daybreak.
An Agent that monitors the appearance of the `EmergencyExitAnnotations` component in the Scene and clicks on it as soon as it appears.
This can be used in games that contain behavior that is irregular in the execution of the test scenario, for example, communication errors or "Return to Title Screen" buttons that are triggered by a daybreak.

It should always be started at the same time as other Agents (that actually perform game operations).
This can be accomplished with `ParallelCompositeAgent`, but it is easier to set it up as an `Scene Crossing Agents` in AutopilotSettings.
Generally, you add to `Scene Crossing Agents` in `AutopilotSettings`.
If you want to change the settings for each Scene, use with `ParallelCompositeAgent`.

This Agent instance (.asset file) can contain the following.

<dl>
<dt>Interval</dt><dd>Interval in milliseconds to check for the appearance of the EmergencyExitAnnotation component.</dd>
<dt>Screenshot</dt><dd>Take a screenshot when click the EmergencyExit button.</dd>
</dl>



Expand Down Expand Up @@ -600,7 +608,7 @@ The `GameObject` to which this component is attached avoids manipulation by the

### EmergencyExitAnnotations

When a `Button` to which this component is attached appears, the `EmergencyExitAgent` will immediately attempt to click on it.
When a `Button` to which this component is attached appears, the `UGUIEmergencyExitAgent` will immediately attempt to click on it.
It is intended to be attached to buttons that are irregular in the execution of the test scenario, such as the "return to title screen" button due to a communication error or a daybreak.


Expand Down
16 changes: 12 additions & 4 deletions README_ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,13 +420,21 @@ Sceneごとに設定を変えたい場合は、`ParallelCompositeAgent` と合
> 実行中に例外が発生した時点でオートパイロットを中断するために、`Handle Exception` の有効化をお勧めします。

### EmergencyExitAgent
### UGUIEmergencyExitAgent

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

常に、他の(実際にゲーム操作を行なう)Agentと同時に起動しておく必要があります。
`ParallelCompositeAgent` でも実現できますが、AutopilotSettingsの `Scene Crossing Agents` に追加するほうが簡単です。
一般的には、`AutopilotSettings``Scene Crossing Agents` に追加します。
Sceneごとに設定を変えたい場合は、`ParallelCompositeAgent` と合わせて使用します。

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

<dl>
<dt>間隔</dt><dd>EmergencyExitAnnotationコンポーネントの出現を確認する間隔をミリ秒で指定します</dd>
<dt>スクリーンショット</dt><dd>EmergencyExitボタンクリック時にスクリーンショットを撮影します</dd>
</dl>



Expand Down Expand Up @@ -606,7 +614,7 @@ Anjinの操作を制御するためのアノテーションを定義していま

### EmergencyExitAnnotations

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


Expand Down
68 changes: 0 additions & 68 deletions Runtime/Agents/EmergencyExitAgent.cs

This file was deleted.

95 changes: 95 additions & 0 deletions Runtime/Agents/UGUIEmergencyExitAgent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) 2023-2024 DeNA Co., Ltd.
// This software is released under the MIT License.

using System.Text;
using System.Threading;
using Cysharp.Threading.Tasks;
using DeNA.Anjin.Annotations;
using DeNA.Anjin.Strategies;
using TestHelper.Monkey.Operators;
using TestHelper.Monkey.ScreenshotFilenameStrategies;
using TestHelper.RuntimeInternals;
using UnityEngine;
using UnityEngine.UI;

namespace DeNA.Anjin.Agents
{
/// <summary>
/// Wait for the <c>EmergencyExitAnnotation</c> component to appear and click attached <c>UnityEngine.UI.Button</c>.
/// This Agent will not be terminated and will continue to be observed.
/// </summary>
[CreateAssetMenu(fileName = "New UGUIEmergencyExitAgent", menuName = "Anjin/uGUI Emergency Exit Agent", order = 51)]
public class UGUIEmergencyExitAgent : AbstractAgent
{
/// <summary>
/// Interval in milliseconds to check for the appearance of the <c>EmergencyExitAnnotation</c> component.
/// </summary>
public int intervalMillis = 1000;

/// <summary>
/// Take a screenshot when click the EmergencyExit button.
/// </summary>
public bool screenshot;

private static IClickOperator ClickOperator => new UGUIClickOperator();
private IScreenshotFilenameStrategy _filenameStrategy;

/// <inheritdoc />
public override async UniTask Run(CancellationToken token)
{
Logger.Log($"Enter {this.name}.Run()");
this._filenameStrategy = new TwoTieredCounterStrategy(this.name);

try
{
var selectables = new Selectable[20];

while (true) // Note: This agent is not terminate myself
{
var allSelectableCount = Selectable.allSelectableCount;
if (selectables.Length < allSelectableCount)
{
selectables = new Selectable[allSelectableCount];
}

Selectable.AllSelectablesNoAlloc(selectables);
for (var i = 0; i < allSelectableCount; i++)
{
if (selectables[i].TryGetComponent<EmergencyExitAnnotation>(out var emergencyExit))
{
await ClickEmergencyExitButton(emergencyExit, token);
}
}

await UniTask.Delay(intervalMillis, ignoreTimeScale: true, cancellationToken: token);
}
}
finally
{
Logger.Log($"Exit {this.name}.Run()");
}
}

private async UniTask ClickEmergencyExitButton(EmergencyExitAnnotation emergencyExit,
CancellationToken cancellationToken = default)
{
var button = emergencyExit.gameObject.GetComponent<Button>();
if (!ClickOperator.CanOperate(button))
{
return;
}

var message = new StringBuilder($"Click emergency exit button: {button.gameObject.name}");
if (screenshot)
{
var filename = _filenameStrategy.GetFilename();
await ScreenshotHelper.TakeScreenshot(filename: filename).ToUniTask(button);
message.Append($" ({filename})");
}

Logger.Log(message.ToString());

await ClickOperator.OperateAsync(button, cancellationToken);
}
}
}
File renamed without changes.
3 changes: 2 additions & 1 deletion Runtime/DeNA.Anjin.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"UniTask",
"TestHelper.Monkey",
"TestHelper.Monkey.Annotations",
"TestHelper.Random"
"TestHelper.Random",
"TestHelper.RuntimeInternals"
],
"includePlatforms": [],
"excludePlatforms": [],
Expand Down
Loading

0 comments on commit 6a913f2

Please sign in to comment.