Advanced Workflow: Blueprint Queries
You've learned how to create powerful, data-driven queries using the Query Definition Asset. This is the recommended approach for the vast majority of cases as it's efficient, readable by designers, and integrates with the FactsDB debugger.
However, sometimes you need to perform logic that is too complex for a simple condition, such as running a loop, performing a line trace, or getting data from another game system. For these scenarios, you can create a Blueprint Query.
A Blueprint Query is a Blueprint Class
that inherits from UFactQuery
. It allows you to write any Blueprint graph logic you want inside its Evaluate
function to determine the result.
Data-Driven vs. Blueprint Queries
Here is a summary of the key differences to help you decide which to use:
Feature | Data-Driven Query (FactsDBQueryDefinition Asset) | Blueprint Query (UFactQuery Blueprint) |
---|---|---|
Primary Use Case | Defining reusable, declarative logic (95% of cases). | Encapsulating complex, programmatic logic. |
Logic Definition | In a Data Asset using a simple, type-safe UI. | In a Blueprint's Event Graph by overriding the Evaluate function. |
Performance | Very High. Evaluates native C++ structures. | Lower. Incurs standard Blueprint execution overhead. |
Memory Footprint | Minimal. A simple C++ struct in a cooked map. | Higher. Requires loading a full UBlueprintGeneratedClass . |
Debugger Integration | Yes. The query's execution path is visible in the debugger. | No. The logic is opaque to the debugger; it's just a BP call. |
Flexibility | Limited to the provided conditions (AND , OR , NOT ). | Unlimited. Can execute any Blueprint node or C++ function. |
When to Use a Blueprint Query
Use a Blueprint Query when your logic cannot be expressed by combining simple conditions. Good examples include:
- Complex mathematical calculations that go beyond simple comparisons.
- Needing to get data from other Actors or Subsystems (e.g., using
Get All Actors Of Class
). - Performing world queries like sphere traces or line traces.
- Logic that requires a loop.
Blueprint Queries are an excellent tool for rapid prototyping. You can quickly implement complex logic without leaving the editor.
However, due to their performance and memory trade-offs, it is recommended to use them sparingly in production code. If a Blueprint Query becomes a core part of your gameplay and is evaluated frequently, consider working with a programmer to convert its logic into a new, native C++ FFactQuery_Data
struct for optimal performance.
Workflow: Creating a Blueprint Query
Let's create a Blueprint Query that checks if the player is within 500 units of a mission objective.
Step 1: Create the Blueprint Query Asset
Thanks to the editor integration, creating a Blueprint Query is simple.
- In the Content Browser, right-click and go to
FactsDB
>Fact Query
. - A new Blueprint will be created. Name it
BPQ_Player_IsNearObjective
.
Step 2: Implement the Evaluate Function
-
Open
BPQ_Player_IsNearObjective
. -
In the
My Blueprint
panel, find theFunctions
section. Hover over Evaluate and click Override. -
This will create the
Event Evaluate
node, which is the entry point for your logic. It receives theTarget Context
andInstigator Context
as inputs and must return aboolean
. -
Implement the logic:
- From
Target Context
, get the player's current location (you could get this from aFact.Player.Location
fact). - From
Instigator Context
, get the Mission Objective Actor's location (you could get this from aFact.MissionObjective.Location
fact). - Calculate the
Distance (Vector)
between the two locations. - Check if the distance is
<
500. - Connect the result of the comparison to the
Return Value
pin of theReturn Node
.
- From
- Compile and save the Blueprint.
Step 3: Use the Query in Blueprints
There are two main ways to use your new Blueprint Query in another Blueprint: as a reusable, configurable variable, or by constructing it dynamically for one-off use.
Option A: As a Reusable Variable (Recommended)
This method is ideal when a query is a core part of an Actor's logic that you might want to evaluate multiple times or allow designers to change easily in child Blueprints.
-
In your player character Blueprint, open the My Blueprint panel and create a new variable. Name it
IsNearObjectiveQuery
. -
Select the new variable. In the Details panel, set its Variable Type to
Fact Query
(Object Reference). -
Make sure the variable is Instance Editable by clicking the "eye" icon next to its name. This is crucial.
-
Compile the Blueprint.
-
With the variable still selected, look at the Details panel. You will now see a dropdown for your variable. Thanks to the
EditInlineNew
property on the baseUFactQuery
class, you can create a unique instance of your query directly here. -
Click the dropdown and select your
BPQ_Player_IsNearObjective
class. -
Now, simply drag your
IsNearObjectiveQuery
variable into the Event Graph to get a reference to it. -
Add an Evaluate Fact Query node and connect the variable to its
Query
input pin. Connect theTarget Context
and the output boolean to aBranch
as you normally would.
- Reusability: You can evaluate the same query object multiple times without reconstructing it.
- Configurability: A level designer can change the query on an instance of a Blueprint in the level, or a game designer can change it on a child Blueprint class, without ever touching the original graph.
- Performance: This is slightly more performant if the query is used often, as the object is only created once when the Actor is initialized.
Option B: Dynamic Construction (For one-off use)
This method is useful inside a function or for a single event where you only need to evaluate the query once and don't need to store it as a property of your class.
- In your player Blueprint (or any other graph), add an Evaluate Fact Query node.
- Instead of selecting a Query Tag in the Details panel, you will provide the Query object directly to the
Query
input pin.
- Instead of selecting a Query Tag in the Details panel, you will provide the Query object directly to the
- To do this, add a Construct Object from Class node.
- Set the
Class
toBPQ_Player_IsNearObjective
.
- Set the
- Connect the
Return Value
of theConstruct Object
node to theQuery
input pin on theEvaluate Fact Query
node. - Connect the
Target Context
and the output boolean as you normally would.
You have now successfully created and used a programmatic query. While it required more setup than a data-driven one, you were able to implement logic that would have been impossible with a simple condition, all while keeping the calling Blueprint clean and readable.
Next Up: Creating and Using Actions