Skip to content

Console Variables (CVars) Guide

Console Variables provide runtime control over game parameters without recompilation. Essential for tuning and debugging.


Implementation Strategy

1. Global CVars Module

Create Source/Platformer/Utilities/PlatformerCVars.h:

cpp
#pragma once

#include "CoreMinimal.h"
#include "HAL/IConsoleManager.h"

class PLATFORMER_API FPlatformerCVars
{
public:
    // Character Movement
    static TAutoConsoleVariable<float> CharacterWalkSpeed;
    static TAutoConsoleVariable<float> CharacterSprintSpeed;
    static TAutoConsoleVariable<float> CharacterJumpHeight;
    static TAutoConsoleVariable<int32> CharacterJumpCount;
    
    // Camera
    static TAutoConsoleVariable<float> CameraDistance;
    static TAutoConsoleVariable<float> CameraLagSpeed;
    static TAutoConsoleVariable<float> CameraRotationLag;
    static TAutoConsoleVariable<float> CameraFOV;
    
    // Interaction System
    static TAutoConsoleVariable<float> InteractionRange;
    static TAutoConsoleVariable<float> InteractionRadius;
    static TAutoConsoleVariable<bool> ShowInteractionDebug;
    static TAutoConsoleVariable<float> InteractionCooldown;
    
    // AI System
    static TAutoConsoleVariable<float> EnemySightRange;
    static TAutoConsoleVariable<float> EnemyHearingRange;
    static TAutoConsoleVariable<float> EnemyAttackRange;
    static TAutoConsoleVariable<float> EnemyPatrolSpeed;
    static TAutoConsoleVariable<float> EnemyChaseSpeed;
    
    // Debug and Performance
    static TAutoConsoleVariable<bool> ShowDebugInfo;
    static TAutoConsoleVariable<bool> ShowPerformanceStats;
    static TAutoConsoleVariable<int32> MaxEnemyCount;
    static TAutoConsoleVariable<bool> EnableAI;
    
    // Initialize all CVars
    static void Initialize();
};

Implementation Source/Platformer/Utilities/PlatformerCVars.cpp:

cpp
#include "PlatformerCVars.h"

// Character Movement CVars
TAutoConsoleVariable<float> FPlatformerCVars::CharacterWalkSpeed(
    TEXT("platformer.Character.WalkSpeed"),
    600.0f,
    TEXT("Character walking speed"),
    ECVF_Cheat | ECVF_Scalability
);

TAutoConsoleVariable<float> FPlatformerCVars::CharacterSprintSpeed(
    TEXT("platformer.Character.SprintSpeed"),
    900.0f,
    TEXT("Character sprinting speed"),
    ECVF_Cheat | ECVF_Scalability
);

TAutoConsoleVariable<float> FPlatformerCVars::CharacterJumpHeight(
    TEXT("platformer.Character.JumpHeight"),
    700.0f,
    TEXT("Character jump Z velocity"),
    ECVF_Cheat
);

TAutoConsoleVariable<int32> FPlatformerCVars::CharacterJumpCount(
    TEXT("platformer.Character.JumpCount"),
    2,
    TEXT("Maximum number of jumps (1 = no double jump)"),
    ECVF_Cheat
);

// Camera CVars
TAutoConsoleVariable<float> FPlatformerCVars::CameraDistance(
    TEXT("platformer.Camera.Distance"),
    450.0f,
    TEXT("Camera boom arm length"),
    ECVF_Cheat
);

TAutoConsoleVariable<float> FPlatformerCVars::CameraLagSpeed(
    TEXT("platformer.Camera.LagSpeed"),
    12.0f,
    TEXT("Camera position lag speed"),
    ECVF_Cheat
);

TAutoConsoleVariable<float> FPlatformerCVars::CameraRotationLag(
    TEXT("platformer.Camera.RotationLag"),
    10.0f,
    TEXT("Camera rotation lag speed"),
    ECVF_Cheat
);

TAutoConsoleVariable<float> FPlatformerCVars::CameraFOV(
    TEXT("platformer.Camera.FOV"),
    90.0f,
    TEXT("Camera field of view"),
    ECVF_Cheat
);

// Interaction System CVars
TAutoConsoleVariable<float> FPlatformerCVars::InteractionRange(
    TEXT("platformer.Interaction.Range"),
    400.0f,
    TEXT("Maximum interaction trace distance"),
    ECVF_Cheat
);

TAutoConsoleVariable<float> FPlatformerCVars::InteractionRadius(
    TEXT("platformer.Interaction.Radius"),
    30.0f,
    TEXT("Interaction sphere trace radius"),
    ECVF_Cheat
);

TAutoConsoleVariable<bool> FPlatformerCVars::ShowInteractionDebug(
    TEXT("platformer.Interaction.ShowDebug"),
    false,
    TEXT("Show interaction system debug visualization"),
    ECVF_Cheat
);

TAutoConsoleVariable<float> FPlatformerCVars::InteractionCooldown(
    TEXT("platformer.Interaction.Cooldown"),
    0.5f,
    TEXT("Minimum time between interactions"),
    ECVF_Cheat
);

// AI System CVars
TAutoConsoleVariable<float> FPlatformerCVars::EnemySightRange(
    TEXT("platformer.AI.SightRange"),
    1800.0f,
    TEXT("Enemy AI sight perception range"),
    ECVF_Cheat
);

TAutoConsoleVariable<float> FPlatformerCVars::EnemyHearingRange(
    TEXT("platformer.AI.HearingRange"),
    1000.0f,
    TEXT("Enemy AI hearing perception range"),
    ECVF_Cheat
);

TAutoConsoleVariable<float> FPlatformerCVars::EnemyAttackRange(
    TEXT("platformer.AI.AttackRange"),
    150.0f,
    TEXT("Enemy AI attack range"),
    ECVF_Cheat
);

TAutoConsoleVariable<float> FPlatformerCVars::EnemyPatrolSpeed(
    TEXT("platformer.AI.PatrolSpeed"),
    200.0f,
    TEXT("Enemy AI patrol movement speed"),
    ECVF_Cheat
);

TAutoConsoleVariable<float> FPlatformerCVars::EnemyChaseSpeed(
    TEXT("platformer.AI.ChaseSpeed"),
    500.0f,
    TEXT("Enemy AI chase movement speed"),
    ECVF_Cheat
);

// Debug and Performance CVars
TAutoConsoleVariable<bool> FPlatformerCVars::ShowDebugInfo(
    TEXT("platformer.Debug.ShowInfo"),
    false,
    TEXT("Show general debug information overlay"),
    ECVF_Cheat
);

TAutoConsoleVariable<bool> FPlatformerCVars::ShowPerformanceStats(
    TEXT("platformer.Debug.ShowPerformance"),
    false,
    TEXT("Show performance statistics"),
    ECVF_Cheat
);

TAutoConsoleVariable<int32> FPlatformerCVars::MaxEnemyCount(
    TEXT("platformer.Performance.MaxEnemies"),
    20,
    TEXT("Maximum number of active enemies"),
    ECVF_Scalability
);

TAutoConsoleVariable<bool> FPlatformerCVars::EnableAI(
    TEXT("platformer.AI.Enable"),
    true,
    TEXT("Enable/disable AI processing"),
    ECVF_Cheat
);

void FPlatformerCVars::Initialize()
{
    // CVars are automatically registered via TAutoConsoleVariable
    // This function can be used for any additional setup
    UE_LOG(LogTemp, Log, TEXT("Platformer CVars initialized"));
}

Integration with Game Systems

1. Character Movement Integration

In APlatformCharacter::BeginPlay():

cpp
void APlatformCharacter::BeginPlay()
{
    Super::BeginPlay();
    
    // Apply CVar values at startup
    ApplyCVarSettings();
    
    // Register for CVar change notifications
    RegisterCVarCallbacks();
}

void APlatformCharacter::ApplyCVarSettings()
{
    if (UCharacterMovementComponent* MovementComp = GetCharacterMovement())
    {
        MovementComp->MaxWalkSpeed = FPlatformerCVars::CharacterWalkSpeed.GetValueOnGameThread();
        MovementComp->JumpZVelocity = FPlatformerCVars::CharacterJumpHeight.GetValueOnGameThread();
        MovementComp->JumpMaxCount = FPlatformerCVars::CharacterJumpCount.GetValueOnGameThread();
        
        // Update sprint speed reference
        SprintSpeed = FPlatformerCVars::CharacterSprintSpeed.GetValueOnGameThread();
    }
    
    UE_LOG(LogTemp, Log, TEXT("Applied CVar settings to character %s"), *GetName());
}

void APlatformCharacter::RegisterCVarCallbacks()
{
    // Register callback for dynamic updates
    FPlatformerCVars::CharacterWalkSpeed->AsVariable()->SetOnChangedCallback(
        FConsoleVariableDelegate::CreateUObject(this, &APlatformCharacter::OnWalkSpeedChanged)
    );
    
    FPlatformerCVars::CharacterSprintSpeed->AsVariable()->SetOnChangedCallback(
        FConsoleVariableDelegate::CreateUObject(this, &APlatformCharacter::OnSprintSpeedChanged)
    );
}

void APlatformCharacter::OnWalkSpeedChanged(IConsoleVariable* Variable)
{
    if (UCharacterMovementComponent* MovementComp = GetCharacterMovement())
    {
        float NewSpeed = Variable->GetFloat();
        MovementComp->MaxWalkSpeed = NewSpeed;
        
        // If not sprinting, update current speed
        if (!bIsSprinting)
        {
            WalkSpeed = NewSpeed;
        }
        
        UE_LOG(LogTemp, Log, TEXT("Walk speed changed to %.1f for %s"), NewSpeed, *GetName());
    }
}

void APlatformCharacter::OnSprintSpeedChanged(IConsoleVariable* Variable)
{
    float NewSprintSpeed = Variable->GetFloat();
    SprintSpeed = NewSprintSpeed;
    
    // If currently sprinting, apply immediately
    if (bIsSprinting)
    {
        if (UCharacterMovementComponent* MovementComp = GetCharacterMovement())
        {
            MovementComp->MaxWalkSpeed = NewSprintSpeed;
        }
    }
    
    UE_LOG(LogTemp, Log, TEXT("Sprint speed changed to %.1f for %s"), NewSprintSpeed, *GetName());
}

2. Camera System Integration

In Camera Setup:

cpp
void APlatformCharacter::UpdateCameraSettings()
{
    if (CameraBoom)
    {
        CameraBoom->TargetArmLength = FPlatformerCVars::CameraDistance.GetValueOnGameThread();
        CameraBoom->CameraLagSpeed = FPlatformerCVars::CameraLagSpeed.GetValueOnGameThread();
        CameraBoom->CameraRotationLagSpeed = FPlatformerCVars::CameraRotationLag.GetValueOnGameThread();
    }
    
    if (FollowCamera)
    {
        FollowCamera->SetFieldOfView(FPlatformerCVars::CameraFOV.GetValueOnGameThread());
    }
}

// Call this in Tick for real-time updates (or use callbacks)
void APlatformCharacter::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    
    // Update camera settings if CVars changed
    static float LastCameraDistance = -1.0f;
    float CurrentCameraDistance = FPlatformerCVars::CameraDistance.GetValueOnGameThread();
    
    if (!FMath::IsNearlyEqual(LastCameraDistance, CurrentCameraDistance))
    {
        UpdateCameraSettings();
        LastCameraDistance = CurrentCameraDistance;
    }
}

3. Interaction System Integration

In UInteractionComponent:

cpp
void UInteractionComponent::UpdateFocusActor()
{
    // Use CVar values for range and radius
    InteractionRange = FPlatformerCVars::InteractionRange.GetValueOnGameThread();
    InteractionRadius = FPlatformerCVars::InteractionRadius.GetValueOnGameThread();
    bShowDebugTraces = FPlatformerCVars::ShowInteractionDebug.GetValueOnGameThread();
    
    // Rest of implementation...
}

bool UInteractionComponent::CanInteractNow() const
{
    // Use CVar for cooldown
    float CooldownTime = FPlatformerCVars::InteractionCooldown.GetValueOnGameThread();
    float TimeSinceLastInteraction = GetWorld()->GetTimeSeconds() - LastInteractionTime;
    
    return TimeSinceLastInteraction >= CooldownTime;
}

CVar Categories and Organization

By System

cpp
// Movement
platformer.Character.WalkSpeed
platformer.Character.SprintSpeed
platformer.Character.JumpHeight
platformer.Character.JumpCount

// Camera
platformer.Camera.Distance
platformer.Camera.LagSpeed
platformer.Camera.RotationLag
platformer.Camera.FOV

// Interaction
platformer.Interaction.Range
platformer.Interaction.Radius
platformer.Interaction.ShowDebug
platformer.Interaction.Cooldown

// AI
platformer.AI.SightRange
platformer.AI.HearingRange
platformer.AI.AttackRange
platformer.AI.PatrolSpeed
platformer.AI.ChaseSpeed
platformer.AI.Enable

// Debug
platformer.Debug.ShowInfo
platformer.Debug.ShowPerformance

// Performance
platformer.Performance.MaxEnemies

Advanced CVar Features

1. CVar Presets

Create preset configurations:

cpp
// Console command to apply preset configurations
class FPlatformerCVarPresets
{
public:
    static void ApplyDevPreset()
    {
        FPlatformerCVars::ShowDebugInfo->AsVariable()->Set(true, ECVF_SetByConsole);
        FPlatformerCVars::ShowInteractionDebug->AsVariable()->Set(true, ECVF_SetByConsole);
        FPlatformerCVars::CharacterWalkSpeed->AsVariable()->Set(800.0f, ECVF_SetByConsole);
        
        UE_LOG(LogTemp, Log, TEXT("Applied development preset"));
    }
    
    static void ApplyProductionPreset()
    {
        FPlatformerCVars::ShowDebugInfo->AsVariable()->Set(false, ECVF_SetByConsole);
        FPlatformerCVars::ShowInteractionDebug->AsVariable()->Set(false, ECVF_SetByConsole);
        FPlatformerCVars::MaxEnemyCount->AsVariable()->Set(10, ECVF_SetByConsole);
        
        UE_LOG(LogTemp, Log, TEXT("Applied production preset"));
    }
    
    static void ApplyPerformancePreset()
    {
        FPlatformerCVars::MaxEnemyCount->AsVariable()->Set(5, ECVF_SetByConsole);
        FPlatformerCVars::EnableAI->AsVariable()->Set(false, ECVF_SetByConsole);
        FPlatformerCVars::CameraLagSpeed->AsVariable()->Set(20.0f, ECVF_SetByConsole);
        
        UE_LOG(LogTemp, Log, TEXT("Applied performance preset"));
    }
};

// Register console commands
static FAutoConsoleCommand ApplyDevPresetCommand(
    TEXT("platformer.preset.dev"),
    TEXT("Apply development preset settings"),
    FConsoleCommandDelegate::CreateStatic(&FPlatformerCVarPresets::ApplyDevPreset)
);

static FAutoConsoleCommand ApplyProdPresetCommand(
    TEXT("platformer.preset.production"),
    TEXT("Apply production preset settings"),
    FConsoleCommandDelegate::CreateStatic(&FPlatformerCVarPresets::ApplyProductionPreset)
);

static FAutoConsoleCommand ApplyPerfPresetCommand(
    TEXT("platformer.preset.performance"),
    TEXT("Apply performance preset settings"),
    FConsoleCommandDelegate::CreateStatic(&FPlatformerCVarPresets::ApplyPerformancePreset)
);

2. CVar Validation

cpp
// Custom CVar with validation
class FValidatedFloatCVar
{
private:
    TAutoConsoleVariable<float> CVar;
    float MinValue;
    float MaxValue;
    
public:
    FValidatedFloatCVar(const TCHAR* Name, float DefaultValue, const TCHAR* Help, 
                       float InMinValue, float InMaxValue)
        : CVar(Name, DefaultValue, Help, ECVF_Cheat)
        , MinValue(InMinValue)
        , MaxValue(InMaxValue)
    {
        CVar->AsVariable()->SetOnChangedCallback(
            FConsoleVariableDelegate::CreateRaw(this, &FValidatedFloatCVar::OnValueChanged)
        );
    }
    
    void OnValueChanged(IConsoleVariable* Variable)
    {
        float Value = Variable->GetFloat();
        if (Value < MinValue || Value > MaxValue)
        {
            float ClampedValue = FMath::Clamp(Value, MinValue, MaxValue);
            Variable->Set(ClampedValue, ECVF_SetByConsole);
            
            UE_LOG(LogTemp, Warning, TEXT("CVar value %.2f out of range [%.2f, %.2f], clamped to %.2f"),
                Value, MinValue, MaxValue, ClampedValue);
        }
    }
    
    float GetValue() const { return CVar.GetValueOnGameThread(); }
    IConsoleVariable* AsVariable() { return CVar.AsVariable(); }
};

// Usage
static FValidatedFloatCVar ValidatedWalkSpeed(
    TEXT("platformer.Character.WalkSpeedValidated"),
    600.0f,
    TEXT("Character walk speed (validated)"),
    100.0f,  // Min
    2000.0f  // Max
);

Console Usage Examples

Runtime Tuning Commands

cpp
// Basic usage
platformer.Character.WalkSpeed 800
platformer.Camera.Distance 300
platformer.Interaction.ShowDebug true

// Batch commands
platformer.preset.dev
platformer.preset.performance

// Debug commands
platformer.Debug.ShowInfo true
stat fps
stat memory

// AI tuning
platformer.AI.SightRange 1200
platformer.AI.ChaseSpeed 600
platformer.AI.Enable false

// Performance testing
platformer.Performance.MaxEnemies 5
platformer.Debug.ShowPerformance true

Save/Load CVar Configurations

cpp
// Save current settings
exec Platformer_SaveCVars

// Load saved settings
exec Platformer_LoadCVars

// Implementation
static FAutoConsoleCommand SaveCVarsCommand(
    TEXT("Platformer_SaveCVars"),
    TEXT("Save current CVar values to config"),
    FConsoleCommandDelegate::CreateLambda([]()
    {
        GConfig->SetFloat(TEXT("Platformer"), TEXT("WalkSpeed"), 
            FPlatformerCVars::CharacterWalkSpeed.GetValueOnGameThread(), GGameUserSettingsIni);
        GConfig->SetFloat(TEXT("Platformer"), TEXT("CameraDistance"), 
            FPlatformerCVars::CameraDistance.GetValueOnGameThread(), GGameUserSettingsIni);
        // ... save other CVars
        
        GConfig->Flush(false, GGameUserSettingsIni);
        UE_LOG(LogTemp, Log, TEXT("CVars saved to config"));
    })
);

Best Practices

1. Naming Conventions

  • Use hierarchical naming: system.subsystem.property
  • Keep names descriptive but concise
  • Use consistent capitalization

2. Value Ranges

  • Always consider valid ranges for numeric CVars
  • Implement validation for critical values
  • Provide reasonable defaults

3. Performance

  • Use callbacks sparingly in hot paths
  • Cache CVar values when appropriate
  • Consider using ECVF_Scalability for performance-related CVars

4. Documentation

  • Provide clear help text for each CVar
  • Document expected value ranges
  • Include usage examples

CVars are powerful tools for real-time tuning and debugging. Use them wisely to create a professional, tunable game experience.