📋 Overview
The MedievalBehaviorEngine is the core execution system that drives NPC behaviors based on personality profiles, time schedules, and environmental factors. It processes schedule-based activities, manages social interactions, and coordinates with the MedievalNPCAIController to create authentic medieval character behaviors.
🔄 Behavior Execution Workflow
Schedule Check
→
Personality Evaluation
→
Behavior Selection
→
Action Execution
→
Social Update
⏰ Schedule Management System
The engine operates on a five-period daily schedule that reflects authentic medieval timekeeping and activities:
🌅 Morning (6:00 - 9:00)
Early day activities and preparations
Work begins, market setup, prayers, breakfast
☀️ Noon (9:00 - 12:00)
Peak working hours and social activity
Craft work, farming, trading, socializing
🌞 Afternoon (12:00 - 15:00)
Continued work and community engagement
Lunch, workshops, markets, guild meetings
🌇 Evening (15:00 - 18:00)
Work conclusion and social time
Tool cleanup, tavern visits, family time
🌙 Night (18:00 - 6:00)
Rest and limited activities
Dinner, rest, night watch, tavern socializing
🎭 Role-Based Behavior System
The engine implements specialized behaviors for different medieval social roles:
Child Behaviors
case NPCSocialRole.Child:
switch (schedulePeriod)
{
case NPCSchedulePeriod.Morning:
// Children help with simple chores or play
if (Random.Range(0f, 1f) < 0.6f)
ExecuteChildChoreBehavior(controller);
else
ExecutePlayBehavior(controller);
break;
case NPCSchedulePeriod.Noon:
// Attend lessons or apprenticeship
ExecuteLearningBehavior(controller);
break;
case NPCSchedulePeriod.Afternoon:
// Continue learning or help family
ExecuteFamilyAssistanceBehavior(controller);
break;
case NPCSchedulePeriod.Evening:
// Play with other children or family time
ExecuteChildSocialBehavior(controller);
break;
case NPCSchedulePeriod.Night:
// Limited night activities for children
if (Random.Range(0f, 1f) < 0.2f)
ExecuteSneakOutBehavior(controller);
break;
}
break;
Adult Behaviors
case NPCSocialRole.Adult:
switch (schedulePeriod)
{
case NPCSchedulePeriod.Morning:
// Work activities based on occupation
ExecuteWorkBehavior(controller);
break;
case NPCSchedulePeriod.Noon:
// Peak work hours and market activities
ExecutePeakWorkBehavior(controller);
break;
case NPCSchedulePeriod.Afternoon:
// Continue work or guild activities
ExecuteGuildBehavior(controller);
break;
case NPCSchedulePeriod.Evening:
// Social activities and family time
if (Random.Range(0f, 1f) < 0.4f)
ExecuteTavernBehavior(controller);
else
ExecuteFamilyBehavior(controller);
break;
case NPCSchedulePeriod.Night:
// Limited activities, mostly rest or guard duty
ExecuteNightAdultBehavior(controller);
break;
}
break;
🗣️ Social Interaction System
The engine manages complex social interactions between NPCs, including conversations, relationship building, and reputation effects:
private void ExecuteTalkingBehavior(MedievalNPCAIController controller)
{
// Find nearby NPC to talk to
var nearbyNPC = FindNearestFriendlyNPC(controller);
if (nearbyNPC != null)
{
controller.LookAt(nearbyNPC.transform.position);
var otherController = nearbyNPC.GetComponent<MedievalNPCAIController>();
if (otherController != null)
{
controller.StartConversation(otherController);
}
}
}
Social Behavior Types
| Behavior Type |
Description |
Personality Influence |
| Conversations |
Dialogue between NPCs |
CurrentSociability, CheerfulnessWeight |
| Greetings |
Polite acknowledgments |
HonorCode, CurrentSociability |
| Trading |
Commercial interactions |
HonestyWeight, DeceitWeight |
| Arguing |
Disputes and disagreements |
CurrentMorality, HonorCode |
| Flirting |
Romantic interactions |
CheerfulnessWeight, CurrentSociability |
🎯 Behavior Scoring System
The engine uses a sophisticated scoring system to determine the most appropriate behavior based on personality, schedule, and environmental factors:
private float CalculateBehaviorScore(MedievalNPCAIController controller,
NPCBehaviorType behaviorType, NPCSchedulePeriod period)
{
var profile = controller.BehaviorProfile;
float score = 0f;
switch (behaviorType)
{
case NPCBehaviorType.Work:
score += profile.DisciplineWeight * 10f;
score += profile.CraftsmanshipPride * 8f;
score += profile.FamilyDuty * 6f;
break;
case NPCBehaviorType.Socialize:
score += profile.CurrentSociability * 12f;
score += profile.CheerfulnessWeight * 8f;
score += profile.CommunityResponsibility * 6f;
break;
case NPCBehaviorType.Pray:
score += profile.ReligiousPiety * 15f;
score += profile.HonorCode * 5f;
break;
case NPCBehaviorType.Trade:
score += profile.HonestyWeight * 8f;
score += profile.DeceitWeight * 4f;
score += profile.CurrentSociability * 6f;
break;
}
// Apply schedule modifiers
score *= GetScheduleModifier(behaviorType, period);
// Add randomness for variety
score += Random.Range(-5f, 5f);
return Mathf.Max(0f, score);
}
⚡ Performance Optimizations
The behavior engine includes several performance optimizations:
⚡ Optimization Features
- Behavior Caching: Recently calculated behavior scores are cached to avoid redundant calculations
- Distance-Based Updates: NPCs far from the player update less frequently
- LOD System: Level-of-detail behavior complexity based on distance and importance
- Batch Processing: Similar behaviors are processed in batches to improve CPU cache efficiency
- Event-Driven Updates: Behaviors only recalculate when significant changes occur
🔧 Integration with AI Controller
The behavior engine integrates seamlessly with the MedievalNPCAIController:
public class MedievalNPCAIController : MonoBehaviour
{
private MedievalBehaviorEngine behaviorEngine;
private NPCBehaviorProfile behaviorProfile;
void Start()
{
behaviorEngine = new MedievalBehaviorEngine();
behaviorEngine.Initialize(this, behaviorProfile);
}
void Update()
{
// Update behavior based on current schedule
behaviorEngine.UpdateBehavior(Time.time);
}
public void SetBehaviorProfile(NPCBehaviorProfile profile)
{
behaviorProfile = profile;
behaviorEngine?.UpdateProfile(profile);
}
}
🌍 Environmental Factors
The behavior engine considers various environmental factors that influence NPC decisions:
Weather Effects
private float GetWeatherModifier(NPCBehaviorType behaviorType)
{
var weatherSystem = MedievalWeatherSystem.Instance;
float modifier = 1f;
switch (weatherSystem.CurrentWeather)
{
case WeatherType.Rain:
if (behaviorType == NPCBehaviorType.Work) modifier *= 0.8f;
if (behaviorType == NPCBehaviorType.Socialize) modifier *= 0.6f;
if (behaviorType == NPCBehaviorType.Pray) modifier *= 1.2f; // Seek shelter in church
break;
case WeatherType.Snow:
if (behaviorType == NPCBehaviorType.Work) modifier *= 0.7f;
if (behaviorType == NPCBehaviorType.Trade) modifier *= 0.5f;
break;
case WeatherType.Storm:
if (behaviorType == NPCBehaviorType.Work) modifier *= 0.3f;
if (behaviorType == NPCBehaviorType.Socialize) modifier *= 0.2f;
if (behaviorType == NPCBehaviorType.Pray) modifier *= 1.5f;
break;
}
return modifier;
}
Seasonal Activities
🌸 Spring
Planting season activities
Increased farming work, market preparation, spring cleaning
☀️ Summer
Peak activity season
Longer work hours, festivals, increased trade
🍂 Autumn
Harvest and preparation
Harvest work, food preservation, winter preparation
❄️ Winter
Limited outdoor activities
Indoor crafts, storytelling, reduced market activity
🔍 Debugging and Monitoring
The behavior engine includes comprehensive debugging tools for development and troubleshooting:
Debug Visualization
public class BehaviorEngineDebugger : MonoBehaviour
{
[Header("Debug Settings")]
public bool showBehaviorScores = true;
public bool showScheduleInfo = true;
public bool showSocialConnections = true;
void OnDrawGizmos()
{
if (Application.isPlaying == false) return;
var engine = GetComponent<MedievalNPCAIController>().BehaviorEngine;
if (showBehaviorScores)
{
DrawBehaviorScores(engine);
}
if (showScheduleInfo)
{
DrawScheduleInfo(engine);
}
if (showSocialConnections)
{
DrawSocialConnections(engine);
}
}
private void DrawBehaviorScores(MedievalBehaviorEngine engine)
{
var scores = engine.GetCurrentBehaviorScores();
Vector3 offset = Vector3.up * 2f;
foreach (var score in scores)
{
Gizmos.color = Color.Lerp(Color.red, Color.green, score.Value / 100f);
Gizmos.DrawSphere(transform.position + offset, 0.2f);
// Draw score text
UnityEditor.Handles.Label(transform.position + offset,
$"{score.Key}: {score.Value:F1}");
offset += Vector3.up * 0.5f;
}
}
}
Behavior Logging
public void LogBehaviorDecision(NPCBehaviorType selectedBehavior, float score)
{
var logEntry = new BehaviorLogEntry
{
timestamp = Time.time,
npcName = gameObject.name,
behaviorType = selectedBehavior,
score = score,
schedulePeriod = CurrentSchedulePeriod,
personalityFactors = GetRelevantPersonalityFactors(selectedBehavior)
};
BehaviorLogger.LogDecision(logEntry);
// Detailed logging for debugging
if (BehaviorLogger.IsVerboseLoggingEnabled)
{
Debug.Log($"[{Time.time:F1}] {gameObject.name}: Selected {selectedBehavior} " +
$"(Score: {score:F2}, Period: {CurrentSchedulePeriod}, " +
$"Weather: {MedievalWeatherSystem.Instance.CurrentWeather})");
}
}
🎪 Advanced Behavior Patterns
The engine supports complex multi-step behaviors and emergent patterns:
Chain Behaviors
public class BehaviorChain
{
private Queue<NPCBehaviorType> behaviorSequence;
private MedievalNPCAIController controller;
public BehaviorChain(MedievalNPCAIController controller, params NPCBehaviorType[] behaviors)
{
this.controller = controller;
behaviorSequence = new Queue<NPCBehaviorType>(behaviors);
}
public void ExecuteNext()
{
if (behaviorSequence.Count > 0)
{
var nextBehavior = behaviorSequence.Dequeue();
controller.SetCurrentBehavior(nextBehavior);
// Subscribe to behavior completion
controller.OnBehaviorCompleted += OnBehaviorCompleted;
}
}
private void OnBehaviorCompleted(NPCBehaviorType completedBehavior)
{
controller.OnBehaviorCompleted -= OnBehaviorCompleted;
// Execute next behavior in sequence
if (behaviorSequence.Count > 0)
{
ExecuteNext();
}
else
{
// Chain completed, return to default behavior
controller.ReturnToDefaultBehavior();
}
}
}
// Example usage: Blacksmith work routine
var blacksmithRoutine = new BehaviorChain(controller,
NPCBehaviorType.Work, // Forge items
NPCBehaviorType.Trade, // Sell to customers
NPCBehaviorType.Socialize, // Chat with other merchants
NPCBehaviorType.Work // Clean up and prepare for next day
);
Emergent Behavior Patterns
private void CheckForEmergentBehaviors()
{
// Crowd formation - NPCs gather when multiple characters start socializing
var nearbySocializers = FindNearbyNPCsWithBehavior(NPCBehaviorType.Socialize, 10f);
if (nearbySocializers.Count >= 3)
{
// Form a crowd - attract more NPCs to socialize
foreach (var npc in nearbySocializers)
{
npc.IncreaseSocialAttraction(1.5f);
}
}
// Work partnerships - NPCs with similar occupations work together
var nearbyWorkers = FindNearbyNPCsWithBehavior(NPCBehaviorType.Work, 15f);
foreach (var worker in nearbyWorkers)
{
if (worker.Occupation == this.controller.Occupation)
{
// Form work partnership
controller.FormWorkPartnership(worker);
worker.FormWorkPartnership(controller);
}
}
// Avoidance behaviors - NPCs avoid suspicious or dangerous characters
var suspiciousNPCs = FindNPCsWithLowReputation(0.3f, 20f);
foreach (var suspicious in suspiciousNPCs)
{
if (controller.BehaviorProfile.CurrentMorality > 0.7f)
{
controller.AddAvoidanceTarget(suspicious);
}
}
}
📊 Performance Metrics
Monitor behavior engine performance with built-in metrics:
| Metric |
Description |
Target Value |
| Update Frequency |
How often behaviors are recalculated |
1-2 seconds for nearby NPCs |
| Behavior Cache Hit Rate |
Percentage of cached behavior scores reused |
> 70% |
| Social Interaction Success |
Percentage of successful social interactions |
> 80% |
| Schedule Adherence |
How well NPCs follow their daily schedules |
> 85% |
| Memory Usage |
Memory consumed by behavior profiles |
< 1MB per 100 NPCs |