Dots 常用操作

news2024/12/25 7:07:49

游戏中有多个蚂蚁群落,每个蚂蚁属于一个群落,如何设计数据结构?

  • 方法1:为蚂蚁组件添加一个属性 ID,会造成逻辑中大量分支语句,如果分支语句逻辑不平衡可能带来 Job 调度问题,每个蚂蚁会有一份蚂蚁群落 ID 属性的拷贝,海量蚂蚁时造成存储空间的浪费
  • 方法2:使用 TagComponent 标记不同的群落,蚂蚁群落个数不固定,运行时添加 TagComponent 不合适
    TagComponent 个数太多,造成 Archetype 数量爆炸
  • 方法3:使用 Shared Component 处理蚂蚁群落 ID,所有具有相同蚂蚁群落的蚂蚁共享相同的群落 ID 值,创建时确定,运行时不变,不会带来共享属性值频繁更新带来的 Structual Change 的影响,充分利用 WithShareComponentFilter 方法,快速通过一次查询处理所有蚂蚁初始化位置逻辑

读取工具选择

  • SystemAPl.Query+Foreach
  • IJobEntity / lJobChunk + EntityQuery
  • ComponentLookup

写入工具选择

  • EntityManager API
  • Entity Command Buffer
  • Entity Command Buffer ParallexWritter
  • 根据查询结果直接对引用组件的数据写入

DOTS程序的两种模式

  • Hybrid 混合模式:混合使用托管与非托管数据组件
  • Pure 纯净模式:只使用非托管数据组件

在这里插入图片描述
定义宏:UNITY_DISABLE_MANAGED_COMPONENTS,会禁用托管对象

DOTS调试宏

  • ENABLE_UNITY_COLLECTIONS_CHECKS
  • UNITY_DOTS_DEBUG

在这里插入图片描述
为 release 版本生成调试信息

在这里插入图片描述
查看泄露点

Benchmark

Entity 创建的几种方式

  1. 子场景 Bake 方式
  2. 通过 EntityManager 实例化 Prefab 的 Entity 原型方式
  3. 通过 ECS 的 parallelwriter 实例化 ParallelWriter.Instantiate(index, protoType)
  4. 通过 EntityManager 的 CreateEntity 接口以及 RenderMeshUtility 手动创建 Entity 对象

效率由高到低,大致是 1 > 2 > 3 > 4

创建Entity方案推荐与细节

  • 静态场景用子场景烘焙,动态场景对象用主线程创建
  • 多线程创建只在对象初始化需要大量额外计算时使用,这种情况较少
  • 通过 Prefab 实例化 Entity 的方式会在场景中额外保存一个 Entity,其 Archetype 与实例化后的 Entity 不同,所以对于有海量 prefab 对象的项目,注意 Archetype 数量对效率的影响。
  • 完全通过脚本化生成 Entity 不是不能用,但尽量少用。

Component组件添加的几种方式

  1. EntityManager.AddComponent(EntityQuery query, new Component)
  2. EntityManager.AddComponent(NativeArray<Entity> entitie, new Component)
  3. Foreach + EntityManager.AddComponent
  4. Ecb.AddComponent(EntityQuery query, new Component)
  5. Ecb.AddComponent(NativeArray<Entity> entities, new Component)
  6. Foreach + Ecb.AddComponent(entity, new Component)
  7. Ecb + lJobChunk ScheduleParallel
  8. Ecb + lJobEntity ScheduleParallel

EntityManager 接口添加 Component 总结

  • 使用上面 1 方式查询添加组件是最高效的方式
  • 缓存 Entity 数组无论是访问还是做添加删除是没有必要的,性能差
  • 多次调用为单个 Entity 添加组件接口会导致多次 structural change
  • 如果为单个 Entity 添加多个组件尽量通过以下两个接口:
    • CreateArchetype
    • AddComponent(EntityQuery,ComponentTypeset)
  • 先添加普通 Component,再添加 Enableable 修饰的 Component 比颠倒二者添加效率高
  • 通过 Enableable 组件禁用与启用组件比直接添加删除组件性能要高,因为避免 structural change
  • Structual Change 的操作主线程比工作线程更有效
  • 标签组件的性能开销比数据组件要低。

数据的存储与传递方式

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

静态共享数据区交互

  • static readonly xxx,只读
  • SharedStatic<T>,可变数据,可读写,可以是非托管或托管数据

适合 SharedStatic<T> 的使用场景,网络数据读取

  • 不可避免要做随机访问
  • 网络数据要与 Entity 实体对象有映射关系
  • 有跨 System 访问的需求
  • 有数据共享和读写的需求
public struct SharedCubesEntityColorMap
{
    public static readonly SharedStatic<SharedCubesEntityColorMap> SharedValue 
        = SharedStatic<SharedCubesEntityColorMap>.GetOrCreate<SharedCubesEntityColorMap>();
    
    public SharedCubesEntityColorMap(int capacity)
    {
        entityColorMap = new NativeHashMap<Entity, float3>(capacity, Allocator.Persistent);
    }
    
    //保存 entity 和 color 的映射关系
    public NativeHashMap<Entity, float3> entityColorMap; 
}

假设每个 entity 都有一个颜色属性,需要做随机访问,初始化时记录映射关系

void Update()
{
    //获取某个entity
    float3 color = SharedCubesEntityColorMap.SharedValue.Data.entityColorMap[entity];
    //对颜色进行处理
}

之后就可以在 mono 或 System 中对共享数据进行读写

System复杂度拆分策略

  • 多个处理相同事务的 System 耗时远远小于 1ms,可以考虑将这些 System 合并成一个 System
  • 如果一个 System 处理的事务耗时大于 1ms,考虑使用 Job 并行或 burst 编译优化,优化后仍然远远大于 1ms,可以考虑对 System 做事务拆分
  • 耗时过低的 System 影响其中 Job 的并行程度,耗时过高的 System 影响 CPU 调度

Sub Scene 管理

在这里插入图片描述
Dots 中 Scene 结构,Section 用于对子场景进行分组,默认情况下,所有的 entity 都会在 section 0 上

在这里插入图片描述
可以在子场景物体上挂载 SceneSectionComponent 官方脚本,设置 Section Index,Section Index = 0 的会优先加载

在这里插入图片描述
Initialization 中的 Scene System Group

在这里插入图片描述

如何标识子场景

  • EntitySceneReference 直接引用子场景
  • Hash128 GUID 尽量避免使用
  • Entity 子场景加载后返回的 meta entity
[Serializable]
public struct SubscenesReferences : IComponentData
{
    //sub scene资源引用
    public EntitySceneReference cubeSceneReference;
    //sub scene加载后返回的entity,卸载时需要
    public Entity cubeSceneMetaEntity;
    
    public EntitySceneReference sphereSceneReference;
    public Entity sphereSceneMetaEntity;
}
public class SubscenesLoaderAuthoring : MonoBehaviour
{
    [SerializeField] 
    public SubscenesReferences references;
    private class SubscenesLoaderBaker : Baker<SubscenesLoaderAuthoring>
    {
        public override void Bake(SubscenesLoaderAuthoring authoring)
        {
            var entity = GetEntity(TransformUsageFlags.None);
            AddComponent(entity, authoring.references);
        }
    }
}
public partial struct ScenesLoadSystem : ISystem, ISystemStartStop
{
    [BurstCompile]
    public void OnCreate(ref SystemState state)
    {
        state.RequireForUpdate<SubscenesReferences>();
    }

    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        var references = SystemAPI.GetSingletonRW<SubscenesReferences>();
        //场景状态
        SceneSystem.SceneStreamingState ssstate = SceneSystem.GetSceneStreamingState(state.WorldUnmanaged, references.ValueRO.cubeSceneMetaEntity);
       
        if (ssstate == SceneSystem.SceneStreamingState.LoadedSuccessfully)
        {
            //卸载子场景内容,移除 meta entity 上的 RequestSceneLoaded
            //SceneSystem.UnloadScene(state.WorldUnmanaged, references.ValueRW.cubeSceneMetaEntity);
            //完全卸载
            //SceneSystem.UnloadScene(state.WorldUnmanaged, references.ValueRW.cubeSceneMetaEntity, SceneSystem.UnloadParameters.DestroyMetaEntities);
        }

        ssstate = SceneSystem.GetSceneStreamingState(state.WorldUnmanaged, references.ValueRO.sphereSceneMetaEntity);
        if (ssstate == SceneSystem.SceneStreamingState.LoadedSectionEntities)
        {
            //根据 meta entity 加载场景
            SceneSystem.LoadSceneAsync(state.WorldUnmanaged, references.ValueRW.sphereSceneMetaEntity);
        }
    }

    public void OnStartRunning(ref SystemState state)
    {
        var references = SystemAPI.GetSingletonRW<SubscenesReferences>();
        if (references.ValueRO.cubeSceneReference.IsReferenceValid)
        {
            references.ValueRW.cubeSceneMetaEntity =
                SceneSystem.LoadSceneAsync(state.WorldUnmanaged, references.ValueRO.cubeSceneReference);
        }
        if (references.ValueRO.sphereSceneReference.IsReferenceValid)
        {
            references.ValueRW.sphereSceneMetaEntity =
                SceneSystem.LoadSceneAsync(state.WorldUnmanaged, references.ValueRO.sphereSceneReference, 
                new SceneSystem.LoadParameters
                {
                    //不自动加载
                    AutoLoad = false
                });
        }
    }

    public void OnStopRunning(ref SystemState state) {}
}

在这里插入图片描述
子场景加载后,会生成两个额外的 entity,即 meta entity 和 section entity

public partial struct SceneSectionsLoadSystem : ISystem
{
    private float timer = 1f;

    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        var sectionEntities = SystemAPI.GetSingletonBuffer<ResolvedSectionEntity>();
        NativeArray<Entity> sectionEntitiesArray = CollectionHelper.CreateNativeArray<Entity>(sectionEntities.Length, Allocator.Temp);
        for (int i = 0; i < sectionEntities.Length; i++)
        {
            sectionEntitiesArray[i] = sectionEntities[i].SectionEntity;
        }

        timer -= SystemAPI.Time.DeltaTime;
        if (timer < 0)
        {
            for (int i = 0; i < sectionEntitiesArray.Length; i++)
            {
                var sectionState = SceneSystem.GetSectionStreamingState(state.WorldUnmanaged, sectionEntitiesArray[i]);
                if (sectionState == SceneSystem.SectionStreamingState.Loaded)
                {
                    state.EntityManager.RemoveComponent<RequestSceneLoaded>(sectionEntitiesArray[i]);
                    if (i == sectionEntitiesArray.Length - 1)
                        timer = 1.0f;
                }
                else if (sectionState == SceneSystem.SectionStreamingState.Unloaded)
                {
                    state.EntityManager.AddComponent<RequestSceneLoaded>(sectionEntitiesArray[i]);
                    if (i == sectionEntitiesArray.Length - 1)
                        timer = 1.0f;
                }
            }
        }
        sectionEntitiesArray.Dispose();
    }
}

section 的动态加载和卸载,实际开发中可以把地图分成不同的 scetion,然后按需加载

Scene section上Entity的交叉引用关系

  • Section 0 里的 Entity 可以被其他 Section 的 Entity 引用
  • 单个 Section 内的 Entity 之间可以彼此引用
  • 除 Section 0 外其他 Section 间的 Entity 彼此是不能被引用的

参考

《DOTS之路》系列课程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2265162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML与数据抓取:GET与POST方法详解

讲GET和POST就不能只讲GET和POST 你要讲HTTP请求的基本概念&#xff1a; HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是互联网上应用最为广泛的一种网络协议&#xff0c;主要用于Web浏览器与Web服务器之间的数据通信。HTTP是一个基于…

Android 之 Activity 的启动模式(launchMode)

一、Activity 启动模式 在实际项目中&#xff0c;应该根据项目的实际需要来为每个 Activity 指定恰当的启动模式 launchMode。启动模式一共有四种&#xff0c;分别是 standard、singleTop、singleTask 和 singleInstance。可以在 AndroidManifest.xml 中通过给 <activity&g…

软考:系统架构设计师教材笔记(持续更新中)

教材中的知识点都会在。其实就是将教材中的废话删除&#xff0c;语言精练一下&#xff0c;内容比较多&#xff0c;没有标注重点 系统架构概述 定义 系统是指完成某一特定功能或一组功能所需要的组件集&#xff0c;而系统架构则是对所有组件的高层次结构表示&#xff0c;包括各…

大模型应用—IOPaint 图片去水印

IOPaint 是由 SOTA AI 模型提供支持的免费开源修复和修复工具,可以轻松实现图片去水印,去除图片不需要的部分,是目前效果最好的一个项目!完全免费开源 IOPaint 已经托管到 hugging face上,打开就可以直接免费使用,需要外网环境! 在线免费使用:【链接直达】 如果你需要…

Go C编程 第6课 无人机 --- 计算旋转角

旋转的秘密---认识角度 rt、lt命令学习 goc电子课程 一、编程步骤 第一步 第二步 第三步 第四步 二、画“四轴无人机” &#xff08;一&#xff09;、画第一根机轴 &#xff08;二&#xff09;、画第二根机轴 &#xff08;三&#xff09;、画完整的无人机 三、画“多轴无人…

v3s点RGB屏 40pin 800x480,不一样的点屏,不通过chosen。

一、背景、目的、简介。 一般来说&#xff0c;通过uboot将屏幕参数传给kernel&#xff0c;是通过修改设备树。 uboot和kernel都需要屏幕点亮。uboot侧重于显示一张图片。而kernel则多是动画。 在这里&#xff0c;我先是找到了一个裸机点屏的代码。将其编译成静态库后&#x…

【编译原理】编译原理知识点汇总·语法分析器(消除左递归、消除二义性、自顶向下语法分析、自下向上语法分析)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;编译原理_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. …

golang 并发--goroutine(四)

golang 语言最大的特点之一就是语法上支持并发&#xff0c;通过简单的语法很容易就能创建一个 go 程&#xff0c;这就使得 golang 天生适合写高并发的程序。这一章节我们就主要介绍 go 程&#xff0c;但是要想完全理解 go 程我们需要深入研究 GPM 模型&#xff0c;关于 GPM 模型…

Wireshark协议相关功能:过滤、启用/禁用、导出和统计查看

简述 Wireshark 是一个非常强大的网络分析工具&#xff0c;广泛用于网络故障排查、安全分析、协议分析等任务。在使用 Wireshark 进行网络抓包和协议分析时&#xff0c;掌握一些基本的操作技巧对于提高效率和准确性至关重要。本文将介绍 Wireshark 中如何进行协议相关的操作&a…

渗透Vulnhub-DC-9靶机

本篇文章旨在为网络安全渗透测试行业靶机教学。通过阅读本文&#xff0c;读者将能够对渗透Vulnhub系列DC-6靶机有定的了解 一、信息收集阶段 DC-9靶场信息: DC-9靶场介绍&#xff1a; https://www.vulnhub.com/entry/dc-9,412/ DC-9靶场下载&#xff1a; https://download.vu…

【Linux系列】Shell 命令:`echo ““ > img.sh`及其应用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

云图库平台(三)——后端用户模块开发

需求分析&#xff1a;对于用户模块而言&#xff0c;通常要实现下列功能&#xff1a; 用户注册&#xff1a;用户输入账号、密码、确认密码进行注册账号用户登录&#xff1a;用户通过输入账号、密码登录注册账号获取当前登录用户信息&#xff1a;即得到当前已登录用户的信息用户…

怎么设置电脑密码?Windows和Mac设置密码的方法

为电脑设置密码是保护个人信息安全的重要措施。无论是Windows系统还是MacOS系统&#xff0c;设置密码的步骤都相对简单&#xff0c;但需要根据不同的操作系统选择不同的方法。 一、Windows系统电脑密码设置 方法一&#xff1a;通过控制面板设置账户密码 点击桌面左下角的“开…

思考: 与人交际

前晚可能是因为我和某个曾经的同学&#xff08;我认为是朋友&#xff0c;但是它真的很讨厌&#xff0c;现在觉得它在PUA很多人&#xff09;发生了一件事情&#xff0c;现在没关系了&#xff0c;算是到此结束了&#xff0c;再也不见。 让我看清楚了人和人的交际需要什么&#xf…

突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除

GitLab停止为中国大陆、香港和澳门地区提供服务&#xff0c;要求用户在60天内迁移账号&#xff0c;否则将被删除。这一事件即将引起广泛的关注和讨论。以下是对该事件的扩展信息&#xff1a; 1. 背景介绍&#xff1a;GitLab是一家全球知名的软件开发平台&#xff0c;提供代码托…

vulnhub靶场-matrix-breakout-2-morpheus攻略(截止至获取shell)

扫描出ip为192.168.121.161 访问该ip&#xff0c;发现只是一个静态页面什么也没有 使用dir dirsearch 御剑都只能扫描到/robots.txt /server-status 两个页面&#xff0c;前者提示我们什么也没有&#xff0c;后面两个没有权限访问 扫描端口&#xff0c;存在81端口 访问&#x…

美股开户网:谷歌搜索迎“大动作”:推出AI模式切换选项应对竞争压力

谷歌的AI战略新举措 近日&#xff0c;硅谷权威媒体《The Information》报道了谷歌即将在其搜索引擎中推出一项全新的功能——“切换到AI模式”。这一新功能将为用户提供更加智能、对话式的回答&#xff0c;标志着谷歌对人工智能&#xff08;AI&#xff09;领域的进一步布局&am…

如何在window 使用 conda 环境下载大模型

最近开始学习 变形金刚&#xff0c;最大的问题就是 huggingface 无法访问&#xff0c;无论是翻墙还是通过本地镜像网站HF-Mirror&#xff0c;然后再通过git下载都很慢&#xff0c;影响学习进度&#xff0c;后面看了如下文章&#xff0c;Huggingface配置镜像_huggingface镜像-CS…

WebRTC学习二:WebRTC音视频数据采集

系列文章目录 第一篇 基于SRS 的 WebRTC 环境搭建 第二篇 基于SRS 实现RTSP接入与WebRTC播放 第三篇 centos下基于ZLMediaKit 的WebRTC 环境搭建 第四篇 WebRTC 学习一&#xff1a;获取音频和视频设备 第五篇 WebRTC学习二&#xff1a;WebRTC音视频数据采集 文章目录 系列文章…

内部知识库的未来展望:技术融合与用户体验的双重升级

在当今数字化飞速发展的时代&#xff0c;企业内部知识库作为知识管理的关键载体&#xff0c;正站在变革的十字路口&#xff0c;即将迎来技术融合与用户体验双重升级的崭新时代&#xff0c;这一系列变化将深度重塑企业知识管理的格局。 一、技术融合&#xff1a;开启知识管理新…