当前位置: 首页 > news >正文

新的挑战ECS框架-开篇-EnTT基础

EnTT基础

目标:

  • 了解三件套:entt::registry / entt::entity / component

  • 学会用entt::view遍历"符合组件条件"的实体集合

  • 了解entt::hashed_string(哈希字符串)的用途与常见问题

  • 简单了解registry.ctx()是什么

设计思路

ECS框架,本质就是拿空间换时间,如果是传统的OOP架构,那么我们会在类之间进行跳转,所以有一个缓存cache命中率的问题,因为cpu喜欢读一块一块的内存,而不是分散开来的,oop就会有这个问题,比如不同游戏对象之间,update、render是先跑完update然后再轮到render,这种是会不断跳转读取,而ECS的思维,分为实体、组件、系统,实体就是一个ID/句柄,就是一个非负整数,组件就是简单的纯数据结构,系统相当于一个函数,其会负责如何更新,这种方式再更新的时候读取就是一块一块的连续内存了,极大的提升了性能。

  • 实体(entity)不是一个“带方法的对象”,更像是一个ID/句柄
  • 组件(component)是纯数据:位置、速度、血量、阵营……
  • 系统(system)负责“如何更新”:它会遍历一批拥有指定组件的实体,批量处理

这是个吃后期的架构,越到后面收益越明显:当你要新增玩法(比如“阻挡”“弹道”“技能”),往往是新增组件 + 新增系统,而不是在一堆类的继承链里打补丁。

实现

实体 Entity

entt::registry registry;entt::entity player = registry.create(); // 一个实体

建立一个实体很简单,需要使用entt::registry,这是"世界/数据库",我就理解是一个注册表,所有实体得先注册,用于创建实体、增删组件、查询视图。

组件 Component

struct position {float x;float y;
};struct velocity {float dx;float dy;
};

组件,只存放数据,简单的数据结构。这里的 emplace<T> 可以理解成:“给这个实体添加一个 T 组件,并初始化它的数据”。

registry.emplace<position>(player, 10.f, 20.f);
registry.emplace<velocity>(player, 1.f, 0.5f);

系统 System

这里我们会采用 view 遍历实体集合,当我们想找出“所有带 tag + position 的实体”,就可以建立一个 view:

auto view = registry.view<const tag, const position>();view.each([](const auto& entity_tag, const auto& pos) {if (entity_tag.id == "player"_hs) {spdlog::info("找到玩家,位置: ({}, {})", pos.x, pos.y);}
});

这段代码要牢记,后面游戏系统,都会沿用这个结构,用view找到目标实体,然后批处理。

嗯,我应该记住了,*_*!

哈希字符串:高效,节能,稳如狗

怎么像打广告,简单来说就是用整型数字来比较,就是把std::string 映射成整数,性能好。

entt::hashed_string可隐式转换成entt::id_type,这是个32位的无符号整型。

果然C++就是不讲道理,从语法层面可以直接改

我们可以采用 _hs 字面量来生成哈希值

using namespace entt::literals;
registry.emplace<tag>(player, "player"_hs, "player");

这里这个tag组件有一个id和std::string。这里有个问题要注意,就是hashed_string是不拥有原始字符串的值的,它好像是字符串指针,有点类似string_view,不保证生命周期,所以会存一个id,一个value值 std::string

struct tag {entt::id_type id;std::string value;
};

我们可以通过函数``registry.get(player)` 拿到组件,就能同时打印哈希值与原始文本:

auto player_tag = registry.get<tag>(player);
spdlog::info("玩家标签的哈希值: {}", player_tag.id);
spdlog::info("玩家标签的原始文本: {}", player_tag.value);

上下文变量(registry.ctx())

依赖注入,可以存放一些全局/共享数据;先记住它的定位:当你不想把某个全局对象做成单例,又希望系统之间能共享时,ctx 往往是一个更干净的选择

章节总结

了解entt基础知识,如何挂组件,如何通过view获取相应的实体,了解哈希字符串高效查找的原理,注意哈希字符串不保证生命周期的问题

http://www.jsqmd.com/news/487187/

相关文章:

  • 开源工具实现Cursor使用权限重置的技术方案
  • Spring Boot开发者必备:IntelliJ IDEA中Maven Helper和Spring Boot Assistant的隐藏功能
  • 在LocalDB 实例启动期间出错:无法启动 SQL Server 进程。
  • SolidWorks 2021爆炸动画制作全流程:从零件装配到动画导出的保姆级教程
  • L2-033 简单计算器
  • 万物识别-中文镜像效果可视化:热力图+边界框+置信度三重结果展示
  • 丹青识画效果实测:弱光/逆光/模糊图像下的意象感知鲁棒性分析
  • AI赋能版本控制:用快马平台开发智能git助手提升开发体验
  • **发散创新:用 Rust构建高性能微应用——从零搭建一个轻量级任务调
  • ANIMATEDIFF PRO部署教程:HTTPS反向代理配置与局域网多终端访问方案
  • Windows下redis安装
  • Azure DevOps Server:2026年3月份补丁
  • YOLO11 改进 - 主干网络_ RevCol可逆列网络:轻量级多列设计破解特征信息丢失难题,提升小目标与密集目标感知精度
  • AudioSeal实战教程:将AudioSeal集成至LangChain AudioTool实现AI工作流溯源
  • YOLO11 改进 - 即插即用 _ PST金字塔稀疏Transformer:粗粒度到细粒度推理优化特征提取,提升复杂场景适应性
  • YOLO11 改进 - 即插即用 _ 中小目标检测飙升:Hyper 超图赋能YOLO:轻量级设计实现跨层级信息交互,增强复杂场景感知
  • 【WPF】使用Costura.Fody将工程打包为单个EXE文件
  • 2026年3月音乐留学行业标杆出炉:TOP5机构如何解决师资与作品集痛点? - 资讯焦点
  • SystemUI通知栏卡顿?揭秘QS面板性能优化5大实战技巧
  • YOLO11 改进 - 即插即用 PST金字塔稀疏Transformer:粗粒度到细粒度推理优化特征提取,提升复杂场景适应性
  • 2026年珍珠奶茶TOP10品牌及产品最新评测盘点 - 资讯焦点
  • DPDK 高性能网络数据处理:原理、配置与实践
  • 【C++】类和对象--一篇带你解决运算符重载实例--日期类
  • 2026年南京靠谱装修公司推荐 南京装修公司口碑排行与避坑指南 - 资讯焦点
  • 构建生产级 AI Agent 系统的4大主流技术:反思、工具、规划与多智能体协作
  • Gemini 2.5 Pro代码实战评测:用C语言双缓冲日志案例验证其推理能力是否真比GPT-4强?
  • GLM-5-Turbo完全指南2026:中国新世代前沿AI模型
  • 【C++】一篇带你了解C++中的动态内存管理
  • 无刷VS有刷:电站清洁机器人硬件选型破局,解锁运维效率新范式
  • 徐林:龙骧锋会的稳健基石与敏锐操盘手 - 资讯焦点