初探unity中的ECS

news2024/11/28 2:33:15

ECS是一种软件架构模式,就像MVC一样。ECS最早在游戏《守望先锋》中提及到的相关链接。ECS具体是指实体(entity)、 组件(component)和系统(system):

实体:实体是一个ID,它是一个唯一的标识符,用于标识一个对象,它本身不包含任何数据,只是一个ID,它的作用是用于标识一个对象,它的数据是由组件来提供的。

组件:组件是一个数据结构,它包含了一些数据,用于描述一个对象的属性,组件是没有任何行为的,它只是一个数据结构。

系统:主要用户逻辑处理,进行状态迁移。系统中不保留数据,且是无状态的。

三者之间的关系如下图所示:
请添加图片描述

ECS在unity中出现的原因

在使用unity开发的时候,monobehaviour是我们最常用的,然而monobehaviour中的update是基于gameobject去更新的且无序的,这样很容易造成memory cache miss。而ECS是基于数据的,它将具有相同Component组合的Entity放在一起,这样可以更好的利用cache,提高性能。

archetype

通过上面的图和介绍我们知道通过将不同的Component组合和Entity一起组成了GameOjbect,Component不同组合的唯一性在ECS中被称为archetype。在ECS中,archetype是一个很重要的概念,它是用来管理内存的,每个archetype都有一个chunk列表,chunk是一种内存管理方式。

请添加图片描述

上图中EntityA和EntityB具有相同的Component组合,所以它们属于同一个Archetype M,而EntityC具有不同的Component组合,所以它们属于不同的Archetype N。

下图是一个chunk的内存排布:
请添加图片描述

component在chunk中的排布.
请添加图片描述

Archetype
ArchetypeChunkData Chunks;
ComponentTypeInArchetype* Types;
ArchetypeChunkData
Chunk** p;
Chunk

执行System

请添加图片描述

unity会自己实例化system,system里的方法默认都在主线程执行,可以通过一下几种方式来实现多线程

  • Entities.ForEach
  • Job.WithCode
  • IJobEntity
  • IJobEntityBatch
  • C# Job System

各部分的创建

下面是一个简单的例子,创建一个CustomSystem,它会在每一帧中更新CustomData的值。ComponentData不一定要和MonoBehaviour一起使用,它可以单独使用,像一些CPU密集性的计算可以使用ComponentData来实现。下面的示例重点是为了说明各部分的创建过程,从LaunchECS中可以发现仅仅使用了World中的EntityManager来创建了一个Entity,系统的创建被注视掉了。这是因为unity会自己实例化system,所以我们不需要手动创建system。

public class Custom : MonoBehaviour
{
    private void Awake()
    {
        LaunchECS();
    }

    private void LaunchECS()
    {
        var world = World.DefaultGameObjectInjectionWorld;
        world.EntityManager.CreateEntity(typeof(CustomData));
        // world.CreateSystem<CustomSystem>();
    }
}

public struct CustomData : IComponentData
{
    public int Value;
}

public partial class CustomSystem : SystemBase
{
    [BurstCompile]
    protected override void OnUpdate()
    {
        var timeElapsedTime = World.Time.ElapsedTime;
        Entities.ForEach((ref CustomData customData) =>
        {
            customData.Value = (int)(100 * math.sin(timeElapsedTime));
        }).ScheduleParallel();
    }
}

游戏制作

ECS的大致情况我们已经了解了,那如何在项目中应用呢。下面是一个简单的例子,我们创建一个Cube,然后通过ECS来控制它的移动。

  1. 将下面的代码放到名叫MoveMono的cs文件中,
  2. 然后在场景中添加一个sub scene
  3. 在sub scene中添加一个Cube,然后添加一个MoveMono组件,并设置Velocity的值。
    运行后,我们会发现Cube会按照我们设置的Velocity的值进行移动。
[GenerateAuthoringComponent]
public struct MoveData : IComponentData
{
    public float3 Velocity; 
}
    
public partial class MoveSystem : SystemBase
{
    [BurstCompile]
    protected override void OnUpdate()
    {
        var deltaTime = World.Time.DeltaTime;
        Entities.ForEach((ref Translation translation, in MoveData moveData) =>
        {
            translation.Value += moveData.Velocity * deltaTime;
        }).ScheduleParallel();
    }
}

上面代码中使用了GenerateAuthoringComponent,这个属性将会自动生成一个名为MoveMono的MonoBehaviour,所有虽然我们并没有显示的创建MoveMono,但是我们可以给GameObject添加组件是可以看到MoveMono.

除了GenerateAuthoringComponent属性以外还有其他方式去将ComponentData和MonoBehaviour关联起来,还可以有其他方式。我们将在后面的gameplay文章中介绍。

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

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

相关文章

IDEA如何进行远程Debug调试(二)解决jar包运行报错的问题

一、解决jar包运行报错的问题 上文提到在进行debug远程调试的时候&#xff0c;打包后的jar包本地无法运行&#xff0c;报如下的错误 ​​​​​​​IDEA如何进行远程Debug调试-CSDN博客 查看报错是找不到对应的类&#xff0c;那么我们使用jd-gui的反编译工具&#xff0c;看看…

opencv中使用cuda加速图像处理

opencv大多数只使用到了cpu的版本&#xff0c;实际上对于复杂的图像处理过程用cuda&#xff08;特别是高分辨率的图像&#xff09;可能会有加速效果。是否需要使用cuda需要思考&#xff1a; 1、opencv的cuda库是否提供了想要的算子。在CUDA-accelerated Computer Vision你可以…

Sklearn、TensorFlow 与 Keras 机器学习实用指南第三版(三)

原文&#xff1a;Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第六章&#xff1a;决策树 决策树是多功能的机器学习算法&#xff0c;可以执行分类和回归任务&#xff0c;甚至多输出任务。它们…

Android BitmapShader setLocalMatrix缩放Bitmap高度重新onMeasure,Kotlin

Android BitmapShader setLocalMatrix缩放Bitmap高度重新onMeasure&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://sc…

Kubernetes基础(十一)-CNI网络插件用法和对比

1 CNI概述 1.1 什么是CNI&#xff1f; Kubernetes 本身并没有实现自己的容器网络&#xff0c;而是借助 CNI 标准&#xff0c;通过插件化的方式来集成各种网络插件&#xff0c;实现集群内部网络相互通信。 CNI&#xff08;Container Network Interface&#xff0c;容器网络的…

JavaScript原型和原型链是什么

JavaScript原型和原型链是Web前端技术中的重要概念&#xff0c;了解它们可以帮助开发者更好地理解JavaScript对象的创建和继承机制。本文将深入探讨JavaScript原型和原型链&#xff0c;并提供相关的示例代码和解析。 首先&#xff0c;让我们了解一下JavaScript中的原型。每个J…

ubuntu 18.04修改网卡名称

1.原来网卡配置 现在要把enp3s0的名称改为eth0 2. 总共修改三个文件 第一个修改 sudo vi /etc/default/grub 添加最后一行 GRUB_CMDLINE_LINUX"net.ifnames0 biosdevname0" 第二个修改sudo vi /etc/udev/rules.d/70-persistent-net.rules 如果没有就新建文件&a…

用通俗易懂的方式讲解:12 个大模型 RAG 痛点及解决方案

受 Barnett 等人的论文《工程检索增强生成系统时的七个失败点》启发&#xff0c;让我们在本文中探讨论文中提到的七个失败点以及开发 RAG 管道时的五个常见痛点。 论文&#xff1a;https://arxiv.org/pdf/2401.05856.pdf 更重要的是&#xff0c;我们将深入探讨这些 RAG 痛点的…

vue基本语法总结大全

vue基本语法 文章目录 vue基本语法基本用法内容渲染指令属性绑定指令使用js表达式事件绑定指令条件渲染指令v-else和v-else-if指令列表渲染指令v-for中的key 组件化开发安装详细讲解 第三方组件1. 组件间的传值2. element-ui介绍3. 组件的使用4. 图标的使用 Axios网络请求1. Ax…

Redis-缓存问题及解决方案

本文已收录于专栏 《中间件合集》 目录 概念说明缓存问题缓存击穿问题描述解决方案 缓存穿透问题描述解决方案 缓存雪崩问题描述解决方案提高缓存可用性过期时间配置熔断降级 总结提升 概念说明 Redis是一个开源的内存数据库&#xff0c;也可以用作缓存系统。它支持多种数据结构…

网络攻防模拟与城市安全演练 | 图扑数字孪生

在数字化浪潮的推动下&#xff0c;网络攻防模拟和城市安全演练成为维护社会稳定的不可或缺的环节。基于数字孪生技术我们能够在虚拟环境中进行高度真实的网络攻防模拟&#xff0c;为安全专业人员提供实战经验&#xff0c;从而提升应对网络威胁的能力。同时&#xff0c;在城市安…

UE中对象创建方法示例和类的理解

对象创建方法示例集 创建Actor示例 //创建一个护甲道具 AProp* armor GetWorld()->SpawnActor<AProp>(pos, rotator); 创建Component示例 UCapsuleComponent* CapsuleComponent CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleComponent&qu…

【HarmonyOS应用开发】HTTP数据请求(十四)

文章末尾含相关内容源代码 一、概述 日常生活中我们使用应用程序看新闻、发送消息等&#xff0c;都需要连接到互联网&#xff0c;从服务端获取数据。例如&#xff0c;新闻应用可以从新闻服务器中获取最新的热点新闻&#xff0c;从而给用户打造更加丰富、更加实用的体验。 那么…

【Linux网络编程三】Udp套接字编程网络应用场景

【Linux网络编程三】Udp套接字编程网络应用场景 应用场景一&#xff1a;远程命令执行应用场景二&#xff1a;与Windos端相互通信应用场景三&#xff1a;简单聊天1.多线程化2.输入输出分开 应用场景一&#xff1a;远程命令执行 简单的服务器上一篇已经完成&#xff0c;接下来我…

前端小案例——动态导航栏文字(HTML + CSS, 附源码)

一、前言 实现功能: 这案例是一个具有动态效果的导航栏。导航栏的样式设置了一个灰色的背景&#xff0c;并使用flex布局在水平方向上平均分配了四个选项。每个选项都是一个li元素&#xff0c;包含一个文本和一个横向的下划线。 当鼠标悬停在选项上时&#xff0c;选项的文本颜色…

flask+pyinstaller实现mock接口,并打包到exe运行使用postman验证

flask代码 from flask import Flask, request, jsonifyapp Flask(__name__)app.route("/login", methods[POST]) def login():username request.json.get("username").strip() # 用户名password request.json.get("password").strip() # 密…

FastAdmin青动CRM-E售后

应用介绍 一款基于FastAdminThinkPHP和uniapp开发的CRM售后管理系统&#xff0c;旨在助力企业销售售后全流程精细化、数字化管理&#xff0c;主要功能&#xff1a;客户、合同、工单、任务、报价、产品、库存、出纳、收费&#xff0c;适用于&#xff1a;服装鞋帽、化妆品、机械机…

随机森林超参数的网格优化(机器学习的精华--调参)

随机森林超参数的网格优化&#xff08;机器学习的精华–调参&#xff09; 随机森林各个参数对算法的影响 影响力参数⭐⭐⭐⭐⭐几乎总是具有巨大影响力n_estimators&#xff08;整体学习能力&#xff09;max_depth&#xff08;粗剪枝&#xff09;max_features&#xff08;随机…

STM32--SPI通信协议(3)SPI通信外设

前言 硬件SPI&#xff1a;通过硬件电路实现&#xff0c;所以硬件SPI速度更快&#xff0c;有专门的寄存器和 库函数 &#xff0c;使用起来更方便。 软件SPI&#xff1a;也称模拟SPI&#xff0c;通过程序控制IO口电平模拟SPI时序实现&#xff0c;需要程序不断控制IO电平翻转&am…

网工每日一练(2月4日)

试题1 通过HFC网络实现宽带接入&#xff0c;用户端需要的设备是&#xff08;A&#xff09;&#xff0c;局端用于控制和管理用户的设备是&#xff08;D&#xff09;。 &#xff08;1&#xff09;A.Cable Modem B.ADSL Modem C.OLT D.CMTS &#xff08;2&#xff09;A. Cable Mo…