Skip to content

Quick Start Guide

Quake edited this page Nov 12, 2024 · 10 revisions

Let's get started!

In this Quickstart Guide, you will learn how to create your first aplib test in Unity. You can also use it to learn aplib in general.

Aplib is a C# library that allows you to create automated playtests for your games with ease. Aplib is driven by the Belief-Desire-Intention (BDI) model, a widely used framework in artificial intelligence for agent-based systems. That sounds intimidating, but don't worry; you'll have your first aplib test running in no time!

Important

You need to have Unity installed to follow along with this guide.

1. Open a Unity project

Open a Unity project that you would like to write aplib tests for, or create an empty project if you just want to learn aplib.

2. Install the Unity Package

Head to the repository of our Unity Package for aplib and follow the instructions there to install the Unity Package for aplib within your Unity project.

3. Set up a test assembly

To be able to run our tests, we need to create a test assembly. Open the Unity Test Runner window (Window > General > Test Runner), and open the PlayMode tab. Click on the big button asking you to create a new assembly folder for the tests.

Now, select the assembly definition file within this newly created folder, and look at the inspector menu, you will want to do two things here:

  1. Under Assembly Definition References, click the plus icon and add team-zomsa.aplib-unity.
  2. Under Assembly References, click the plus icon and add Aplib.Core.dll.

Done!

Your project is now set up to create aplib tests! Next, let's create one:


How to create an aplib test?

To create a new test, right-click on the tests folder you just created, and click on Create > Testing > Test-script. Now, this will import a test template. In a second, we will adjust this template. You can also create a new test script by opening the tests folder and right-clicking outside the asmdef file and creating a test script, or by clicking the plus button.

Let's write a simple test!

1. Create a test script as described above

2. Create a scene for the playtest

Before we write our first aplib test, we set up a Unity scene that we can run the test on, and add it to the build settings so that we can open it from our test script.

  1. Create a scene called FirstTestScene.
  2. Open FirstTestScene.
  3. Click File → Build Settings (or press ctrl + shift + b) to open the build settings of your project.
  4. Click Add Open Scenes to add your scene to the build settings.

3. Set up the scene

We add a few game objects to the newly created scene so that we can write a test for them and visualize our test.

  1. Create a cube by right-clicking the scene hierarchy and clicking 3D Object → Cube. Rename this GameObject to Player.
  2. Create a sphere by right-clicking the scene hierarchy and clicking 3D Object → Sphere. Rename this GameObject to Target.
  3. Remove the SphereCollider component from the Target GameObject.
  4. Move the Target GameObject away from the Player GameObject, such that they are still within the camera view.

4. Write your first aplib test!

Replace the contents of the test script you just created with the following:

using Aplib.Core;
using Aplib.Core.Belief.Beliefs;
using Aplib.Core.Belief.BeliefSets;
using Aplib.Core.Desire.Goals;
using Aplib.Core.Intent.Actions;
using Aplib.Core.Intent.Tactics;
using NUnit.Framework;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
using Aplib.Core.Desire.GoalStructures;
using Aplib.Core.Desire.DesireSets;
using Aplib.Core.Agents;
using Aplib.Integrations.Unity;

namespace Tests.AplibTests
{
    public class MyFirstAplibTest
    {
        /// <summary>
        /// A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use `yield return null;` to skip a frame.
        /// </summary>
        [UnityTest]
        public IEnumerator PerformMyFirstAplibTest()
        {
            // Arrange
            // Create a belief set for the agent.
            MyFirstBeliefSet beliefSet = new();

            // Create an intent for the agent that moves the agent towards the target position.
            Action<MyFirstBeliefSet> moveTowardsTargetAction = new(
                beliefSet =>
                {
                    GameObject player = beliefSet.Player;
                    const float playerSpeed = 10f;
                    Vector3 playerPosition = player.transform.position;
                    Vector3 targetPosition = beliefSet.TargetPosition;
                    player.transform.position = Vector3.MoveTowards(playerPosition,
                        targetPosition,
                        maxDistanceDelta: playerSpeed * Time.deltaTime
                    );
                }
            );
            PrimitiveTactic<MyFirstBeliefSet> moveTowardsTargetTactic = new(moveTowardsTargetAction);

            // Create a desire for the agent to reach the target position.
            Goal<MyFirstBeliefSet> reachTargetGoal = new(
                moveTowardsTargetTactic,
                beliefSet =>
                {
                    GameObject player = beliefSet.Player;
                    Vector3 playerPosition = player.transform.position;
                    Vector3 targetPosition = beliefSet.TargetPosition;
                    return Vector3.Distance(playerPosition, targetPosition) < 0.1f;
                }
            );
            PrimitiveGoalStructure<MyFirstBeliefSet> reachTargetGoalStructure = new(reachTargetGoal);
            RepeatGoalStructure<MyFirstBeliefSet> repeat = new(reachTargetGoalStructure);
            DesireSet<MyFirstBeliefSet> desireSet = new(repeat);

            // Setup the agent with the belief set and desire set and initialize the test runner.
            BdiAgent<MyFirstBeliefSet> agent = new(beliefSet, desireSet);
            AplibRunner testRunner = new(agent);

            // Act
            yield return testRunner.Test();

            // Assert
            Assert.AreEqual(CompletionStatus.Success, agent.Status);
        }
    }
}

You now defined your first test! However, the BeliefSet of this test is still missing. To bridge the gap between aplib and your Unity scene, add its BeliefSet above your test class:

public class MyFirstBeliefSet : BeliefSet
{
    /// <summary>
    /// The player object in the scene.
    /// </summary>
    public readonly Belief<GameObject, GameObject> Player = new(reference: GameObject.Find("Player"), x => x);

    /// <summary>
    /// The target position that the player needs to move towards.
    /// </summary>
    public readonly Belief<Transform, Vector3> TargetPosition =
        new(GameObject.Find("Target").transform, x => x.position);
}

Lastly, to prepare this test, add this final piece of code within your test class:

[SetUp]
public void SetUp()
{
    Debug.Log("Starting test MyFirstAplibTest");
    SceneManager.LoadScene("FirstTestScene");
}

And you are done! You can now run the test in the test runner window you opened earlier, and it should succeed. If it does not succeed, make sure you have not forgotten the BeliefSet and SetUp, and also make sure you added the scene to the build settings!

Let's create a more complex aplib test!

Now that you've created your first aplib test, you're ready for the big work! In our tanks tutorial below, you will create an aplib test for a real game!


Let's write a more complex aplib test!

You created your first aplib test! Now let's create a slightly more complex aplib test in a real game!

1. Clone the example project repository

You can find the example game here, it is based on Unity's Tanks! Tutorial example game.

2. Open the test script

You can find this in the Tests folder.

3. Follow the instructions in the test script

Fill in the blanks to complete the aplib test for the example game. You can run the tests frequently to see if it works!