Dots下给程序化生成的网格加上Lod

1 篇文章 0 订阅

近段时间研究dots terrain时有个想法是给程序动态生成的mesh加上lod。网上搜了下基本国内没发现几篇讲这个的文章。官网论坛上倒是有几篇帖子。于是这里一篇记录贴。

首先来看下如果不是实时生成的网格在dots下LOD是怎么回事。我们做个试验,新建一个空的gameobject作为父entity,加上Lod Group组件和convertToEntityscirpt,然后再给这个gameobje增加3个child,分别是一个方块一个全球和一个椭圆。运行一下看看Entity debugger里面的信息。可以看见在转化生成的4个Entity中,父entity上挂接了个MeshLodGroupComponent和一个LodGroupWorldReferencePoint的组件。这个MeshLodGroupComponent用两个float4保存了8个LodDistance的参数,而另一个point组件显然是用于地址的引用。

针对3个child Entity,三个entity的组件类型完全一样,与Lod相关的组件有:MeshLodCompoent,这个也是一个定义性质的组件,包含一个对父entity的字段。

RootLODRange,最大最小参数。

LODRange,这个层级的lod对应的最大最小距离

其他组件和一个不使用lod转化的mesh entity 一样。那问题来了,这些组件似乎都没有控制entity的显示?仔细观察发现,在HybridChunkInfo中,有个visible的值。不显示的这个字段的值都被设置为0。

弄清楚dots 下LOD的数据结构有哪些后 我们尝试通过代码来给4个entity加上这些组件。不过部分组件比如LODRange不能公共访问,并不能手动添加。于是尝试给父Entity加上MeshLodGroupComponent组件,给childEntity加上MeshLodComponent组件。写个脚本测试一下:

using Unity.Entities;
using Unity.Mathematics;
using Unity.Rendering;
using Unity.Transforms;
using UnityEngine;
using UnityEngine.Rendering;

[DisallowMultipleComponent]
public class TestLod : MonoBehaviour, IConvertGameObjectToEntity
{
    public Mesh lod0;
    public Mesh lod1;
    public Mesh lod2;
    public Material material;

    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        var lodGroupData = new MeshLODGroupComponent();
        lodGroupData.LocalReferencePoint = float3.zero;

        var lodDistances0 = new float4(float.PositiveInfinity);
        var lodDistances1 = new float4(float.PositiveInfinity);

        lodDistances0 = new float4(2 , 4 ,6 , 8);

        lodGroupData.LODDistances0 = lodDistances0;
        lodGroupData.LODDistances1 = lodDistances1;

        dstManager.AddComponentData(entity , lodGroupData);

        var entityLod0 = CreateRenderMeshEntity(lod0 , material , dstManager);
        var entityLod1 = CreateRenderMeshEntity(lod1 , material , dstManager);
        var entityLod2 = CreateRenderMeshEntity(lod2 , material , dstManager);

        dstManager.AddComponentData(entityLod0 , new MeshLODComponent { Group = entity , LODMask = 1 << 0 });
        dstManager.AddComponentData(entityLod1 , new MeshLODComponent { Group = entity , LODMask = 1 << 1 });
        dstManager.AddComponentData(entityLod2 , new MeshLODComponent { Group = entity , LODMask = 1 << 2 });

    }

    public static Entity CreateRenderMeshEntity (Mesh mesh , Material material , EntityManager dstManager)
    {
        var desc = new RenderMeshDescription(
            mesh ,
            material ,
            shadowCastingMode: ShadowCastingMode.On ,
            receiveShadows: true
            );

        var prefab = dstManager.CreateEntity();

        RenderMeshUtility.AddComponents(
            prefab ,
            dstManager ,
            desc);

        dstManager.AddComponentData(prefab , new LocalToWorld { Value = new float4x4(quaternion.identity , float3.zero) });

        return prefab;
    }
}

运行发现其他不能公开访问的组件都被加上去了,并且LOD功能显示正常。

但是从上面的分析似乎也发现了个局限性,似乎没法获取当前的LOD层级?要了解当前在哪个LOD层级,需要遍历各个子entity的HybridChunkInfo的CullingData.Visible字段。这个似乎不是一个有效率的做法。

Unity DOTS(DOTS: Data-Oriented Technology Stack)是Unity的一种数据导向技术堆栈,它旨在提高游戏性能和可扩展性。它基于实体组件系统(Entity-Component-System,ECS)的概念,其中游戏对象被拆分为实体(Entity)和组件(Component),并通过系统(System)进行处理。 在Unity DOTS中,可以使用实体组件系统来管理和处理游戏对象。通过将游戏对象转换为实体和组件的形式,可以实现高效的数据处理和并行计算。例如,在创建实体时,可以使用GameObjectConversionUtility.ConvertGameObjectHierarchy函数将GameObject转换为Entity,并使用IConvertGameObjectToEntity接口进行自定义转换。然后,可以使用系统(System)对实体和组件进行处理,例如旋转方块事件。 Unity DOTS的优势包括更高的性能,更好的可扩展性和更方便的并行计算。通过采用数据导向的设计,可以减少内存访问和数据处理的开销,从而提高游戏的帧率和响应性。 总而言之,Unity DOTS是一种数据导向的技术堆栈,通过实体组件系统和并行计算来提高游戏性能和可扩展性。它可以通过转换游戏对象为实体和组件的形式,并使用系统进行处理来实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Unity的Dots技术入门](https://blog.csdn.net/m0_37920739/article/details/108181541)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Unity DOTS简明教程](https://blog.csdn.net/mango9126/article/details/105219215)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值