Telepathy Implementation V1 - Part 1

Overview

This is the first of a multipart series showcasing my solution for the telepathy ability I described in a previous planning post. The system, even in this prototype format, includes multiple Blueprints, graphs, post-processing effects, and audio logic, so I’ve chosen to split it into parts for easier consumption.

It can be modified to work as a standalone system. But for my purposes, I designed it to work with the Narrative Pro 2 framework plugin and GAS. If you want to replicate it as-is, you would need both in your project.

The four objects I’m going to go through in this post are BPC_AmbientThoughtsManager, BPC_NPC_Thoughts, BP_MindRead_Thoughts_Actor, and PDA_AmbientThoughts. These objects are responsible for storing and managing an NPC’s ambient thoughts.

In simple terms, the NPC owns a PDA_AmbientThoughts data asset, a BP_MindRead_Thoughts_Actor, and a BPC_NPC_Thoughts component. The data asset is where I set the information for each NPC, such as their thought audio, subtitles, and clue timestamps. The BP_MindRead_Thoughts_Actor contains the audio component and plays the thought sound clip.

When the player activates the mind-reading ability, the BP_MindRead_Thoughts_Actor moves through the world from the NPC to the player and attaches itself to the player character. When the ability ends, it moves back to the NPC. Because the sound is spatialized, it gradually becomes louder as the actor moves closer to the player, creating the illusion that the player is “concentrating” on the thought—more on this in Part 2.

BPC_NPC_Thoughts is a component attached to the NPC. It serves as the NPC-side manager of sorts. BPC_AmbientThoughtsManager is a component that lives on the player character and manages the player-side logic.

PDA_AmbientThoughts

This is a primary data asset that is associated with each BP_NPCTelepathDefinition (it’s my subclassed version of the Narrative Pro NPC definition).

Variables

Modifiable

NameTypeComments
ThoughtsSound Wave Object ReferenceThis is the audio file that represents the thoughts of the NPC
SubtitlesData Table Object ReferenceThis data table contains the subtitles associated with the thought audio file. It has a subtle line and a timestamp indicating when it should appear.
ClueS Thought Clue ArrayThis array is contained in clues and timestamps. It relates to how I integrate this telepathy into Narrative Pro’s quest system.

Hidden

NameTypeComments
IndexIntegerAn index used to parse the subtitles
AudioAudio Component Object ReferenceA reference to the audio component located in the BP_MindRead_Thoughts_Actor
DisplaySubtitlesBooleanI only want to display the subtitles when the player is currently reading the character's mind. This variable controls that.
NarrativeHudWBP Telepath Narrative Tale Overlay Object ReferenceA reference to a subclass of the Narrative Pro tales HUD overlay to display the subtitles.
PlayBackTimeFloatA modulo of the RawPlaybackTime and the audio clip duration
RawPlaybackTimeFloatThe current timestamp of the thought audio clip

Functions

In this Data asset, I have two functions. Both are fairly simple.

The first initiates some variables and tells the event graph to start working.

Play
I/ONameType
AudioComponentAudio Component Object Reference
NarrativeHudWBP Telepath Narrative Tale Overlay Object Reference
None

The second. Controls the subtitle state and resets the HUD if I need them off.

SetDisplaySubtitles
I/ONameType
DisplayBoolean
None

Event Graph

The event graph is also fairly simple, but there is a bit of a catch. I have to start the clip only after binding the audio component to the playback event, or it can cause problems. Then, if necessary, I handle the subtitles.

BP_MindRead_Thoughts_Actor

This object was created to move between the NPC and the player, and back, during the mind-reading ability to create a seamless audio change while the player is concentrating/unconcentrating.

Variables

NameTypeComment
SphereStatic mesh componentA visual component so I can see where the thought actor is. I'll remove it when I'm done.
AudioAudio componentTo play the thought wave clip
OwnerThoughtManagerBPC_NPC_Thoughts object referenceA reference to the BPC_NPC_Thoughts of the owning NPC
MoveTimeFloatHow long does it take for the thought actor to move from the NPC to the player? More on this in part 2.
NormalizedTimeFloatA normalized version of the MoveTime while taking into account the delta time
TargetNarrativeCharacter object referenceThe character this object needs to move to.
StartPosVectorSave where the object started the move
CurrentAmbientThoughtsPDA_AmbientThoughts object referenceI keep a reference to the data asset so I can control when to display the subtitles.

Functions

Normalizing the time gives me a clean 0–1 value, so I can use it to control the transition predictably and return when the move is over.

UpdateTime
I/ONameType
DeltaTimeFloat
EndBoolean

Lerping between the start position and the target character’s head socket.

Move
I/ONameType
None
None

When I reach the object’s target, I disable tick.

ReachedTarget
I/ONameType
None
None
Initiate
I/ONameType
VolumeFloat
CurrentAmbientThoughtsPDA_AmbientThoughts
None

I’m getting the target narrative character, the duration of the move, and saving the actor’s current position before initiating the move by enabling tick.

InitiateMove
I/ONameType
TargetActorNarrativeCharacter object referance
Timefloat
None

Event Graph

BPC_NPC_Thoughts

Variables

NameTypeComment
MindReaderPlayerComponentBPC_Ambient_Thoughts_Manager object referenceA reference to the BPC_Ambient_Thoughts_Manager that sits on the player
CurrentVolumeFloatThe volume of this specific CurrentThoughtsActor
NPCBP_Telepath_NPC object referenceThe NPC that owns this component
CurrentThoughtsActorBP_Mind_Read_Thoughts_Actor object referenceAn object reference to the BP_Mind_Read_Thoughts_Actor belonging to the NPC.
ThoughtClueBP_ThoughtClue object reference array object referenceThis is to handle the clues associated with these thoughts. More on that in part 3.

Functions

This function controls the gradual volume change for the ambient thought audio. Instead of snapping the volume from one value to another, it uses elapsed time and a curve to smoothly fade from the starting volume to the target volume. This lets the mind-reading audio feel more natural when the player starts concentrating or stops concentrating, because the thought doesn’t suddenly appear or disappear.

AmbientThoughtsTimeGraphGradualChangeCalculation
I/ONameType
ElapsedTimeFloat
StartVolumeFloat
TargetVolumeFloat
TotalTimeFloat
CurveCurve Float reference
None

Here, I’m just creating the thought actor and placing it. When the game loads, I sometimes encounter an issue where the character's head joint doesn’t exist yet, so I’m just using the NPC location for it now. If I ever want to have a special effect on that thought actor, I would need to change that.

CreateThoughtsActor
I/ONameType
AmbientThoughtsPDA_AmbientThought
None

I’m not a huge fan of this function. The only thing it does is tell the CurrentThoughtActor to move. It’s one of the problems that I see in this system and one of the things I would like to change.

StartMoveThoughtActor
I/ONameType
Target ActorNarrative Character
TimeFloat
None

This is similar to the function above. A Matrioshka function. It’s to get a variable that is inside a thing that is inside another thing.

GetThoughtPlaybackTime
I/ONameType
None
ThoughtPlaybackTimeFloat

Same type of Matrioshka function. Except that this time it’s related to integrating telepathy with the Narrative pro Quest system. More on this in Part 3

GetClues
I/ONameType
None
CluesS_ThoughtClue struct array

Macro

This macro changes the volume in controlled steps, using the current volume to determine its position between the minimum and maximum values. It then uses that position to select a change rate between the minimum and maximum increment values, so the volume can rise or fall more smoothly rather than changing by the same fixed amount each time.

CalculateAmbientThoughtsVolumeChange
I/ONameType
None
NewVolumeFloat

Event Graph

The event graph here is a bit bigger. But I’m basically just initializing some variables and binding to events that let me easily control volume changes for all NPCs at once.

BPC_AmbientThoughtsManager

This class is big, and there are a lot of things going on here. I’ll try to divide things into subjects and explain them as best I can.

Variables

Components

NameTypeComment
PostProcessPost Process Component

Volume

NameTypeComment
AmbientThoughtsVolumeMaxFloat
AmbientThoughtsVolumeMinFloat
GeneralAmbientThoughtVolumeFloat
AmbientThoughtsChangeRateMaxFloat
AmbientThoughtsChangeRateMinFloat
ConfortableVolumeFloat
OldVolumeFloat

Post Processing

There are 4 post-processing variables that I’ll discuss in part 3.

Mind Reading Ability Setting

NameTypeComment
ChargeTimeFloat
CoolDownFloat
RangeInteger
MindReadingVolumeAdditionFloat

Functions

Initialize
I/ONameType
None
None

Volume

AmbientThoughtsGradualChange
I/ONameType
None
None
SetOldVolume
I/ONameType
None
None

Post Processing

There are 4 post-processing functions that I’ll discuss in part 3.

Event Graph

None


To do