5

UE4关卡编辑问题记录

 3 years ago
source link: https://blog.ch-wind.com/ue4-level-editor-notes/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近自己摆弄关卡遇到的一些问题的记录。

由于近段时间基本一直在作逻辑开发,所以很少自己碰编辑器,发现一些常见的问题也不知道该如何应对。于是统一的记录了起来,方便下次查找原因。

Texture streaming over budget

结论写在前面,基本原因是默认配置太小,调大就可以了。

主要是直接输出一个红色的错误日志在顶部,让人担心自己是不是做错了什么。

首先,找到日志输出的地方:

SmallTextItem.SetColor(FLinearColor::Red);
SmallTextItem.Text = FText::Format(LOCTEXT("TEXTURE_STREAMING_POOL_OVER_BUDGET_FMT", "TEXTURE STREAMING POOL OVER {0} BUDGET"), FText::AsMemory(MemOver));
Canvas->DrawItem(SmallTextItem, FVector2D(MessageX, MessageY));
SmallTextItem.SetColor(FLinearColor::Red); 
SmallTextItem.Text = FText::Format(LOCTEXT("TEXTURE_STREAMING_POOL_OVER_BUDGET_FMT", "TEXTURE STREAMING POOL OVER {0} BUDGET"), FText::AsMemory(MemOver)); 
Canvas->DrawItem(SmallTextItem, FVector2D(MessageX, MessageY));

这个东西的计算在:

FRenderAssetStreamingMipCalcTask::UpdateStats_Async
FRenderAssetStreamingMipCalcTask::UpdateStats_Async

中,主要有两个来源:

内存池超过限制

Stats.OverBudget += FMath::Max<int64>(Stats.RequiredPool - Stats.StreamingPool, 0);
Stats.OverBudget += FMath::Max<int64>(Stats.RequiredPool - Stats.StreamingPool, 0);

用实际消耗的内存大小减去MemoryBudget,RequairedPool就是每一个FStreamingRenderAsset的消耗加起来

Stats.RequiredPool += RequiredSize;
Stats.RequiredPool += RequiredSize;

单个物体超过限制

// All persistent mip bias bigger than the expected is considered overbudget.
const int32 OverBudgetBias = FMath::Max<int32>(0, StreamingRenderAsset.BudgetMipBias - Settings.GlobalMipBias);
Stats.OverBudget += StreamingRenderAsset.GetSize(StreamingRenderAsset.MaxAllowedMips + OverBudgetBias) - MaxSize;
// All persistent mip bias bigger than the expected is considered overbudget. 
const int32 OverBudgetBias = FMath::Max<int32>(0, StreamingRenderAsset.BudgetMipBias - Settings.GlobalMipBias); 
Stats.OverBudget += StreamingRenderAsset.GetSize(StreamingRenderAsset.MaxAllowedMips + OverBudgetBias) - MaxSize;

这里累计进去的就是OverBudgetBias,因为前面

const int64 MaxSize = StreamingRenderAsset.GetSize(StreamingRenderAsset.MaxAllowedMips);
const int64 MaxSize = StreamingRenderAsset.GetSize(StreamingRenderAsset.MaxAllowedMips);

这样的话,直接stat streaming,看结果

这里就是配置太小了,不知为什么默认只有76M,这样随便上几个大点的pbr贴图就超过了。通过指令上调配置就好。

r.Streaming.PoolSize 2000

也就是说,实际上是默认配置太小导致的,不是哪里操作有问题。

InstanceMesh

目前共有UInstancedStaticMeshComponent和UHierarchicalInstancedStaticMeshComponent两个组件,但是他们有什么区别呢?一旦开始纠结就不知道应该选哪一个了。

稍微查了下资料,主要的区别是。UHierarchicalInstancedStaticMeshComponent是会按instance更新LOD的,而UInstancedStaticMeshComponent则全部统一使用同一个LOD。

本身的限制

由于目前的版本会自动合批,不是很确定UInstancedStaticMeshComponent还有没有必要性。不过至少会减少Actor的数量,也方便使用Cluster来减少GC负担。

InstanceMesh的限制:

  1. 无法使用负数的Scale
  2. 无法分别指定材质(per instance random可用于一些效果)
  3. 碰撞不会在运行时更新(这个现在应该没有了)

Crash

实际使用instancemesh,发现在编辑器里面直接ctrl+w会崩溃,主要原因是instance的生成直接放到构造函数里面了。

正确的做法是,将生成放到OnConstruction里面,还能在改变属性时自动更新。

Bound

在愉快的拖动关卡的时候,突然出现了这样的报错:

The actor will be placed outside the bounds of the current level. Continue?

于是找了下输出来源,这个Bound似乎是实时计算的

FBox CurrentLevelBounds(ForceInit);
if (InLevel->LevelBoundsActor.IsValid())
CurrentLevelBounds = InLevel->LevelBoundsActor.Get()->GetComponentsBoundingBox();
CurrentLevelBounds = ALevelBounds::CalculateLevelBounds(InLevel);
FBox CurrentLevelBounds(ForceInit);
if (InLevel->LevelBoundsActor.IsValid())
{
    CurrentLevelBounds = InLevel->LevelBoundsActor.Get()->GetComponentsBoundingBox();
}
else
{
    CurrentLevelBounds = ALevelBounds::CalculateLevelBounds(InLevel);
}

在有LevelBoundsActor的情况下,会使用指定的Bound

* Defines level bounds
* Updates bounding box automatically based on actors transformation changes or holds fixed user defined bounding box
* Uses only actors where AActor::IsLevelBoundsRelevant() == true
/**
 *
 * Defines level bounds
 * Updates bounding box automatically based on actors transformation changes or holds fixed user defined bounding box
 * Uses only actors where AActor::IsLevelBoundsRelevant() == true
 */

也就是说,没有自己指定边界Actor为自定义的话,其实没什么太大的意义。

可以在编辑器设置中关闭bPromptWhenAddingToLevelOutsideBounds。

UE4
本博客所有内容遵循CC BY-NC-SA 3.0协议, 如有转载,请注明出处。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK