skip to Main Content

Creating Custom EQS Generators in C++

In this post we’re going to create our own EQS Generator in Unreal Engine 4. This post assumes you’re familiar with the Environment Query System that resides in UE4. In case you don’t quite remember what this is, check out my previous post here.

Before we start creating our own Generator, check out the end result here:

This post was written in 4.13 version of UE4. In case you’re using a different version you may need to adjust the code in order to match with the corresponding API changes.

Creating a custom EQS Generator

Our generator will create a cone in front of our AI pawn. Please note that in this case we won’t create a Pawn with custom behavior, instead, we’re going to use an EQS Testing Pawn. These Pawns help us test our EQS logic faster, since we don’t have to play or simulate our game.

Having said that, create a template project (it doesn’t matter if it’s C++ or Blueprint) and when the editor loads up activate the Environment Query System. In 4.13 version this option is located in the following path:

Edit -> Editor Preferences -> Experimental -> AI.

Here is a screenshot of the mentioned path:

enabling_eqs
Click on image to enlarge in a new tab

When you’re done with that, add a new C++ class named EnvQueryGenerator_Cone that inherits the EnvQueryGenerator_ProjectedPoints class. Then, inside its header file, type in the following code:

Then, inside the source file, implement the following logic for the GenerateItems function:

Notice that we didn’t call the Super::GenerateItems function. This is because this particular function is designed to be overriden completely. The default implementation should never be called, since it’s designed to throw an error.

Save and compile your code. Then:

  • Add a Nav mesh into your map
  • Create a Blueprint Pawn that inherits the EQSTestingPawn class
  • Place the EQSTestingPawn in your map

Then, create an Environment Query and call your C++ generator like the following screenshot suggests:

cone_eqs

When you’re done with that, assign the created EQS (ConeEQS in my case) to your placed EQSTesting Pawn:

eqstestingpawn
Click on image to enlarge in a new tab

Moreover, you should disable the Re Run Query Only on Finished Move for a more smooth display of your EQS while moving your Pawn.

At this point you have created your own generator! Temper with the values we exposed to the editor to have different results!

If you’ve made it this far, thank you!

Avatar photo

This Post Has 3 Comments

  1. Hi Orfeas,

    thank you for another great tutorial. I am actually trying to create a generator that finds all weapons that are not already held by someone else. How would I return the weapon found to the behavior tree from the generator? I would basically need a alternative to StoreNavPoints, which you are using.

    This is what it currently looks like. It causes an error at QueryInstance.AddItemData(*ActorItr);

    void UFindUnequippedFirearmGenerator::GenerateItems(FEnvQueryInstance& QueryInstance) const
    {
    AActor* aiPawn = Cast((QueryInstance.Owner).Get());
    for (TActorIterator ActorItr(GetWorld()); ActorItr; ++ActorItr)
    {
    if ((ActorItr->GetActorLocation() – aiPawn->GetActorLocation()).Size() <= _range)
    {
    AFirearm *desiredFirearm = *ActorItr;
    QueryInstance.AddItemData(*ActorItr);
    return;
    }
    }
    }

    1. Hello Kai,

      EQS Generators are used in order to “ask” the environment various queries. From your description I think that it would be best to create your own Behavior Tree Task instead of an EQS Generator.

      -Orfeas

      1. Hey Orfeas,

        thanks for the reply. Sorry it took me so long to get back. I want to ask the environment where all the unused firearms within a certain area are. Wouldn’t that exactly be what the eqs is for? I am already using it to help the AI find cover, but in the case of the firearms I have one boolean condition, which is: not picked up.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Back To Top