PlayKit.ai

NPC Conversations

Create AI-powered NPC dialogues in Unreal Engine

NPC Conversations

UPlayKitNPCClient is an Actor Component that manages AI-powered NPC conversations with automatic history tracking, memory, actions, and reply predictions.

Setup

Blueprint

  1. Select your NPC Actor and click Add Component → search for PlayKit NPC Client
  2. Call Setup NPC (from PlayKit Blueprint Library) in Begin Play
  3. Set the Character Design property in the Details panel
  4. Bind to On Response and On Error events

C++

#include "NPC/PlayKitNPCClient.h"
#include "PlayKitBlueprintLibrary.h"

UCLASS()
class ANPCActor : public AActor
{
    GENERATED_BODY()

    UPROPERTY(VisibleAnywhere)
    UPlayKitNPCClient* NPCClient;

    virtual void BeginPlay() override;

    UFUNCTION()
    void HandleNPCResponse(const FNPCResponse& Response);
};

void ANPCActor::BeginPlay()
{
    Super::BeginPlay();

    NPCClient = FindComponentByClass<UPlayKitNPCClient>();
    UPlayKitBlueprintLibrary::SetupNPC(NPCClient);

    NPCClient->SetCharacterDesign(TEXT(
        "You are Gareth, a grizzled blacksmith in a medieval village. "
        "You speak in a gruff but friendly manner. "
        "You can forge weapons and armor, and know local rumors."
    ));

    NPCClient->OnResponse.AddDynamic(this, &ANPCActor::HandleNPCResponse);
}

void ANPCActor::HandleNPCResponse(const FNPCResponse& Response)
{
    if (Response.bSuccess)
        DialogueWidget->SetNPCText(Response.Content);
}

Basic Conversation

NPCClient->Talk(TEXT("Hello, what do you sell?"));

The NPC automatically maintains conversation history across calls. Subsequent messages build on prior context.

Streaming Responses

void ANPCActor::BeginPlay()
{
    Super::BeginPlay();
    NPCClient = FindComponentByClass<UPlayKitNPCClient>();
    UPlayKitBlueprintLibrary::SetupNPC(NPCClient);
    NPCClient->OnStreamChunk.AddDynamic(this, &ANPCActor::HandleChunk);
    NPCClient->OnStreamComplete.AddDynamic(this, &ANPCActor::HandleComplete);
}

void ANPCActor::HandleChunk(const FString& Chunk)
{
    DialogueWidget->AppendText(Chunk);
}

void ANPCActor::StartConversation()
{
    NPCClient->TalkStream(TEXT("Tell me the legend of this land"));
}

Character Design

The character design defines the NPC's personality, knowledge, and behavioral constraints.

NPCClient->SetCharacterDesign(TEXT(
    "You are Luna, a mysterious fortune teller. "
    "You speak in riddles and metaphors. "
    "You know secrets about the player's destiny but reveal them cryptically."
));

For NPCs with strict knowledge boundaries:

NPCClient->SetCharacterDesign(TEXT(
    "You are a guard stationed at the castle gate. "
    "You only know about the castle schedule, your captain Sir Roland, "
    "and recent bandit sightings in the forest. "
    "Decline to discuss anything outside your knowledge."
));

Memory System

Persist facts across conversation resets using named memory entries.

NPCClient->SetMemory(TEXT("PlayerName"), TEXT("Alex"));
NPCClient->SetMemory(TEXT("LastQuest"), TEXT("found the lost amulet"));

FString PlayerName = NPCClient->GetMemory(TEXT("PlayerName"));

Memory is included in every request — ideal for information that should persist even after ClearHistory().

History Management

TArray<FNPCMessage> History = NPCClient->GetHistory();

NPCClient->ClearHistory();

NPCClient->RevertHistory();

FString SaveData = NPCClient->SaveHistory();
NPCClient->LoadHistory(SaveData);

NPC Actions

NPCs can trigger game actions through structured responses. When the NPC decides to perform an action, OnActionTriggered fires with the action name and parameters.

NPCClient->OnActionTriggered.AddDynamic(this, &ANPCActor::HandleAction);

void ANPCActor::HandleAction(const FNPCActionCall& ActionCall)
{
    if (ActionCall.Name == TEXT("give_item"))
    {
        FString ItemId = ActionCall.Arguments.FindRef(TEXT("item_id"));
        PlayerInventory->AddItem(ItemId);
        NPCClient->ReportActionResult(ActionCall.CallId, TEXT("Item given successfully"));
    }
}

Define available actions in the character design:

NPCClient->SetCharacterDesign(TEXT(
    "You are a quest giver. "
    "When you want to give the player an item, call the give_item action with the item_id. "
    "Available items: health_potion, iron_sword, map."
));

Reply Predictions

Generate suggested player responses to display as dialogue options.

NPCClient->bAutoGenerateReplyPredictions = true;
NPCClient->PredictionCount = 4;

NPCClient->OnReplyPredictionsGenerated.AddDynamic(this, &ANPCActor::HandlePredictions);

void ANPCActor::HandlePredictions(const TArray<FString>& Predictions)
{
    for (const FString& Option : Predictions)
        CreateDialogueButton(Option);
}

To generate predictions on demand:

NPCClient->GenerateReplyPredictions(3);

Temperature

NPCClient->SetTemperature(0.3f); // Consistent, predictable responses
NPCClient->SetTemperature(0.9f); // Creative, varied responses

Events Reference

EventParametersDescription
OnResponseFNPCResponse ResponseFired when NPC responds (non-streaming)
OnStreamChunkFString ChunkFired for each streaming text chunk
OnStreamCompleteFString FullContentFired when streaming finishes
OnActionTriggeredFNPCActionCall ActionCallFired when NPC triggers an action
OnReplyPredictionsGeneratedTArray<FString> PredictionsFired when reply predictions are ready
OnErrorFString ErrorCode, FString ErrorMessageFired on request failure

Next Steps