可可西

UE4控制台命令

UE4控制台命令是大小写不敏感

所有windows平台的控制台命令见:Unreal Engine 4.26.1(windows) Console Variables and Commands

所有macOS平台的控制台命令见:Unreal Engine 4.26.1(macos) Console Variables and Commands

 

Windows中可通过按键调用控制台来输入执行控制台命令

注:windows上下面黑色输入框对应UConsole类,具体见UnrealEngine\Engine\Source\Runtime\Engine\Classes\Engine\Console.h

可通过修改DefaultInput.ini中[/Script/Engine.InputSettings]标签下的ConsoleKeys来修改该快捷键

[/Script/Engine.InputSettings]
-ConsoleKeys=Tilde
+ConsoleKeys=F7

 

类结构图

详见:UnrealEngine\Engine\Source\Runtime\Core\Public\HAL\IConsoleManager.hUnrealEngine\Engine\Source\Runtime\Core\Private\HAL\ConsoleManager.cpp

注1:TAutoConsoleVariable<T>.Ref.ShadowedValue[0]为GameThread用数据,TAutoConsoleVariable<T>.Ref.ShadowedValue[1]为RenderThread用数据

注2:开发者只能在GameThread中修改TAutoConsoleVariable<T>.Ref.ShadowedValue[0]数据,不能显示地修改TAutoConsoleVariable<T>.Ref.ShadowedValue[1]数据

注3:TAutoConsoleVariable<T>的Flags中不包含ECVF_RenderThreadSafe标志位时,TAutoConsoleVariable<T>.Ref.ShadowedValue[0]会把数据立即设置给TAutoConsoleVariable<T>.Ref.ShadowedValue[1]

         TAutoConsoleVariable<T>的Flags中包含ECVF_RenderThreadSafe标志位时,TAutoConsoleVariable<T>.Ref.ShadowedValue[0]会线程安全的异步地将数据立即设置给TAutoConsoleVariable<T>.Ref.ShadowedValue[1]

注4:FOutputDevice& OutputDevice中打印才会写到memreport文件中,如下

OutputDevice.Logf(ELogVerbosity::Display, TEXT("Current Draws: %d, Prims: %d"), GNumDrawCallsRHI, GNumPrimitivesDrawnRHI);

 

Console Variable Flags

/* UnrealEngine\Engine\Source\Runtime\Core\Public\HAL\IConsoleManager.h */
enum
EConsoleVariableFlags { /* Mask for flags. Use this instead of ~ECVF_SetByMask */ ECVF_FlagMask = 0x0000ffff, /** * Default, no flags are set, the value is set by the constructor */ ECVF_Default = 0x0, /** * Console variables marked with this flag behave differently in a final release build. * Then they are are hidden in the console and cannot be changed by the user. */ ECVF_Cheat = 0x1, /** * Console variables cannot be changed by the user (from console). * Changing from C++ or ini is still possible. */ ECVF_ReadOnly = 0x4, /** * UnregisterConsoleObject() was called on this one. * If the variable is registered again with the same type this object is reactivated. This is good for DLL unloading. */ ECVF_Unregistered = 0x8, /** * This flag is set by the ini loading code when the variable wasn't registered yet. * Once the variable is registered later the value is copied over and the variable is destructed. */ ECVF_CreatedFromIni = 0x10, /** * Maintains another shadow copy and updates the copy with render thread commands to maintain proper ordering. * Could be extended for more/other thread. * Note: On console variable references it assumes the reference is accessed on the render thread only * (Don't use in any other thread or better don't use references to avoid the potential pitfall). */ ECVF_RenderThreadSafe = 0x20, /* ApplyCVarSettingsGroupFromIni will complain if this wasn't set, should not be combined with ECVF_Cheat */ ECVF_Scalability = 0x40, /* those cvars control other cvars with the flag ECVF_Scalability, names should start with "sg." */ ECVF_ScalabilityGroup = 0x80, // ------------------------------------------------ /* Set flags */ ECVF_SetFlagMask = 0x00ff0000, // Use to set a cvar without calling all cvar sinks. Much faster, but potentially unsafe. Use only if you know the particular cvar/setting does not require a sink call ECVF_Set_NoSinkCall_Unsafe = 0x00010000, // ------------------------------------------------ /* to get some history of where the last value was set by ( useful for track down why a cvar is in a specific state */ ECVF_SetByMask = 0xff000000, // the ECVF_SetBy are sorted in override order (weak to strong), the value is not serialized, it only affects it's override behavior when calling Set() // lowest priority (default after console variable creation) ECVF_SetByConstructor = 0x00000000, // from Scalability.ini (lower priority than game settings so it's easier to override partially) ECVF_SetByScalability = 0x01000000, // (in game UI or from file) ECVF_SetByGameSetting = 0x02000000, // project settings (editor UI or from file, higher priority than game setting to allow to enforce some setting fro this project) ECVF_SetByProjectSetting = 0x03000000, // per project setting (ini file e.g. Engine.ini or Game.ini) ECVF_SetBySystemSettingsIni = 0x04000000, // per device setting (e.g. specific iOS device, higher priority than per project to do device specific settings) ECVF_SetByDeviceProfile = 0x05000000, // consolevariables.ini (for multiple projects) ECVF_SetByConsoleVariablesIni = 0x06000000, // a minus command e.g. -VSync (very high priority to enforce the setting for the application) ECVF_SetByCommandline = 0x07000000, // least useful, likely a hack, maybe better to find the correct SetBy... ECVF_SetByCode = 0x08000000, // editor UI or console in game or editor ECVF_SetByConsole = 0x09000000, // ------------------------------------------------ };

EConsoleVariableFlags的说明详见:https://docs.unrealengine.com/4.26/en-US/API/Runtime/Core/HAL/EConsoleVariableFlags/ 

 

ECVF_Cheat标记

一些测试命令可以带上ECVF_Cheat,保证在Test或Shipping包裁剪掉这些命令

DISABLE_CHEAT_CVARS定义如下:

#define DISABLE_CHEAT_CVARS (UE_BUILD_SHIPPING || (UE_BUILD_TEST && !ALLOW_CHEAT_CVARS_IN_TEST))

 

ECVF_Set_NoSinkCall_Unsafe标记

使用ECVF_Set_NoSinkCall_Unsafe标记来设置Console Variable,不会触发对Sink的回调 

/** UnrealEngine\Engine\Source\Runtime\Core\Private\HAL\ConsoleManager.cpp  **/
template <class T>
void OnCVarChange(T& Dst, const T& Src, EConsoleVariableFlags Flags, EConsoleVariableFlags SetBy)
{
    FConsoleManager& ConsoleManager = (FConsoleManager&)IConsoleManager::Get();

    if(IsInGameThread())
    {
        if((Flags & ECVF_RenderThreadSafe) && ConsoleManager.GetThreadPropagationCallback())
        {
            // defer the change to be in order with other rendering commands
            ConsoleManager.GetThreadPropagationCallback()->OnCVarChange(Dst, Src);
        }
        else
        {
            // propagate the change right away
            Dst = Src;
        }
    }
    else
    {
        // CVar Changes can only be initiated from the main thread
        check(0);
    }

    if ((SetBy & ECVF_Set_NoSinkCall_Unsafe)== 0)
    {
        ConsoleManager.OnCVarChanged();
    }
}

 

在代码中设置Console Variable,但不触发Sink的回调

void TestCode()
{
    static IConsoleVariable* CVarMaxFPSCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("t.maxfps"));
    if (CVarMaxFPSCVar)
    {
        CVarMaxFPSCVar->Set(90, EConsoleVariableFlags(ECVF_SetByCode | ECVF_Set_NoSinkCall_Unsafe)); // 将t.maxfps设置为90,但不对Sink进行回调
    }
}

 

回调相关的代理类

/* UnrealEngine\Engine\Source\Runtime\Core\Public\HAL\IConsoleManager.h */
/*
* Console variable delegate type This is a void callback function. */ DECLARE_DELEGATE_OneParam(FConsoleVariableDelegate, IConsoleVariable*); /** Console variable multicast delegate type. */ DECLARE_MULTICAST_DELEGATE_OneParam(FConsoleVariableMulticastDelegate, IConsoleVariable*); /** Console command delegate type (takes no arguments.) This is a void callback function. */ DECLARE_DELEGATE( FConsoleCommandDelegate ); /** Console command delegate type (with arguments.) This is a void callback function that always takes a list of arguments. */ DECLARE_DELEGATE_OneParam( FConsoleCommandWithArgsDelegate, const TArray< FString >& ); /** Console command delegate type with a world argument. This is a void callback function that always takes a world. */ DECLARE_DELEGATE_OneParam( FConsoleCommandWithWorldDelegate, UWorld* ); /** Console command delegate type (with a world and arguments.) This is a void callback function that always takes a list of arguments and a world. */ DECLARE_DELEGATE_TwoParams(FConsoleCommandWithWorldAndArgsDelegate, const TArray< FString >&, UWorld*); /** Console command delegate type (with a world arguments and output device.) This is a void callback function that always takes a list of arguments, a world and output device. */ DECLARE_DELEGATE_ThreeParams(FConsoleCommandWithWorldArgsAndOutputDeviceDelegate, const TArray< FString >&, UWorld*, FOutputDevice&); /** Console command delegate type with the output device passed through. */ DECLARE_DELEGATE_OneParam( FConsoleCommandWithOutputDeviceDelegate, FOutputDevice& );

 

FAutoConsoleVariableRef

FAutoConsoleVariableRef对象会引用关联一个全局变量,使得执行Console Variable时会修改全局变量的数值

/**  UnrealEngine\Engine\Source\Runtime\Core\Public\HAL\IConsoleManager.h **/
FAutoConsoleVariableRef(const TCHAR* Name, int32& RefValue, const TCHAR* Help, uint32 Flags = ECVF_Default);
FAutoConsoleVariableRef(const TCHAR* Name, float& RefValue, const TCHAR* Help, uint32 Flags = ECVF_Default);
FAutoConsoleVariableRef(const TCHAR* Name, bool& RefValue, const TCHAR* Help, uint32 Flags = ECVF_Default);
FAutoConsoleVariableRef(const TCHAR* Name, FString& RefValue, const TCHAR* Help, uint32 Flags = ECVF_Default);
FAutoConsoleVariableRef(const TCHAR* Name, int32& RefValue, const TCHAR* Help, const FConsoleVariableDelegate& Callback, uint32 Flags = ECVF_Default);
FAutoConsoleVariableRef(const TCHAR* Name, float& RefValue, const TCHAR* Help, const FConsoleVariableDelegate& Callback, uint32 Flags = ECVF_Default);
FAutoConsoleVariableRef(const TCHAR* Name, bool& RefValue, const TCHAR* Help, const FConsoleVariableDelegate& Callback, uint32 Flags = ECVF_Default);
FAutoConsoleVariableRef(const TCHAR* Name, FString& RefValue, const TCHAR* Help, const FConsoleVariableDelegate& Callback, uint32 Flags = ECVF_Default);

 

示例

/** UnrealEngine\Engine\Source\Runtime\ApplicationCore\Private\GenericPlatform\GenericPlatformApplicationMisc.cpp **/
static int32 bEnableHighDPIAwareness = 1;

FAutoConsoleVariableRef FGenericPlatformApplicationMisc::CVarEnableHighDPIAwareness(
    TEXT("EnableHighDPIAwareness"),
    bEnableHighDPIAwareness,
    TEXT("Enables or disables high dpi mode"),
    ECVF_ReadOnly
);

 

Console Variable代码示例

/////////////////////////////////////////////////////////////////FConsoleVariableDelegate///////////////////////////////////////////////////////////////
// 全局函数
static void OnRenderThreadPollPeriodMsChanged(IConsoleVariable* Var)
{
    const int32 DesiredRTPollPeriod = Var->GetInt();  // 以int32类型来获取Var变量的值

    GRenderThreadPollingOn = (DesiredRTPollPeriod >= 0);
    ENQUEUE_RENDER_COMMAND(WakeupCommand)([DesiredRTPollPeriod](FRHICommandListImmediate&)
    {
        GRenderThreadPollPeriodMs = DesiredRTPollPeriod;
    });
}

static FAutoConsoleVariable CVarRenderThreadPollPeriodMs(
    TEXT("TaskGraph.RenderThreadPollPeriodMs"),
    -1,
    TEXT("Render thread polling period in milliseconds. If value < 0, task graph tasks explicitly wake up RT, otherwise RT polls for tasks."),
    FConsoleVariableDelegate::CreateStatic(&OnRenderThreadPollPeriodMsChanged)
);

// Lambda表达式
bool bHudStatsEnabledCVar = false;
FAutoConsoleVariableRef CVarHudStats(
    TEXT("PixelStreaming.HUDStats"),
    bHudStatsEnabledCVar,
    TEXT("Whether to show PixelStreaming stats on HUD"),
    FConsoleVariableDelegate::CreateLambda([](IConsoleVariable* InVariable)
    {
        FHUDStats& Stats = FHUDStats::Get();
        Stats.bEnabled = bHudStatsEnabledCVar;
        Stats.Reset();
    }),
    ECVF_Cheat
);

/////////////////////////////////////////////////////////////////FConsoleCommandDelegate///////////////////////////////////////////////////////////////    
// 全局函数
static void ResetAllParticleComponents()
{
    for (TObjectIterator<UParticleSystemComponent> It; It; ++It)
    {
        UParticleSystemComponent* ParticleSystemComponent = *It;
        ParticleSystemComponent->ResetParticles();
        ParticleSystemComponent->ActivateSystem(true);
        ParticleSystemComponent->bIsViewRelevanceDirty = true;
        ParticleSystemComponent->CachedViewRelevanceFlags.Empty();
        ParticleSystemComponent->ConditionalCacheViewRelevanceFlags();
        ParticleSystemComponent->ReregisterComponent();
    }
}
static FAutoConsoleCommand GResetAllParticleComponentsCmd(
    TEXT("FX.RestartAll"),
    TEXT("Restarts all particle system components"),
    FConsoleCommandDelegate::CreateStatic(ResetAllParticleComponents)
    );

// Lambda表达式
static FAutoConsoleCommand CCmdNiagaraDumpPriorities(
    TEXT("fx.Niagara.TaskPriority.Dump"),
    TEXT("Dump currently set priorities"),
    FConsoleCommandDelegate::CreateLambda(
        []()
        {
            auto DumpPriority =
                [](int32 Priority, const TCHAR* TaskName)
                {
                    const ENamedThreads::Type TaskThread = GetNiagaraTaskPriority(Priority);
                    UE_LOG(LogNiagara, Log, TEXT("%s = %d = Thread Priority(%d) Task Priority(%d)"), TaskName, Priority, ENamedThreads::GetThreadPriorityIndex(TaskThread), ENamedThreads::GetTaskPriority(TaskThread));
                };

            
            UE_LOG(LogNiagara, Log, TEXT("=== Niagara Task Priorities"));
            DumpPriority(GNiagaraSystemSimulationTaskPri, TEXT("NiagaraSystemSimulationTask"));
            DumpPriority(GNiagaraSystemInstanceTaskPri, TEXT("NiagaraSystemInstanceTask"));
            DumpPriority(GNiagaraSystemSimulationWaitAllTaskPri, TEXT("NiagaraSystemSimulationWaitAllTask"));
        }
    )
);
    
/////////////////////////////////////////////////////////////////FConsoleCommandWithArgsDelegate///////////////////////////////////////////////////////////////    
// 全局函数
void ConsoleCommandLoadPipelineFileCache(const TArray< FString >& Args)
{
    FShaderPipelineCache::ClosePipelineFileCache();
    FString Name = FApp::GetProjectName();
    if (Args.Num() > 0)
    {
        Name = Args[0];
    }
    FShaderPipelineCache::OpenPipelineFileCache(Name, GMaxRHIShaderPlatform);
}

static FAutoConsoleCommand LoadPipelineCacheCmd(
                                                TEXT("r.ShaderPipelineCache.Open"),
                                                TEXT("Takes the desired filename to open and then loads the pipeline file cache."),
                                                FConsoleCommandWithArgsDelegate::CreateStatic(ConsoleCommandLoadPipelineFileCache)
                                                );
                                                
// Lambda表达式
static FAutoConsoleCommand LeakReporterStartCommand(
    TEXT("mallocleak.start"),
    TEXT("Starts tracking allocations. Args -report=[secs] -size=[filter]"),
    FConsoleCommandWithArgsDelegate::CreateLambda([](const TArray<FString>& Args) {
        FString ArgString = FString::Join(Args, TEXT(" "));
        int32 Size = 0;
        float ReportTime = 0;
        FParse::Value(*ArgString, TEXT("size="), Size);
        FParse::Value(*ArgString, TEXT("report="), ReportTime);

        FMallocLeakReporter::Get().Start(Size * 1024, ReportTime);

        UE_LOG(LogConsoleResponse, Display, TEXT("Tracking allocations >=  %d KB and reporting every %f seconds"), Size / 1024, ReportTime);
    })
);    
                                                   
/////////////////////////////////////////////////////////////////FConsoleCommandWithWorldDelegate///////////////////////////////////////////////////////////////
// 全局函数
static void DumpVisibleActors(UWorld* InWorld)
{
    UE_LOG(LogWorld, Log, TEXT("------ START DUMP VISIBLE ACTORS ------"));
    for (FActorIterator ActorIterator(InWorld); ActorIterator; ++ActorIterator)
    {
        AActor* Actor = *ActorIterator;
        if (Actor && Actor->WasRecentlyRendered(0.05f))
        {
            UE_LOG(LogWorld, Log, TEXT("Visible Actor : %s"), *Actor->GetFullName());
        }
    }
    UE_LOG(LogWorld, Log, TEXT("------ END DUMP VISIBLE ACTORS ------"));
}

static FAutoConsoleCommandWithWorld DumpVisibleActorsCmd(
    TEXT("DumpVisibleActors"),
    TEXT("Dump visible actors in current world."),
    FConsoleCommandWithWorldDelegate::CreateStatic(DumpVisibleActors)
    );

// Lambda表达式
FAutoConsoleCommandWithWorld DumpNiagaraWorldManagerCommand(
    TEXT("DumpNiagaraWorldManager"),
    TEXT("Dump Information About the Niagara World Manager Contents"),
    FConsoleCommandWithWorldDelegate::CreateLambda(
        [](UWorld* World)
        {
            FNiagaraWorldManager* WorldManager = FNiagaraWorldManager::Get(World);
            if (WorldManager != nullptr && GLog != nullptr)
            {
                WorldManager->DumpDetails(*GLog);
            }
        }
    )
);

//////////////////////////////////////////////////////////////FConsoleCommandWithWorldAndArgsDelegate//////////////////////////////////////////////////////////////////
// 全局函数
#if !UE_BUILD_SHIPPING
static void ToggleDebugHUD(const TArray<FString>& Args, UWorld* InWorld)
{

    if (!InWorld)
        return;

    AAbilitySystemDebugHUD *HUD = NULL;

    for (TActorIterator<AAbilitySystemDebugHUD> It(InWorld); It; ++It)
    {
        HUD = *It;
        break;
    }

    static FDelegateHandle DrawDebugDelegateHandle;

    if (!HUD)
    {
        HUD = InWorld->SpawnActor<AAbilitySystemDebugHUD>();
        
        FDebugDrawDelegate DrawDebugDelegate = FDebugDrawDelegate::CreateUObject(HUD, &AAbilitySystemDebugHUD::DrawDebugHUD);
        DrawDebugDelegateHandle = UDebugDrawService::Register(TEXT("GameplayDebug"), DrawDebugDelegate);
    }
    else
    {
        FDebugDrawDelegate DrawDebugDelegate = FDebugDrawDelegate::CreateUObject(HUD, &AAbilitySystemDebugHUD::DrawDebugHUD);
        UDebugDrawService::Unregister(DrawDebugDelegateHandle);
        HUD->Destroy();
    }
}

FAutoConsoleCommandWithWorldAndArgs AbilitySystemToggleDebugHUDCommand(
    TEXT("AbilitySystem.ToggleDebugHUD"),
    TEXT("ToggleDebugHUD Drawing"),
    FConsoleCommandWithWorldAndArgsDelegate::CreateStatic(ToggleDebugHUD)
    );
#endif // !UE_BUILD_SHIPPING

// Lambda表达式
FAutoConsoleCommandWithWorldAndArgs NetRepGraphPrintChannelCounters(TEXT("Net.RepGraph.PrintActorChannelCounters"),TEXT(""),
    FConsoleCommandWithWorldAndArgsDelegate::CreateLambda([](const TArray<FString>& Args, UWorld* World)
    {
        for (auto& MapIt: ActorChannelCreateCounter)
        {
            FActorConnectionPair& Pair = MapIt.Key;
            int32 Count = MapIt.Value;
            UE_LOG(LogReplicationGraph, Display, TEXT("%s : %s ----> %d"), *GetNameSafe(Pair.Actor.Get()), *GetNameSafe(Pair.Connection.Get()), Count );
        }
    })
);


//////////////////////////////////////////////////////////////FConsoleCommandWithWorldArgsAndOutputDeviceDelegate//////////////////////////////////////////////////////////////////
// 全局函数
static void HandleMetalProfileCommand(const TArray<FString>& Args, UWorld*, FOutputDevice& Ar)
{
    if (Args.Num() < 1)
    {
        return;
    }
    FString Param = Args[0];
    if (Param == TEXT("START"))
    {
        FMetalProfiler::GetProfiler()->BeginCapture();
    }
    else if (Param == TEXT("STOP"))
    {
        FMetalProfiler::GetProfiler()->EndCapture();
    }
    else
    {
        int32 CaptureFrames = 0;
        if (FParse::Value(*Param, TEXT("FRAMES="), CaptureFrames))
        {
            FMetalProfiler::GetProfiler()->BeginCapture(CaptureFrames);
        }
    }
}

static FAutoConsoleCommand HandleMetalProfilerCmd(
    TEXT("MetalProfiler"),
    TEXT("Starts or stops Metal profiler"),
    FConsoleCommandWithWorldArgsAndOutputDeviceDelegate::CreateStatic(&HandleMetalProfileCommand)
);

// Lambda表达式
FAutoConsoleCommandWithWorldArgsAndOutputDevice NetEmulationPktEmulationProfile(TEXT("NetEmulation.PktEmulationProfile"), TEXT("Apply a preconfigured emulation profile."),
    FConsoleCommandWithWorldArgsAndOutputDeviceDelegate::CreateStatic([](const TArray<FString>& Args, UWorld* World, FOutputDevice& Output)
{
    bool bProfileApplied(false);
    if (Args.Num() > 0)
    {
        FString CmdParams = FString::Printf(TEXT("PktEmulationProfile=%s"), *(Args[0]));

        NetEmulationHelper::CreatePersistentSimulationSettings();

        bProfileApplied = NetEmulationHelper::PersistentPacketSimulationSettings.GetValue().ParseSettings(*CmdParams, nullptr);
        
        if (bProfileApplied)
        {
            NetEmulationHelper::ApplySimulationSettingsOnNetDrivers(World, NetEmulationHelper::PersistentPacketSimulationSettings.GetValue());
        }
        else
        {
            Output.Log(FString::Printf(TEXT("EmulationProfile: %s was not found in Engine.ini"), *(Args[0])));
        }
    }
    else
    {
        Output.Log(FString::Printf(TEXT("Missing emulation profile name")));
    }

    if (!bProfileApplied)
    {
        if (const UNetworkSettings* NetworkSettings = GetDefault<UNetworkSettings>())
        {
            Output.Log(TEXT("List of some supported emulation profiles:"));
            for (const FNetworkEmulationProfileDescription& ProfileDesc : NetworkSettings->NetworkEmulationProfiles)
            {
                Output.Log(FString::Printf(TEXT("%s"), *ProfileDesc.ProfileName));
            }
        }
    }
}));


////////////////////////////////////////////////////////////FConsoleCommandWithOutputDeviceDelegate////////////////////////////////////////////////////////////////////
// 全局函数
#if STATS
#include "Stats/StatsData.h"
static void DumpRHIMemory(FOutputDevice& OutputDevice)
{
    TArray<FStatMessage> Stats;
    GetPermanentStats(Stats);

    FName NAME_STATGROUP_RHI(FStatGroup_STATGROUP_RHI::GetGroupName());
    OutputDevice.Logf(TEXT("RHI resource memory (not tracked by our allocator)"));
    int64 TotalMemory = 0;
    for (int32 Index = 0; Index < Stats.Num(); Index++)
    {
        FStatMessage const& Meta = Stats[Index];
        FName LastGroup = Meta.NameAndInfo.GetGroupName();
        if (LastGroup == NAME_STATGROUP_RHI && Meta.NameAndInfo.GetFlag(EStatMetaFlags::IsMemory))
        {
            OutputDevice.Logf(TEXT("%s"), *FStatsUtils::DebugPrint(Meta));
            TotalMemory += Meta.GetValue_int64();
        }
    }
    OutputDevice.Logf(TEXT("%.3fMB total"), TotalMemory / 1024.f / 1024.f);
}

static FAutoConsoleCommandWithOutputDevice GDumpRHIMemoryCmd(
    TEXT("rhi.DumpMemory"),
    TEXT("Dumps RHI memory stats to the log"),
    FConsoleCommandWithOutputDeviceDelegate::CreateStatic(DumpRHIMemory)
    );
#endif

// Lambda表达式
static FAutoConsoleCommandWithOutputDevice GParticlePerfStatsDump(
    TEXT("fx.ParticlePerfStats.Dump"),
    TEXT("Dumps current particle perf stats to output"),
    FConsoleCommandWithOutputDeviceDelegate::CreateLambda(
        [](FOutputDevice& Ar)
        {
            DumpParticlePerfStatsToDevice(Ar);
            DumpParticlePerfStatsToFile();
        }
    )
);

 

动态定义Console Variable

UComposureGameSettings::UComposureGameSettings(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
    , bSceneCapWarnOfMissingCam(true)
    , FallbackCompositingTexture(TEXT("/Engine/Functions/Engine_MaterialFunctions02/PivotPainter2/Black_1x1_EXR_Texture.Black_1x1_EXR_Texture"))
{
    IConsoleManager& CVarManager = IConsoleManager::Get();

    CVarManager.RegisterConsoleVariableRef(
        TEXT("r.Composure.CompositingElements.Editor.WarnWhenSceneCaptureIsMissingCamera"),
        bSceneCapWarnOfMissingCam,
        TEXT("By default, scene capture (CG) elements rely on a camera to position themselves.\n")
        TEXT("To catch when one isn't set up, the editor displays a warning image.\n")
        TEXT("Disable this CVar to allow the capture from the element's position & orientation."),
        ECVF_Default);
}

void FLiveCodingModule::StartupModule()
{
    // ... ...
    ConsolePathVariable = ConsoleManager.RegisterConsoleVariable(
        TEXT("LiveCoding.ConsolePath"),
        FPaths::ConvertRelativePathToFull(DefaultEngineDir / DefaultConsolePath),
        TEXT("Path to the live coding console application"),
        ECVF_Cheat
    );
    
    // ... ...
}

void FLiveCodingModule::ShutdownModule()
{
    // ... ...

    IConsoleManager& ConsoleManager = IConsoleManager::Get();
    // ... ...
    ConsoleManager.UnregisterConsoleObject(ConsolePathVariable);
    // ... ...
}

 

动态绑定Console Variable改变时的回调函数

/////////////////////////////////////////////////////////////////FAutoConsoleVariableRef///////////////////////////////////////////////////////////////
static int32 ShallowWaterSim = 1;
static FAutoConsoleVariableRef CVarShallowWaterSim(
    TEXT("r.Water.EnableShallowWaterSimulation"),
    ShallowWaterSim,
    TEXT("Controls whether the shallow water fluid sim is enabled"),
    ECVF_Scalability
);

void UWaterSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
    // ... ...
    FConsoleVariableDelegate NotifyWaterScalabilityChanged = FConsoleVariableDelegate::CreateUObject(this, &UWaterSubsystem::NotifyWaterScalabilityChangedInternal);
    CVarShallowWaterSim->SetOnChangedCallback(NotifyWaterScalabilityChanged); // 绑定代理  注:控制台变量数值改变时会被调用
    // ... ...
}

void UWaterSubsystem::Deinitialize()
{
    // ... ...
    FConsoleVariableDelegate NullCallback;
    CVarShallowWaterSim->SetOnChangedCallback(NullCallback); // 绑定一个空代理
    // ... ...
}

void UWaterSubsystem::NotifyWaterScalabilityChangedInternal(IConsoleVariable* CVar)
{
// ... ...
}
/////////////////////////////////////////////////////////////////TAutoConsoleVariable///////////////////////////////////////////////////////////////
void OnChangeResolutionQuality(IConsoleVariable* Var)
{
    SetResolutionQualityLevel(Var->GetFloat());
}

static TAutoConsoleVariable<float> CVarResolutionQuality(
    TEXT("sg.ResolutionQuality"),
    100.0f,
    TEXT("Scalability quality state (internally used by scalability system, ini load/save or using SCALABILITY console command)\n")
    TEXT(" 10..100, default: 100"),
    ECVF_ScalabilityGroup);
    
void InitScalabilitySystem()
{
    // ... ...
    CVarResolutionQuality.AsVariable()->SetOnChangedCallback(FConsoleVariableDelegate::CreateStatic(&OnChangeResolutionQuality)); // 绑定代理  注:控制台变量数值改变时会被调用
    // ... ...
}

void SetQualityLevels(const FQualityLevels& QualityLevels)
{
    // ... ...
    CVarResolutionQuality.AsVariable()->SetWithCurrentPriority(85.0f); //用变量当前的Priority来进行值的设置  注:当前的Priority为ECVF_ScalabilityGroup
    // ... ...
    
    CVarResolutionQuality.AsVariable()->Set(80.0f, ECVF_SetByScalability); //用ECVF_SetByScalability的Priority来进行值的设置
    // ... ...
}

FQualityLevels GetQualityLevels()
{
    FQualityLevels Ret;

    // ... ...
    Ret.ResolutionQuality = CVarResolutionQuality.GetValueOnGameThread(); // 获取GameThread上的CVarResolutionQuality数值
    // ... ...
    
    return Ret;
}

 

动态注册Console Variable

UDeviceProfileManager& UDeviceProfileManager::Get(bool bFromPostCDOContruct)
{
    if (DeviceProfileManagerSingleton == nullptr)
    {
        // ... ...
        IConsoleManager::Get().RegisterConsoleCommand(
            TEXT("dp.Override.Restore"),
            TEXT("Restores any cvars set by dp.Override to their previous value"),
            FConsoleCommandDelegate::CreateLambda([]()
            {
                UDeviceProfileManager::Get().HandleDeviceProfileOverridePop();
            }),
            ECVF_Default
        );
        // ... ...    
    }
    
    return *DeviceProfileManagerSingleton;
}

// -----------------------------------------------------------------------------------------------------
void UEditorUtilitySubsystem::RunTaskCommand(const TArray<FString>& Params, UWorld* InWorld, FOutputDevice& Ar) { // ... ... } void UEditorUtilitySubsystem::Initialize(FSubsystemCollectionBase& Collection) { RunTaskCommandObject = IConsoleManager::Get().RegisterConsoleCommand( // IConsoleObject* RunTaskCommandObject TEXT("RunTask"), TEXT(""), FConsoleCommandWithWorldArgsAndOutputDeviceDelegate::CreateUObject(this, &UEditorUtilitySubsystem::RunTaskCommand), ECVF_Default ); // ... ... }

 

注册Sink来监听Console Variable的设置

注册的Sink是全局的,任何不带ECVF_Set_NoSinkCall_Unsafe标记的Console Variable的设置操作,将异步触发(下一帧)所有Sink回调函数的调用     注:从控制台执行命令,也会异步触发(下一帧)所有Sink回调函数的调用

>    UE4Editor-MyTest1-Win64-Debug.dll!MySinkFunction() Line 729    C++
     UE4Editor-MyTest1-Win64-Debug.dll!TBaseStaticDelegateInstance<void __cdecl(void),FDefaultDelegateUserPolicy>::ExecuteIfSafe() Line 731    C++
     UE4Editor-Core-Win64-Debug.dll!TDelegate<void __cdecl(void),FDefaultDelegateUserPolicy>::ExecuteIfBound<void,0>() Line 599    C++
     UE4Editor-Core-Win64-Debug.dll!FConsoleManager::CallAllConsoleVariableSinks() Line 803    C++
     UE4Editor-Win64-Debug.exe!FEngineLoop::Tick() Line 4622    C++
     UE4Editor-Win64-Debug.exe!EngineTick() Line 63    C++
     UE4Editor-Win64-Debug.exe!GuardedMain(const wchar_t * CmdLine=0x00000209e9722f80) Line 172    C++
     UE4Editor-Win64-Debug.exe!WinMain(HINSTANCE__ * hInInstance=0x00007ff6477e0000, HINSTANCE__ * hPrevInstance=0x0000000000000000, char * __formal=0x00000209e5394c26, int nCmdShow=10) Line 257    C++

代码示例:

static TAutoConsoleVariable<int32> CVarTest1(
    TEXT("r.test1"),
    1,
    TEXT("test1.\n"),
    ECVF_RenderThreadSafe);
    
static void MySinkFunction()
{
    int32 bNewTest1 = CVarTest1.GetValueOnGameThread() != 0;

    // 默认假定状态为true
    static int32 GTest1 = true;

    if (GTest1 != bNewTest1)
    {
        GTest1 = bNewTest1;

        // 自定义代码
    }
}

FAutoConsoleVariableSink CMyVarSink(FConsoleCommandDelegate::CreateStatic(&MySinkFunction));  // 注册一个Sink
    
void TestCode()
{
    static IConsoleVariable* CVarTest1CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.test1"));
    if (CVarTest1CVar)
    {
        CVarTest1CVar->Set(2, EConsoleVariableFlags(ECVF_SetByCode));
    }
}

 

动态注册Sink

/** UnrealEngine\Engine\Source\Runtime\Engine\Private\UnrealEngine.cpp */

void RefreshEngineSettings()
{
    extern void FreeSkeletalMeshBuffersSinkCallback();

    HDRSettingChangedSinkCallback();
    RefreshSamplerStatesCallback();
    ScalabilityCVarsSinkCallback();
    FreeSkeletalMeshBuffersSinkCallback();
    SystemResolutionSinkCallback();
}

FConsoleVariableSinkHandle GRefreshEngineSettingsSinkHandle;

ENGINE_API void InitializeRenderingCVarsCaching()
{
    GRefreshEngineSettingsSinkHandle = IConsoleManager::Get().RegisterConsoleVariableSink_Handle(FConsoleCommandDelegate::CreateStatic(&RefreshEngineSettings));

    // Initialise this to invalid
    GCachedScalabilityCVars.MaterialQualityLevel = EMaterialQualityLevel::Num;

    // Initial cache
    SystemResolutionSinkCallback();
    ScalabilityCVarsSinkCallback();
}

static void ShutdownRenderingCVarsCaching()
{
    IConsoleManager::Get().UnregisterConsoleVariableSink_Handle(GRefreshEngineSettingsSinkHandle);
}

 

Console Variable使用说明

查看Console Variable帮助

ConsoleVariable ?

t.MaxFPS ?  // 查看t.MaxFPS的帮助

Cmd: t.MaxFPS ?
HELP for 't.MaxFPS':
Caps FPS to the given value.  Set to <= 0 to be uncapped.
t.MaxFPS = "0"      LastSetBy: Console

 

查看Console Variable最近被什么类型操作修改

Cmd: t.maxfps
t.MaxFPS = "0"      LastSetBy: Scalability
Cmd: t.maxfps ?
HELP for 't.MaxFPS':
Caps FPS to the given value.  Set to <= 0 to be uncapped.
t.MaxFPS = "30"      LastSetBy: Scalability
Cmd: t.maxfps 50
t.MaxFPS = "50"
Cmd: t.maxfps
t.MaxFPS = "50"      LastSetBy: Console

所有操作见:

enum EConsoleVariableFlags    // 优先级从低到高
{
    。。。 。。。
    
    // lowest priority (default after console variable creation)
    ECVF_SetByConstructor =            0x00000000,   // 被构造函数修改。console variable创建后默认为这种类型的Flag
    // from Scalability.ini (lower priority than game settings so it's easier to override partially)
    ECVF_SetByScalability =            0x01000000,   // 被Scalability.ini修改
    // (in game UI or from file)
    ECVF_SetByGameSetting =            0x02000000,   // 被GameSettings.ini、GameUserSettings.ini修改
    // project settings (editor UI or from file, higher priority than game setting to allow to enforce some setting fro this project)
    ECVF_SetByProjectSetting =        0x03000000,    // 被Engine.ini等存储的[/Script/Engine.StreamingSettings]、【/Script/Engine.RendererSettings】、【/Script/Engine.NetworkSettings】等标签中的配置所修改
    // per project setting (ini file e.g. Engine.ini or Game.ini)
    ECVF_SetBySystemSettingsIni =    0x04000000,     // 被Engine.ini或Game.ini中[SystemSettings]标签中的配置所修改
    // per device setting (e.g. specific iOS device, higher priority than per project to do device specific settings)
    ECVF_SetByDeviceProfile =        0x05000000,     // 被DeviceProfiles.ini修改
    // consolevariables.ini (for multiple projects)
    ECVF_SetByConsoleVariablesIni = 0x06000000,      // 被ConsoleVariables.ini修改
    // a minus command e.g. -VSync (very high priority to enforce the setting for the application)
    ECVF_SetByCommandline =            0x07000000,   // 被命令行参数修改
    // least useful, likely a hack, maybe better to find the correct SetBy...
    ECVF_SetByCode =                0x08000000,      // hack方式,被代码修改
    // editor UI or console in game or editor
    ECVF_SetByConsole =                0x09000000,   // 被控制台中输入的命令所修改
    // ------------------------------------------------
};

 

当Console Variables被更高优先级的操作修改,就无法再被低优先级的操作修改,会忽略修改并报出warning

static TAutoConsoleVariable<float> CVarViewDistanceScale(
    TEXT("r.ViewDistanceScale"),
    1.0f,
    TEXT("Controls the view distance scale. A primitive's MaxDrawDistance is scaled by this value.\n")
    TEXT("Higher values will increase view distance but at a performance cost.\n")
    TEXT("Default = 1."),
    ECVF_Scalability | ECVF_RenderThreadSafe);

 

带有ECVF_Scalability标志位的控制台变量,如果被Console修改过,就不能再被Scalability修改(配置在*Scalability.ini中),会报如下warning:

[2022.06.09-14.14.30:803][ 27]LogConsoleManager: Warning: |ConsoleManager.cpp:161|Setting the console variable 'r.ViewDistanceScale' with 'SetByScalability' was ignored as it is lower priority than the previous 'SetByConsole'. Value remains '1'

 

可执行控制台命令时,指定修改的方式

static IConsoleVariable* MaxFPSCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("t.MaxFPS"));
MaxFPSCVar->Set(50, ECVF_SetByConsole);

 

执行Console Variable

在c++代码中执行

#include "Engine/Engine.h"
GEngine->Exec(nullptr, TEXT("gc.TimeBetweenPurgingPendingKillObjects 10")); // 默认是61s  // bool UEngine::Exec( UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Out=*GLog )
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), TEXT("gc.TimeBetweenPurgingPendingKillObjects 10"), nullptr); // static void ExecuteConsoleCommand(const UObject* WorldContextObject, const FString& Command, class APlayerController* SpecificPlayer = NULL )

在蓝图中执行

调用堆栈

     libUE4.so!$_13::operator()(IConsoleVariable*) const(const (unnamed class) * this = 0x0000006fc611ec58, FConsoleVariableRef<bool> * InVariable = 0x0000007046095d80) Line 88    c++
     libUE4.so!decltype(Forward<$_13&>(fp)(Forward<IConsoleVariable*&>(fp0))) Invoke<$_13&, IConsoleVariable*&>((unnamed class) & Func = 0x0000006fc611ec58, IConsoleVariable *& Args = 0x0000007945d9d5b0) Line 50    c++
     libUE4.so!decltype(auto) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter<$_13&, IConsoleVariable*&>($_13&, IConsoleVariable*&) const(const UE4Tuple_Private::TTupleBase<TIntegerSequence<> > * this = 0x0000006fc611ec48, (unnamed class) & Func = 0x0000006fc611ec58, IConsoleVariable *& Args = 0x0000007945d9d5b0) Line 298    c++
     libUE4.so!TBaseFunctorDelegateInstance<void (IConsoleVariable*), FDefaultDelegateUserPolicy, $_13>::ExecuteIfSafe(IConsoleVariable*) const(const TBaseFunctorDelegateInstance<void (IConsoleVariable *), FDefaultDelegateUserPolicy, (unnamed class)> * this = 0x0000006fc611ec40, FConsoleVariableRef<bool> * Params = 0x0000007046095d80) Line 835    c++
     libUE4.so!TMulticastDelegate<void (IConsoleVariable*), FDefaultDelegateUserPolicy>::Broadcast(IConsoleVariable*) const(const TMulticastDelegate<void (IConsoleVariable *), FDefaultDelegateUserPolicy> * this = 0x0000007046095da8, FConsoleVariableRef<bool> * Params = 0x0000007046095d80) Line 954    c++
     libUE4.so!FConsoleVariableBase::OnChanged(FConsoleVariableRef<bool> * this = 0x0000007046095d80, EConsoleVariableFlags SetBy = ECVF_SetByConsole) Line 182    c++
     libUE4.so!FConsoleVariableRef<bool>::OnChanged(FConsoleVariableRef<bool> * this = 0x0000007046095d80, EConsoleVariableFlags SetBy = ECVF_SetByConsole) Line 565    c++
     libUE4.so!FConsoleVariableRef<bool>::Set(FConsoleVariableRef<bool> * this = 0x0000007046095d80, const TCHAR * InValue = 0x0000006fa652eb50, EConsoleVariableFlags SetBy = ECVF_SetByConsole) Line 519    c++
>    libUE4.so!FConsoleManager::ProcessUserConsoleInput(FConsoleManager * this = 0x000000710602bf00, const TCHAR * InInput = 0x0000007006f1cac0, FOutputDeviceRedirector & Ar = 0x000000791125f1d8, UWorld * InWorld = 0x0000007346397990) Line 1440    c++
     libUE4.so!UEngine::Exec(UUAGameEngine * this = 0x00000073c614c000, UWorld * InWorld = 0x0000007346397990, const TCHAR * Cmd = 0x0000007006f1cac0, FOutputDeviceRedirector & Ar = 0x000000791125f1d8) Line 4551    c++
     libUE4.so!UGameEngine::Exec(UUAGameEngine * this = 0x00000073c614c000, UWorld * InWorld = 0x0000007346397990, const TCHAR * Cmd = 0x0000007006f1cac0, FOutputDeviceRedirector & Ar = 0x000000791125f1d8) Line 1588    c++
     libUE4.so!UGameViewportClient::Exec(USGGameViewportClient * this = 0x0000007266148800, UWorld * InWorld = 0x0000007346397990, const TCHAR * Cmd = 0x0000007006f1cac0, FOutputDeviceRedirector & Ar = 0x000000791125f1d8) Line 2989    c++
     libUE4.so!ULocalPlayer::Exec(USGLocalPlayer * this = 0x0000007206507d20, UWorld * InWorld = 0x0000007346397990, const TCHAR * Cmd = 0x0000007006f1cac0, FOutputDeviceRedirector & Ar = 0x000000791125f1d8) Line 1581    c++
     libUE4.so!UEngine::TickDeferredCommands(UUAGameEngine * this = 0x00000073c614c000) Line 2023    c++
     libUE4.so!FEngineLoop::Tick(FEngineLoop * this = 0x0000007910e464f8) Line 5131    c++
     libUE4.so!AndroidMain(android_app * state = 0x00000079adc34440) Line 581    c++
     libUE4.so!android_main(android_app * state = 0x00000079adc34440) Line 826    c++
     libUE4.so!android_app_entry(void * param = 0x00000079adc34440) Line 232    c99
     libc.so!__pthread_start()    unknown
     libc.so!__start_thread()    unknown

 

 

ini中配置要执行的Console Variable

UnrealEngine\Engine\Config\ConsoleVariables.ini

[Startup]
net.UseAdaptiveNetUpdateFrequency=0
p.chaos.AllowCreatePhysxBodies=1

Config\*Engine.ini

[SystemSettings]
s.ForceGCAfterLevelStreamedOut=0
s.ContinuouslyIncrementalGCWhileLevelsPendingPurge=0

[/Script/Engine.RendererSettings]
r.AllowStaticLighting=True
r.ReflectionCaptureResolution=64

[/Script/Engine.RendererOverrideSettings]
r.MorphTarget.Mode=True
r.GPUCrashDebugging=False

[/Script/Engine.StreamingSettings]
s.MinBulkDataSizeForAsyncLoading=131072
s.AsyncLoadingThreadEnabled=True
s.EventDrivenLoaderEnabled=True

[/Script/Engine.GarbageCollectionSettings]
gc.MaxObjectsNotConsideredByGC=31552
gc.MaxObjectsInGame=3000000
gc.ActorClusteringEnabled=True

[/Script/Engine.NetworkSettings]
n.VerifyPeer=false

Config\*Scalability.ini

[AntiAliasingQuality@0]    ; 0, 1, 2, 3, Cine
r.PostProcessAAQuality=0

[ViewDistanceQuality@0]
r.SkeletalMeshLODBias=2
r.ViewDistanceScale=0.4

[ShadowQuality@0]
r.LightFunctionQuality=0
r.ShadowQuality=0
r.Shadow.CSM.MaxCascades=1
r.Shadow.MaxResolution=512

[PostProcessQuality@0]
r.MotionBlurQuality=0
r.AmbientOcclusionMipLevelFactor=1.0
r.AmbientOcclusionMaxQuality=0

[TextureQuality@0]
r.Streaming.MipBias=16
r.Streaming.AmortizeCPUToGPUCopy=1
r.Streaming.MaxNumTexturesToStreamPerFrame=1

[EffectsQuality@0]
r.TranslucencyLightingVolumeDim=24
r.RefractionQuality=0

[FoliageQuality@0]
foliage.DensityScale=0
grass.DensityScale=0

[ShadingQuality@0]
r.HairStrands.SkyLighting.IntegrationType=2
r.HairStrands.SkyAO.SampleCount=4
r.HairStrands.Visibility.MSAA.SamplePerPixel=1
r.HairStrands.Interpolation.UseSingleGuide=1

Config\*DeviceProfiles.ini

[Windows DeviceProfile]
DeviceType=Windows
BaseProfileName=
; +CVars=r.Vulkan.EnableValidation=0

[IOS DeviceProfile]
DeviceType=IOS
BaseProfileName=
; HZB will be slower with tiled, and not needed
+CVars=r.HZBOcclusion=0
; Non need for depth prepass
+CVars=r.EarlyZPass=0

[Android DeviceProfile]
DeviceType=Android
BaseProfileName=
+CVars=slate.AbsoluteIndices=1
+CVars=r.Vulkan.DelayAcquireBackBuffer=1
+CVars=r.Vulkan.RobustBufferAccess=1

 

在DS上执行Console Variable

ServerExec log LogNetTraffic log

ServerExec t.MaxFPS 90

 

Console Variable示例

t.MaxFPS 90  // 将帧率上限设置为90

static TAutoConsoleVariable<float> CVarMaxFPS(
    TEXT("t.MaxFPS"),0.f,
    TEXT("Caps FPS to the given value.  Set to <= 0 to be uncapped."));

t.MaxFPS 0  // 帧率为无限上限

 

在控制台下,执行上面命令时,游戏线程用的CVarMaxFPS.Ref.ShadowedValue[0]先被设置成90

 

由于CVarMaxFPS的Flags为ECVF_Default,因此在同一帧内,在后面的OnChanged --> OnCVarChange函数中将渲染线程用的CVarMaxFPS.Ref.ShadowedValue[1]设置成90

 

如果Flags中包含ECVF_RenderThreadSafe标志位,会走上面的if逻辑ConsoleManager.GetThreadPropagationCallback()->OnCVarChange(Dst, Src)

最后通过CommandBuffer来异步设置渲染线程用的CVarMaxFPS.Ref.ShadowedValue[1]变量为90

 

帧率上限也可以做在BaseEngine.ini中配置

;配置游戏帧率上限
[/Script/Engine.Engine]
bSmoothFrameRate=true ;bSmoothFrameRate为true时,SmoothedFrameRateRange生效
SmoothedFrameRateRange=(LowerBound=(Type="ERangeBoundTypes::Inclusive",Value=22),UpperBound=(Type="ERangeBoundTypes::Exclusive",Value=62)) ;帧率上限为62

;配置编辑器帧率上限
[/Script/UnrealEd.EditorEngine]
bSmoothFrameRate=false ;bSmoothFrameRate为false时,SmoothedFrameRateRange生效
SmoothedFrameRateRange=(LowerBound=(Type="ERangeBoundTypes::Inclusive",Value=5),UpperBound=(Type="ERangeBoundTypes::Inclusive",Value=120)) ;帧率上限为120

注:更多平滑帧率详见这里

 

DS帧率上限设置也在BaseEngine.ini中配置

[/Script/OnlineSubsystemUtils.IpNetDriver]
NetServerMaxTickRate=30

 

CauseHitchesHitchMS  150  // 将卡顿时间设为150ms,缺省为200ms

CauseHitches  1 // 每秒产生一个CauseHitchesHitchMS指定时长的卡顿

t.UnsteadyFPS 1 // 设置帧率在[8, 32]之间的某个随机值

 

r.vsync 1  // 开启垂直同步

r.vsync 0  // 关闭垂直同步

r.ScreenPercentage 80  // 将分辨率改成配置的分辨率的80%   注1:设置为-1即100%  注2:UI不受影响

r.MobileContentScaleFactor 0.75  // 在移动平台上,将BackBuffer分辨率设成配置的0.75倍   注:也可通过命令行参数来修改(mcsf=0.75)

 

test 20  // 打印BackBuffer和手机屏幕的分辨率

[2022.10.24-20.22.36:877][854]LogTemp: Display: |MFPWPluginManager.cpp:1352|GSystemResolution X=1280, Y=720    // BackBuffer的size
[2022.10.24-20.22.36:877][854]LogTemp: Display: |MFPWPluginManager.cpp:1357|ViewportSize X=1280.000000, Y=720.000000  // BackBuffer的size
[2022.10.24-20.22.36:878][854]LogTemp: Display: |MFPWPluginManager.cpp:1374|ScreenWidth=1920, ScreenHeight=1080, SurfaceWidth=1920, SurfaceHeight=1080  // 手机屏幕的分辨率

 

r.SceneColorFormat  2 // 将SceneColor的RT像素格式调整为PF_FloatR11G11B10 32Bit  会影响带宽和透明度质量

0: PF_B8G8R8A8 32Bit (mostly for testing, likely to unusable with HDR)
1: PF_A2B10G10R10 32Bit
2: PF_FloatR11G11B10 32Bit
3: PF_FloatRGB 32Bit
4: PF_FloatRGBA 64Bit (default, might be overkill, especially if translucency is mostly using SeparateTranslucency)
5: PF_A32B32G32R32F 128Bit (unreasonable but good for testing)

 

r.Mobile.SceneColorFormat  2  // 在移动平台上,将SceneColor的RT像素格式调整为PF_FloatR11G11B10 32Bit  会影响带宽和透明度质量

0: (default) Automatically select the appropriate format depending on project settings and device support.
1: PF_FloatRGBA 64Bit 
2: PF_FloatR11G11B10 32Bit
3: PF_B8G8R8A8 32Bit

 

定义静态TAutoConsoleVariable<int32> CVarGBufferFormat变量,将r.GBufferFormat初始值为1

注:ValueOnGameThread上的Data.ShadowedValue[0]和ValueOnRenderThread上的Data.ShadowedValue[1]均会被设置为1

static TAutoConsoleVariable<int32> CVarGBufferFormat(
    TEXT("r.GBufferFormat"),
    1,
    TEXT("Defines the memory layout used for the GBuffer.\n")
    TEXT("(affects performance, mostly through bandwidth, quality of normals and material attributes).\n")
    TEXT(" 0: lower precision (8bit per component, for profiling)\n")
    TEXT(" 1: low precision (default)\n")
    TEXT(" 3: high precision normals encoding\n")
    TEXT(" 5: high precision"),
    ECVF_RenderThreadSafe);

 

r.GBufferFormat 3  // 设置GBuffer的法线为高精度编码

FConsoleVariable.Set先设置ValueOnGameThread上的Data.ShadowedValue[0]值为3,然后再异步将3到ValueOnRenderThread上的Data.ShadowedValue[1]值中

 

ShowFlag.AmbientCubemap 0/1 // 环境立方体贴图
ShowFlag.AmbientOcclusion 0/1 // 环境光遮挡
ShowFlag.AntiAliasing 0/1 // 抗锯齿
ShowFlag.Atmosphere 0/1 // 大气
ShowFlag.AudioRadius 0/1 // 音频半径
ShowFlag.BillboardSprites 0/1 // 公告板
ShowFlag.Bloom 0/1 // 泛光
ShowFlag.Bones 0/1 // 骨骼
ShowFlag.Bounds 0/1 // 边界
ShowFlag.Brushes 0/1 // 笔刷
ShowFlag.BSP 0/1 // BSP
ShowFlag.BSPSplit 0/1 // BSP分割
ShowFlag.BSPTriangles 0/1 // BSP三角形
ShowFlag.BuilderBrush 0/1 // 构建器笔刷
ShowFlag.CameraAspectRatioBars 0/1 // 相机高宽比条
ShowFlag.CameraFrustums 0/1 // 相机视锥
ShowFlag.CameraImperfections 0/1 // 相机缺陷
ShowFlag.CameraInterpolation 0/1 // 相机插补
ShowFlag.CameraSafeFrames 0/1 // 相机安全框
ShowFlag.CapsuleShadows 0/1 // 胶囊体阴影
ShowFlag.Collision 0/1 // 碰撞
ShowFlag.CollisionPawn 0/1 // Pawn
ShowFlag.CollisionVisibility 0/1 // 可见性
ShowFlag.ColorGrading 0/1 // 颜色分级
ShowFlag.CompositeEditorPrimitives 0/1 // 合成编辑器Primitives
ShowFlag.Constraints 0/1 // 约束
ShowFlag.ContactShadows 0/1 // 屏幕空间接触阴影
ShowFlag.Cover 0/1 // 覆盖
ShowFlag.DebugAI 0/1 // AI调试
ShowFlag.Decals 0/1 // 贴花
ShowFlag.DeferredLighting 0/1 // 延迟光源
ShowFlag.DepthOfField 0/1 // 景深
ShowFlag.Diffuse 0/1 // 漫反射
ShowFlag.DirectionalLights 0/1 // 定向光源
ShowFlag.DirectLighting 0/1 // 直接光源
ShowFlag.DistanceCulledPrimitives 0/1 // 距离剔除Primitives
ShowFlag.DistanceFieldAO 0/1 // 距离场环境光遮蔽
ShowFlag.DynamicShadows 0/1 // 动态阴影
ShowFlag.Editor 0/1 // 编辑器
ShowFlag.EyeAdaptation 0/1 // 眼部适应
ShowFlag.Fog 0/1 // 雾
ShowFlag.ForceFeedbackRadius 0/1 // 强制反馈半径
ShowFlag.Game 0/1 // 游戏
ShowFlag.GameplayDebug 0/1 //Gameplay调试
ShowFlag.GBufferHints 0/1 //GBuffer提示(材质属性)
ShowFlag.GlobalIllumination 0/1 // 全局光照
ShowFlag.Grain 0/1 // 粒度
ShowFlag.Grid 0/1 // 网格
ShowFlag.HighResScreenshotMask 0/1 // 高精度截图遮罩
ShowFlag.HISMCClusterTree 0/1 // HISM/植物群集树
ShowFlag.HISMCOcclusionBounds 0/1 // HISM/植物遮挡边界
ShowFlag.HitProxies 0/1 // 命中代理
ShowFlag.HLODColoration 0/1 // 显示HLOD着色
ShowFlag.HMDDistortion 0/1 // HMD失真
ShowFlag.IndirectLightingCache 0/1 // 间接光源缓存
ShowFlag.InstancedFoliage 0/1 // 植物
ShowFlag.InstancedGrass 0/1 // 草地
ShowFlag.InstancedStaticMeshes 0/1 // 实例化静态网格体
ShowFlag.Landscape 0/1 // 地形
ShowFlag.LargeVertices 0/1 // 大型顶点
ShowFlag.LensFlares 0/1 // 镜头光斑
ShowFlag.LevelColoration 0/1 // 关卡着色
ShowFlag.LightComplexity 0/1 // 光照复杂度
ShowFlag.LightFunctions 0/1 // 光照函数
ShowFlag.LightInfluences 0/1 // 光照影响
ShowFlag.Lighting 0/1 // 光照
ShowFlag.LightingOnlyOverride 0/1 // 仅光照
ShowFlag.LightMapDensity 0/1 // 光照图密度
ShowFlag.LightRadius 0/1 // 光照半径
ShowFlag.LightShafts 0/1 // 光束
ShowFlag.LOD 0/1 // LOD父处理
ShowFlag.LODColoration 0/1 //显示LOD着色
ShowFlag.MassProperties 0/1 // 质量属性
ShowFlag.Materials 0/1 // 材质
ShowFlag.MaterialTextureScaleAccuracy 0/1 // 材质纹理标度准确度
ShowFlag.MediaPlanes 0/1 // 媒体平面
ShowFlag.MeshEdges 0/1 // 网格体边缘
ShowFlag.MeshUVDensityAccuracy 0/1 // 网格体UV密度准确度
ShowFlag.ModeWidgets 0/1 // 模式控件
ShowFlag.MotionBlur 0/1 // 运动模糊
ShowFlag.Navigation 0/1 // 导航
ShowFlag.OcclusionMeshes 0/1 // 可视化遮挡物查询器
ShowFlag.OnScreenDebug 0/1 // 屏上调试
ShowFlag.OutputMaterialTextureScales 0/1 // 输出材质纹理标度
ShowFlag.OverrideDiffuseAndSpecular 0/1 // 重载漫反射和高光
ShowFlag.Paper2DSprites 0/1 // Paper 2D Sprites
ShowFlag.Particles 0/1 // 粒子
ShowFlag.PathTracing 0/1 // 路径追踪
ShowFlag.PhysicalMaterialMasks 0/1 // 物理材质遮罩
ShowFlag.Pivot 0/1 // 枢轴
ShowFlag.PointLights 0/1 // 点光源
ShowFlag.PostProcessing 0/1 // 后处理
ShowFlag.PostProcessMaterial 0/1 // 后处理材质
ShowFlag.PrecomputedVisibility 0/1 // 预计算可见性
ShowFlag.PrecomputedVisibilityCells 0/1 // 预计算可见性单元
ShowFlag.PreviewShadowsIndicator 0/1 // 预览阴影指示器
ShowFlag.PrimitiveDistanceAccuracy 0/1 // 图元距离准确度
ShowFlag.PropertyColoration 0/1 // 属性着色
ShowFlag.QuadOverdraw 0/1 // 四边形过度绘制
ShowFlag.RayTracedDistanceFieldShadows 0/1 // 距离场阴影
ShowFlag.RayTracingDebug 0/1 // 光线追踪调试
ShowFlag.RectLights 0/1 // 矩形光源
ShowFlag.ReflectionEnvironment 0/1 // 反射环境
ShowFlag.ReflectionOverride 0/1 // 反射
ShowFlag.Refraction 0/1 // 折射
ShowFlag.Rendering 0/1 // 关闭/打开渲染
ShowFlag.RequiredTextureResolution 0/1 // 所需的纹理分辨率
ShowFlag.SceneColorFringe 0/1 // 场景颜色边缘
ShowFlag.ScreenPercentage 0/1 // 屏幕百分比
ShowFlag.ScreenSpaceAO 0/1 // 屏幕空间环境光遮蔽
ShowFlag.ScreenSpaceReflections 0/1 // 屏幕空间反射
ShowFlag.Selection 0/1 // 选择
ShowFlag.SelectionOutline 0/1 // 选择轮廓
ShowFlag.SeparateTranslucency 0/1 // 独立半透明度
ShowFlag.ServerDrawDebug 0/1 // 专属服务器调试绘制
ShowFlag.ShaderComplexity 0/1 // 着色器复杂度
ShowFlag.ShaderComplexityWithQuadOverdraw 0/1 // 带四边形过度绘制的着色器复杂度
ShowFlag.ShadowFrustums 0/1 // 阴影视锥
ShowFlag.SkeletalMeshes 0/1 // 骨骼网格体
ShowFlag.SkyLighting 0/1 // 天空光照
ShowFlag.Snap 0/1 // 对齐
ShowFlag.Specular 0/1 // Specular
ShowFlag.Splines 0/1 // 样条
ShowFlag.SpotLights 0/1 // 聚光灯光源
ShowFlag.StaticMeshes 0/1 // 静态网格体
ShowFlag.StationaryLightOverlap 0/1 // 固定光源重叠
ShowFlag.StereoRendering 0/1 // 立体渲染
ShowFlag.StreamingBounds 0/1 // 流送边界
ShowFlag.SubsurfaceScattering 0/1 // 次表面散射(屏幕空间)
ShowFlag.TemporalAA 0/1 // 临时抗锯齿
ShowFlag.Tessellation 0/1 // 曲面细分
ShowFlag.TestImage 0/1 // 测试图像
ShowFlag.TextRender 0/1 // 渲染(3D)文本
ShowFlag.TexturedLightProfiles 0/1 // 纹理光源描述文件(IES纹理)
ShowFlag.ToneCurve 0/1 // 色调曲线
ShowFlag.Tonemapper 0/1 // 色调映射器
ShowFlag.Translucency 0/1 // 半透明度
ShowFlag.VectorFields 0/1 // 向量场
ShowFlag.VertexColors 0/1 // 顶点颜色
ShowFlag.Vignette 0/1 // 晕映
ShowFlag.VirtualTexturePrimitives 0/1 // 虚拟纹理图元
ShowFlag.VisLog 0/1 // 日志查看器
ShowFlag.VisualizeBuffer 0/1 // 缓冲显示
ShowFlag.VisualizeCalibrationColor 0/1 // 显示校准颜色
ShowFlag.VisualizeCalibrationCustom 0/1 // 显示校准自定义
ShowFlag.VisualizeCalibrationGrayscale 0/1 // 显示校准灰阶
ShowFlag.VisualizeDistanceFieldAO 0/1 // 距离场环境光遮蔽
ShowFlag.VisualizeDOF 0/1 // 景深图层
ShowFlag.VisualizeGlobalDistanceField 0/1 // 全局距离场
ShowFlag.VisualizeHDR 0/1 // HDR(眼部适应)
ShowFlag.VisualizeLightCulling 0/1 // 光源剔除
ShowFlag.VisualizeLPV 0/1 // 光传播体积
ShowFlag.VisualizeMeshDistanceFields 0/1 // 网格体距离场
ShowFlag.VisualizeMotionBlur 0/1 // 动态模糊
ShowFlag.VisualizeOutOfBoundsPixels 0/1 // 越界像素
ShowFlag.VisualizeSenses 0/1 // 感应
ShowFlag.VisualizeShadingModels 0/1 // 着色模型
ShowFlag.VisualizeSkyAtmosphere 0/1 // 天空大气
ShowFlag.VisualizeSSR 0/1 // 屏幕空间反射
ShowFlag.VisualizeSSS 0/1 // 次表面散射(屏幕空间)
ShowFlag.VisualizeVolumetricLightmap 0/1 // 体积光照贴图
ShowFlag.VolumeLightingSamples 0/1 // 体积光源范例
ShowFlag.Volumes 0/1 // 体积
ShowFlag.VolumetricFog 0/1 // 体积雾
ShowFlag.VolumetricLightMap 0/1 // 体积光照贴图
ShowFlag.VREditing 0/1 // VR编辑
ShowFlag.WidgetComponents 0/1 // 控件组件
ShowFlag.Wireframe 0/1 // 线框

 

showflag.DistanceCulledPrimitives 1  // 关掉距离剔除 

r.forceLOD 0  // 始终显示最高一级

 

FreezeRendering  // 冻结摄像机渲染,此时可以移动看摄像机渲染的部分,相当于视椎体的culling

FREEZESTREAMING  // 冻结LevelStreaming

FREEZEALL  // 冻结LevelStreaming

 

CANCELASYNCLOAD   // 取消异步加载

 

flushlog  // flush日志到文件

 

Slate.ShowWireFrame 1  // 以WireFrame(线框)方式查看编辑器

 

Slate.ShowBatching 1  // 查看编辑器绘制的合批情况

 

gamever或gameversion  // 输出游戏的引擎版本、编译版本以及命令行信息

GameVersion Branch: ++UE4+Release-4.26, Configuration: Debug, Build: ++UE4+Release-4.26-CL-0, CommandLine:  PhysxTestMap -game -nothreading -forceRHIBypass -Windowed ResX=800 ResY=600

注:详见UnrealEngine\Engine\Source\Runtime\Launch\Resources\Version.h

#define ENGINE_MAJOR_VERSION    4
#define ENGINE_MINOR_VERSION    26
#define ENGINE_PATCH_VERSION    1

 

 

crackurl  // 解析命令行中的URL信息

 

DumpUnbuiltLightInteractions   // 打印出当前需要重新Build Light的详细信息

Cmd: DumpUnbuiltLightInteractions
DumpUnbuiltLightIteractions
Lights with unbuilt interactions: 1
    Light PointLight_1
Primitives with unbuilt interactions: 2
    Primitive StaticMeshComponent /Game/MS_Vegetables/Maps/UEDPIE_0_TestMap1.TestMap1:PersistentLevel.Cube_2.StaticMeshComponent0
    Primitive StaticMeshComponent /Game/MS_Vegetables/Maps/UEDPIE_0_TestMap1.TestMap1:PersistentLevel.tgmkaehpa_LOD0_5.StaticMeshComponent0

当在场景中放置一个PointLight,在其范围内的Mobility为Static物件都需要重新Build Light    注:左上角会给出红色的提示

 

参考

C++中的控制台变量

Performance and Profiling(UE4优化)

 

posted on 2023-06-20 00:10  可可西  阅读(3316)  评论(0编辑  收藏  举报

导航