1

我有一种特定的方式来生成网格和构建我的场景,这使得遮挡剔除非常直接和最优。现在我只需要知道如何使用 ECS 混合渲染器有效地显示或隐藏网格。我考虑将图层更改为 RenderMesh 组件中的隐藏层,但 RenderMesh 组件是 ISharedComponentData,因此不支持作业化或突发。我看到了 Unity BatchRendererGroup API,它的 OnPerformCulling 回调看起来很有希望,但我不知道是否可以连接到 HybridRenderSystem 的内部 BatchRenderGroup。我还看到了我猜想禁用实体呈现的 DisableRendering IComponentData 标记。但是,同样,这只能从主线程中完成。我可以编写自己的解决方案来使用图形渲染网格。

这有可能吗?预期用途是什么?

4

3 回答 3

1

我不确定这是最好的选择,但您可以尝试并行命令缓冲区:

var ecb = new EntityCommandBuffer( Allocator.TempJob );
var cmd = ecb.AsParallelWriter();

/* job 1 executes with burst & cmd adds/removes Disabled or DisableRendering tags */

// (main thread) job 2 executes produced commands:
Job
    .WithName("playback_commands")
    .WithCode( () =>
    {
        ecb.Playback( EntityManager );
        ecb.Dispose();
    }
    ).WithoutBurst().Run();
于 2020-08-10T18:46:17.970 回答
0

答案是你不能也不应该!Unity 混合渲染通过按顺序排列数据来提高速度。如果每个网格都有一个布尔值,允许您显示或隐藏网格,Unity 仍然需要评估它,我猜这不在他们的设计理念中。正如我发现的那样,整个设计理念对我来说并不奏效。

我的世界由程序生成的地形网格块组成(想想我的世界,但更好;))问题是每个块都有自己的 RenderMesh 和独特的网格......这意味着每个块都有自己的......块...在内存中xD。这听起来很合适,但效率极低。我决定一起放弃 Hybrid ECS 并使用好的旧游戏对象。仅通过这一更改,我就看到了 4 倍的性能提升(从 200 到 800 fps)。我只是使用 MeshRenderer.enabled 属性来有效地启用和禁用渲染。为了解决这个问题,我简单地存储了一个网格边界数组和一个布尔值,以确定它是否可见。然后我可以在作业中评估这个数组,并返回一个索引列表,其中包含需要更改其可见性的所有块。这只留下了为主线程设置一些布尔值,这根本不是很昂贵......这不是我正在寻找的 ECS 友好解决方案,但从它的外观来看,ECS 并不是我在这里的朋友。为我的世界的每个部分拥有独特的网格显然不是混合 ECS 的预期用例。

于 2020-08-16T20:57:44.297 回答
0

还有另一种隐藏/显示实体的方法。但它要求您在空间上将相邻实体分组(您可能已经这样做了)。然后,您将不是一个一个地遮挡特定的实体,而是它们的整个块(空间扇区)。这要归功于以下惊人的力量:

块组件数据

var queryEnabled = EntityManager.CreateEntityQuery(
        ComponentType.ReadOnly<RenderMesh>()
    ,   ComponentType.Exclude<Disabled>()
);

queryEnabled.SetSharedComponentFilter( new SharedSector {
        Value = new int3{ x=4 , y=1 , z=7 }
} );

EntityManager.AddChunkComponentData( queryEnabled , default(Disabled) );
// EntityManager.RemoveChunkComponentData<Disabled>( queryDisabled );

public struct SharedSector : ISharedComponentData
{
    public int3 Value;
}
于 2020-08-11T16:41:38.167 回答