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.h、UnrealEngine\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 注:左上角会给出红色的提示
参考
Performance and Profiling(UE4优化)