๐ง Neural Affect Matrix For NPCs
Give each NPC persistent emotions and dynamic personalities that evolve through interactions, creating more immersive and believable game experiences.
๐ฏ What is Neural Affect Matrix?
Traditional NPCs rely on conditional logic and donโt understand the source of their actions. This often leads to bugs or incoherent decisions that break immersion and make characters feel artificial. The goal is to make NPCs more human by giving them emotions as an important source of their behavior. Emotions that persist over time, creating unique personalities through experiences.
The system works as a simple api for any game engine or modding tools. You can instantly check how any NPC feels about specific characters or entity, then use that emotional dโฆ
๐ง Neural Affect Matrix For NPCs
Give each NPC persistent emotions and dynamic personalities that evolve through interactions, creating more immersive and believable game experiences.
๐ฏ What is Neural Affect Matrix?
Traditional NPCs rely on conditional logic and donโt understand the source of their actions. This often leads to bugs or incoherent decisions that break immersion and make characters feel artificial. The goal is to make NPCs more human by giving them emotions as an important source of their behavior. Emotions that persist over time, creating unique personalities through experiences.
The system works as a simple api for any game engine or modding tools. You can instantly check how any NPC feels about specific characters or entity, then use that emotional data to create more believable interactions.
Hereโs what makes NPCs unique:
- ๐ง Emotional Understanding: NPCs grasp the emotional meaning behind conversations and actions
- ๐ญ Emotional Memory: Every interaction shapes how they feel in the future
- ๐ญ Evolving Personalities: Characters change and grow based on their experiences
- ๐ Complex Relationships: NPCs can love some characters or entity while disliking others, just like real people
How Emotions Actually Work
Think about how humans work: we feel first, then rationalize our decisions. NPCs should work the same way.
We use Russellโs Circumplex Model, a proven scientific framework that maps human emotions onto a simple 2D coordinate system:
- Valence (X-axis): How pleasant or unpleasant the emotion feels (-1 to +1)
- Arousal (Y-axis): How energetic or calm the emotion is (-1 to +1) This creates an emotional landscape where every feeling can be precisely mapped and tracked over time.
๐ Visualize emotions: Interactive Valence-Arousal Explorer
โก The Process Flow
[ Input Text ] โ [ Neural Affect ML Model ] โ [ Memory Retrieval ] โ
[ Contextual Re-evaluation ] โ [ Emotional Response (Valence, Arousal) ]
- Emotion from text: The model evaluates valence/arousal of the text.
- Memory Integration: Retrieves relevant past interactions
- Reevaluate Emotion: Use memory to reevaluate valence/arousal
- Local Storage: Updates memory with new emotional data Language Support: Currently optimized for English text
๐ Getting Started
Build for production
Since the majority of video game engines run on Windows, weโve streamlined the build process to make integration as simple as possible.
chmod +x build.sh
./build.sh
Find your binaries
๐ dist/
โโโ npc_neural_affect_matrix.dll # Main file
โโโ onnxruntime.dll # AI runtime
โโโ onnxruntime_providers_shared.dll # AI providers
Note: Docker is required to execute build.sh
๐ ๏ธ Development
Project Structure
src/
โโโ api/ # C API endpoints
โ โโโ services/ # Files that contain functions that communicate with modules
โ โโโ endpoints.rs # All the functions that we can call
โ โโโ type.rs # The default types used
โโโ modules/
โ โโโ emotion/ # Neural emotion prediction
โ โโโ memory/ # Memory management
โโโ models/ # Input/output data structures
โโโ config/ # Configuration handling
โโโ utils/ # Utilities and setup
๐งฉ API References
The Neural Affect Matrix provides a C API for seamless integration with game engines like Unity, Unreal Engine, and other C/C++ applications.
initialize_neural_matrix
Initializes the shared neural model that powers emotion prediction. This function must be called before using any other API functions to ensure the AI model is properly loaded and ready for use.
ApiResult* initialize_neural_matrix();
Response Fields:
-
Response (string): Confirmation message indicating successful model initialization Important Notes:
-
This function should be called once at application startup
-
Must be called before creating any NPC sessions
-
If initialization fails, all subsequent API calls will fail
create_npc_session
Initializes a new NPC session with unique emotional state and memory storage. Each session represents an independent NPC instance that can maintain its own relationships, memories, and emotional evolution.
ApiResult* create_npc_session(
const char* config_json,
const char* npc_memory_json
);
Parameters:
-
config_json
(const char*): JSON string containing NPC configuration (required) -
Must be valid JSON matching the configuration structure
-
Cannot be NULL or empty
-
npc_memory_json
(const char*): JSON string containing existing memory data (optional) -
Pass NULL for new NPCs with no prior history
-
Use exported memory from
get_npc_memory()
to restore saved NPCs Response Fields: -
npc_id
(string): Unique identifier for the NPC session, required for all subsequent API calls
remove_npc_session
Cleanly removes an NPC session and frees all associated memory. This permanently deletes the NPCโs emotional state and memory history.
ApiResult* remove_npc_session(const char* npc_id);
Parameters:
-
npc_id
(const char*): Unique NPC session identifier (required) -
Must be a valid UUID string returned from
create_npc_session
-
Cannot be NULL or empty Response Fields:
-
Response (string): Confirmation message indicating successful removal
evaluate_interaction
The core function that processes text input through the neural emotion prediction model, integrates it with the NPCโs memory, and returns an emotional response. This function updates the NPCโs memory with the new interaction.
ApiResult* evaluate_interaction(
const char* npc_id,
const char* text,
const char* source_id
);
Parameters:
-
npc_id
(const char*): NPC session identifier (required) -
Must be a valid UUID from an active session
-
text
(const char*): Input text to process (required) -
Can be dialogue, actions, or events
-
Supports up to 512 characters
-
Works best with English text
-
source_id
(const char*): Identifier for who/what is causing this interaction (optional) -
Pass NULL for anonymous interactions
-
Use consistent IDs (e.g., โplayerโ, โmerchantโ, โenemy_orcโ) for relationship tracking Response Fields:
-
valence
(float, -1.0 to 1.0): Emotional pleasantness/unpleasantness of the response -
arousal
(float, -1.0 to 1.0): Emotional energy/calmness of the response
get_current_emotion
Retrieves the NPCโs current overall emotional state by calculating the weighted average of all memories, with recent interactions having more influence.
ApiResult* get_current_emotion(const char* npc_id);
Parameters:
-
npc_id
(const char*): NPC session identifier (required) Response Fields: -
valence
(float, -1.0 to 1.0): Emotional pleasantness/unpleasantness of the response -
arousal
(float, -1.0 to 1.0): Emotional energy/calmness of the response
get_current_emotion_by_source_id
Retrieves the NPCโs emotional state toward a specific character or entity, based only on interactions with that source.
ApiResult* get_current_emotion_by_source_id(
const char* npc_id,
const char* source_id
);
Parameters:
-
npc_id
(const char*): NPC session identifier (required) -
source_id
(const char*): Identifier for the specific source (required) Response Fields: -
valence
(float, -1.0 to 1.0): Emotional pleasantness/unpleasantness of the response -
arousal
(float, -1.0 to 1.0): Emotional energy/calmness of the response
get_npc_memory
Description: Exports all memory data for an NPC in JSON format. This is essential for save/load systems and debugging emotional state.
ApiResult* get_npc_memory(const char* npc_id);
Parameters:
npc_id
(const char*): NPC session identifier (required) Response Format:
[
{
"id": "mem_001",
"source_id": "player_character",
"text": "Thank you for saving my family",
"valence": 0.85,
"arousal": 0.45,
"past_time": 1440
}
]
clear_npc_memory
Description: Permanently deletes all memory entries for an NPC, effectively resetting their emotional state to the base personality.
ApiResult* clear_npc_memory(const char* npc_id);
Parameters:
npc_id
(const char*): NPC session identifier (required)
free_api_result
Description: Critical function that must be called after every API function to prevent memory leaks. Failure to call this will cause memory accumulation.
void free_api_result(ApiResult* result);
Parameters:
result
(ApiResult*): Pointer returned from any API function (required)
๐ Types
ApiResult structure
All functions return an ApiResult
structure that provides error handling and data management:
typedef struct {
bool success; // Operation success status
char* data; // JSON response data (on success)
char* error; // Error message (on failure)
} ApiResult;
Field Descriptions:
-
success
(bool):true
if operation completed successfully,false
if an error occurred -
data
(char*): JSON-formatted response data whensuccess
istrue
,NULL
when operation fails -
error
(char*): Human-readable error message whensuccess
isfalse
,NULL
on successful operations Configuration Fields: -
identity.name
(string): Display name for the NPC, used in logging and debugging -
identity.background
(string): Character backstory that influences emotional responses and provides context for interactions -
personality.valence
(float, -1.0 to 1.0): Default emotional disposition on the pleasant/unpleasant axis. Positive values create optimistic characters, negative values create pessimistic ones -
personality.arousal
(float, -1.0 to 1.0): Default energy level on the calm/excited axis. Positive values create energetic characters, negative values create calm ones -
memory.decay_rate
(float, 0.0 to 1.0): Rate at which old memories fade over time. Higher values make NPCs forget faster, lower values create longer-lasting impressions
NPC Configuration Structure
NPCs are configured using JSON with the following structure:
{
"identity": {
"name": "Village Guard",
"background": "A loyal guard who protects the village from threats. Has served for 15 years and takes pride in maintaining order."
},
"personality": {
"valence": 0.2,
"arousal": -0.1
},
"memory": {
"decay_rate": 0.1
}
}
Memory Structure
Each NPC maintains a local memory of interactions:
{
"source_id": "player_character",
"text": "Thank you for saving my life",
"valence": 0.85,
"arousal": 0.45,
"past_time": 1440
}
Fields Explained:
source_id
: Who/what caused this emotional memoryvalence
/arousal
: Emotional coordinates for this specific interactionpast_time
: Game time elapsed (in minutes) when this occurred- Memory naturally decays over time based on
decay_rate
๐ค Contributing
We welcome contributions! Hereโs how to get started:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature
- Make your changes and add tests
- Test your changes:
cargo test
- Open a Pull Request
๐ Resources & Research
AI Models
- Model: NPC Valence-Arousal Prediction (ONNX)
- Training Dataset: NPC Valence-Arousal Dataset (1K+ video game dialogues)
- Upcoming: Expanded dataset with 100K+ samples in development
Scientific Background
- Russellโs Circumplex Model of Affect
- Memory decay and emotional persistence research
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions