Unity Plugin Quickstart

This page will present you with simple steps you need to take in order to integrate Grail with your Unity project.

1. Grail and Unity

To start off, you simply need to put contents of our plugin in Assets/Plugins/ directory inside your project structure.

2. Grail Configuration Loader

GrailConfigurationLoader allows us to, well…​, load a configuration file and store it’s content in format understandable for the rest of the plugin. The easiest way to produce a proper grail configuration file is to use our tool. To create GrailConfigurationLoader right-click on your project tab and select CreateGrailGrailConfigurationLoader. Right now you should see something like this:

Grail Configuration Loader

Right now we do not need to configure this scriptable object that much. Just select your configuration file and we’re done for now. You can check, whether the file loaded properly by comparing lists of available entities and groups to data provided in your file.

3. Creating Manager Object

AI Manager is an abstraction functioning as a grail’s motor-power. It will control it’s registered entities' thought processes. But for it to be able to do so, you first you need to add AIManagerComponent to any object on your scene. Simply create a new, empty object and attach to it the component mentioned above. Alternatively, you can place the component, i.e. on your Game Controller object or something alike. What matters is, that it should be available in scene hierarchy.

The default AIMangerComponent updates entities thoughts and states every frame. If it doesn’t suit your needs, override this class and provide your own logic for updating entities.

4. Creating Entity Object

AIEntity is a basic grail agent able to reason and execute selected behaviors. We’ve prepared an AIEntityComponent which simply need to be attached to an object you wish to make responsible for thinking and taking actions. Let’s imagine that we’re making a war game and we’ve already prepared a Soldier blueprint. This soldier is supposed to be an autonomous unit, so we need to attach AIEntityComponent to it.

AIEntityComponent Inspector

When that’s done we need to properly configure this component to suit our needs. First, select GrailConfigurationLoader we’ve created in one of the previous steps and then select one of the entities containted in that object and click Import Entity Button. After that, you should be able to see imported entity name in corresponding field.

If you’d like to register an entity in a manager, right at the start of the scene, just click the toggle, select the proper manager object and give this entity a priority. To keep it short, entities with lower priority will be processed before the ones with higher priority.

If you need your physical object be controlled by more than one entity (for example in twin stick shooter - one entity responsible for movement and one for attacking) you can follow the above process but using EntityGroupComponent instead of AIEntityComponent and everything should be just fine.

5. Providing Reasoner Factories

We’re almost ready to play our scene. The only thing left to be done is providing our GrailConfigLoader with reasoner factories, so it can create and assign proper reasoner to each entity.

Depending whether you want to use Grail’s Utility System or other AI algorithms (including rest of Grail’s planners and simulated games) there are different ways to achieve this task.

5.1. Utility Systems

For now let’s assume that we’re going to use the Utility Systems. If you’re interested only in other algorithms skip to further section.

5.1.1. Implementing Behaviors and Behavior Providers

Continuing our example with Soldier, we know that he needs to possess ability to shoot.

To provide him that ability we need to override Behavior class and create much needed ShootBehavior. The best way to learn about this is to read this article.

Following that we need to create our custom BehaviorProvider. BehaviorProvider is an abstract class which requires us to implement InstantiateBlueprint method, which should return properly set up blueprint for our behavior. This blueprint should be passed parent class variable behaviorName as its name. As blueprints are a part of Grail’s Utility Systems we also need to initialize it with functions allowing us to properly instantiate behaviors.

Now we only have to give our provider an attribute which will allow us to create an instance of this scriptable object in project window.

Our finished behavior provider should look more or less like this:

[CreateAssetMenu(menuName = "GenericWarGame/BehaviorProviders/Shoot", fileName = "ShootBehaviorProvider")]
public class ShootBehaviorProvider : Grail.UnityPlugin.BehaviorProvider
{
  public override Grail.Blueprint<Grail.Behavior, (Grail.AIEntity, Grail.Blackboard), Grail.AIEntity>  InstantiateBlueprint()
  {
    return new Grail.Blueprint<Grail.Behavior, (Grail.AIEntity, Grail.Blackboard), Grail.AIEntity>
        (behaviorName, ProduceContexts, ProduceInstance);
  }

  //rest of the class body
}

The only thing left is to create instance of this BehaviorProvider and assign its name.

Be sure that you name created provider EXACTLY like corresponding behavior is called in selected configuration file. Otherwise plugin will be unable to properly provide entity this behavior.

5.1.2. Behavior Repository

As we now have at least one BehaviorProvider we can add it to BehaviorRepository. To do so, first we need to create one. Right-click on project window and select CreateGrailBehaviorRepository. Now, we should insert our BehaviorProvider into the freshly created BehaviorRepository. As that’s done, we can now assign this repository to the corresponding field in GrailConfigurationLoader.

5.1.3. Consideration Provider

Similarly to BehaviorProvider we have to implement ConsiderationProvider. Let’s assume that for the purpose of selecting the most adequate ShootBehavior we will be considering distance between our Soldier and its target.

We need to implement DistanceConsideration which will should calculate said distance. After that’s done, we’re going to write a class for DistanceConsiderationProvider and override ConsiderationProvider’s method `InstantiateConsideration to return freshly implemented consideration.

Final ConsiderationProvider should look alike this:

[CreateAssetMenu(menuName = "GenericWarGame/ConsiderationProviders/Distance", filename = "DistanceConsiderationProvider")]
public class DistanceConsiderationProvider : Grail.UnityPlugin.ConsiderationProvider
{
  public override Consideration<(Grail.AIEntity, Grail.Blackboard)> InstantiateConsideration()
  {
    return new DistanceConsideration();
  }

  //rest of the class body
}

Now we also need to create scriptable object of this type and assign consideration name.

Be sure that you name the created provider EXACTLY like the corresponding consideration is called in the selected configuration file. Otherwise plugin will be unable to properly provide entity this consideration.

5.1.4. Consideration Repository

With ConsiderationProvider ready, our next task is creating ConsiderationRepository. Right-click on the project window and select CreateGrailConsiderationRepository. Now drag DistanceConsidetationProvider scriptable object on correspoding field in repository inspector view and then select this ConsiderationRepository in previously created GrailConfigurationLoader.

5.2. Other Algorithms

If what we need is to provide an entity with custom reasoner we should implement our own ReasonerFactory, create an object instance of this type and pass it to GrailConfigurationLoader.

Exemplar ReasonerFactory can be found in the code snippet below:

public class CustomReasonerFactory : Grail.UnityPlugin.ReasonerFactory
{
  private Dictionary<string, Grail.Reasoner> reasonerMapping;

  public override Grail.Reasoner CreateReasoner(string reasonerID)
  {
    return reasonerMapping[reasonerID];
  }

  //rest of the class body
}

6. Blackboard Data Providers

When everything is done, we should be able to play the scene and watch our AI taking its actions. But what if we require to provide our entity with data taken directly from Unity? For example, our Soldier should additionally be able to patrol the perimeter. Fear not, to make it work we only need to pass proper data to entity’s internal blackboard which can easily be done with BlackboardDataProvider.

Override this class, attach it to entity object, fill it with required data and you’re done.

Sample PatrolPointsDataProvider:

public class PatrolPointsDataProvider : Grail.UnityPlugin.BlackboardDataProvider
{
  [SerializeField] private List<Transform> patrolPoints;

  protected override void Awake() // This override is neccessary to autamatically attach overriden method to proper event on entity creation.
  {
    base.Awake();
  }

  protected override void ProvideBlackboardData(Blackboard entityBlackboard)
  {
    entityBlackboard.SetValue("patrol_points", patrolPoints);
  }
}

7. Plugin ready

Congratulation! Now we’re ready to extensively make use of Grail in Unity project. We hope that Grail will prove useful during the development of your game.