Faster-Godot4 dotnet 之ECS框架第一章:ECS框架安装,并体验ECS
打开Godot4引擎之后在任意的目录下新建一个C#脚本此时在项目根目录下会自动生成一个.sln文件可以打开文件资源管理器进入到项目根目录然后双击打开.sln会自动打开VisualStudio2026它能自动识别为解决方案项目。打开cmd到项目根目录并且确认已经安装donet-sdk8.0。安装ECS框架和扩展# 安装核心Arch ECS包 dotnet add package Arch # 可选配套包推荐一起装#Arch.System 系统基类dotnet add package Arch.System#Arch.System.SourceGenerator 源代码生成器减少反射大幅提速dotnet add package Arch.System.SourceGenerator#Arch-Events 事件扩展dotnet add package Arch-Events然后要引入Arch包到项目中ProjectSdkGodot.NET.Sdk/4.7.0PropertyGroupTargetFrameworknet8.0/TargetFrameworkEnableDynamicLoadingtrue/EnableDynamicLoadingPublishReadyToRuntrue/PublishReadyToRunSelfContainedtrue/SelfContainedAllowUnsafeBlocksTrue/AllowUnsafeBlocks/PropertyGroupItemGroupPackageReferenceIncludeArchVersion2.1.0/PackageReferenceIncludeArch-EventsVersion2.1.0/PackageReferenceIncludeArch.SystemVersion1.1.0/PackageReferenceIncludeArch.System.SourceGeneratorVersion2.1.0/TrimmerRootAssemblyIncludeGodotSharp/TrimmerRootAssemblyInclude$(TargetName)//ItemGroupItemGroupCondition$(Configuration)ReleaseTrimmerRootAssemblyInclude$(AssemblyName)RootModeAll/!-- 保护Arch程序集防止裁剪Arch内部泛型、组件元数据 --TrimmerRootAssemblyIncludeArchRootModeAll//ItemGroup/Project可以在场景中添加一个太阳、天空环境5.然后必须创建一个相机才可以看得见5. 调整相机角度到合适的位置6. 编写一个ECS脚本代码创建25万个物体给物体绕着任意旋转轴旋转新建一个CreateMultiEcsEntity.cs脚本usingArch;usingArch.Core;usingGodot;usingSystem;usingSystem.Diagnostics;usingSystem.Runtime.CompilerServices;usingSystem.Runtime.InteropServices;usingSystem.Threading.Tasks;// ECS data is rendered by one MultiMesh; no per-entity Node3D is created.publicpartialclassCreateMultiEcsEntity:Node3D{[Export]publicMeshTorusPrefab{get;set;}[Export(PropertyHint.Range,1,200000,1)]publicintGridSize{get;set;}500;[Export]publicfloatSpacing{get;set;}2.2f;privateWorld_ecsWorld;privateMultiMesh_multiMesh;privateEntityState[]_statesArray.EmptyEntityState();// Filled in parallel; submitted through Godots main-thread-only MultiMesh API.privateTransform3D[]_transformsArray.EmptyTransform3D();publicstructRotateComp{publicintIndex;publicVector3Axis;publicfloatSpeed;}ParallelOptionsparallelOpt;[StructLayout(LayoutKind.Sequential,Pack1)]privateunsafestructEntityState{publicVector3Position;publicVector3Axis;publicfloatSpeed;publicQuaternionRotation;//public fixed byte Padding[20];}publicoverridevoid_Ready(){varsizeUnsafeUnsafe.SizeOfEntityState();parallelOptnewParallelOptions{MaxDegreeOfParallelismSystem.Environment.ProcessorCount};if(TorusPrefabnull){GD.PrintErr(TorusPrefab must reference a Mesh.);return;}_ecsWorldWorld.Create();_multiMeshnewMultiMesh{TransformFormatMultiMesh.TransformFormatEnum.Transform3D,MeshTorusPrefab};AddChild(newMultiMeshInstance3D{Multimesh_multiMesh});SpawnTorusEcsEntities(Math.Max(1,GridSize));}publicvoidSpawnTorusEcsEntities(intgridSize){intcountchecked(gridSize*gridSize);_statesnewEntityState[count];_transformsnewTransform3D[count];_multiMesh.InstanceCountcount;for(intx0;xgridSize;x){for(intz0;zgridSize;z){intindexx*gridSizez;Vector3axisnewVector3((float)GD.RandRange(1.0,2.0),(float)GD.RandRange(2.0,3.0),(float)GD.RandRange(1.0,2.0)).Normalized();floatspeed(float)GD.RandRange(0.4,1.5);Vector3positionnewVector3((x-(gridSize-1)/2.0f)*Spacing,0,(z-(gridSize-1)/2.0f)*Spacing);_states[index]newEntityState{Positionposition,Axisaxis,Speedspeed,RotationQuaternion.Identity};_transforms[index]newTransform3D(Basis.Identity,position);_ecsWorld.Create(newRotateComp{Indexindex,Axisaxis,Speedspeed});}}SubmitTransforms();}publicoverridevoid_Process(doubledelta){if(_states.Length0)return;ulongt1Time.GetTicksMsec();floatdt(float)delta;// CPU-side ECS rotation and Transform3D construction run in parallel.Parallel.For(0,_states.Length,parallelOpt,i{refEntityStatestateref_states[i];floatangleDeltastate.Speed*dt;QuaternionrotStepnewQuaternion(state.Axis,angleDelta);state.RotationrotStep*state.Rotation;// 构造变换存入transforms数组_transforms[i]newTransform3D(newBasis(state.Rotation),state.Position);});// MultiMesh is a Godot resource and must only be modified from the main thread.SubmitTransforms();ulongt2Time.GetTicksMsec();GD.Print(t2-t1);}privatevoidSubmitTransforms(){for(inti0;i_transforms.Length;i){_multiMesh.SetInstanceTransform(i,_transforms[i]);}}publicoverridevoid_ExitTree(){_ecsWorld?.Dispose();}}然后把脚本拖拽到根节点8. 要选择一个网格最后构建项目运行项目25万个物体同时旋转耗时9 ~ 10毫秒左右如果打包成Release包可以进一步加快速度到6 ~ 7毫秒左右的耗时。使用传统的节点对象创建CreateMultiMonoObj.cs脚本usingGodot;usingSystem;publicpartialclassCreateMultiMonoObj:Node3D{privateconstintGridSize500;privateconstintInstanceCountGridSize*GridSize;privateconstintTransformStride12;[Export]publicMeshDonutMesh{get;set;}null;[Export]publicfloatSpacing2.5f;[Export]publicfloatRotateSpeedMin5.0f;[Export]publicfloatRotateSpeedMax8.0f;privateMultiMesh_multiMesh;privateVector3[]_rotationAxesArray.EmptyVector3();privatefloat[]_rotationSpeedsArray.Emptyfloat();privatefloat[]_rotationAnglesArray.Emptyfloat();privatefloat[]_transformBufferArray.Emptyfloat();publicoverridevoid_Ready(){if(DonutMeshnull){GD.PushWarning(请在检视面板给 DonutMesh 赋值 Mesh 资源);SetProcess(false);return;}_rotationAxesnewVector3[InstanceCount];_rotationSpeedsnewfloat[InstanceCount];_rotationAnglesnewfloat[InstanceCount];_transformBuffernewfloat[InstanceCount*TransformStride];// 格式必须在设置 InstanceCount分配实例缓冲区之前指定。_multiMeshnewMultiMesh{TransformFormatMultiMesh.TransformFormatEnum.Transform3D,MeshDonutMesh,InstanceCountInstanceCount};// 预设能包围所有旋转姿态的边界避免逐帧重新计算 25 万个实例的 AABB。AabbmeshBoundsDonutMesh.GetAabb();floatradiusmeshBounds.Position.Abs().Max(meshBounds.End.Abs()).Length();floatgridEnd(GridSize-1)*Spacing-250.0f;floatminMathf.Min(-250.0f,gridEnd)-radius;floatmaxMathf.Max(-250.0f,gridEnd)radius;_multiMesh.CustomAabbnewAabb(newVector3(min,-radius,min),newVector3(max-min,radius*2.0f,max-min));for(intx0;xGridSize;x){for(intz0;zGridSize;z){intindexx*GridSizez;intoffsetindex*TransformStride;// 每个 3D 变换占 12 个 float按 3 行旋转矩阵 平移存储。WriteBasis(offset,Basis.Identity);_transformBuffer[offset3]x*Spacing-250.0f;_transformBuffer[offset7]0.0f;_transformBuffer[offset11]z*Spacing-250.0f;// 随机三维单位旋转轴Vector3randomAxisnewVector3(GD.Randf()*2.0f-1.0f,GD.Randf()*2.0f-1.0f,GD.Randf()*2.0f-1.0f);_rotationAxes[index]randomAxis.IsZeroApprox()?Vector3.Up:randomAxis.Normalized();_rotationSpeeds[index]Mathf.Lerp(RotateSpeedMin,RotateSpeedMax,GD.Randf());}}_multiMesh.Buffer_transformBuffer;AddChild(newMultiMeshInstance3D{NameDonutMultiMesh,Multimesh_multiMesh});GD.Print($生成 MultiMesh 实例数量{InstanceCount}使用 1 个 MultiMeshInstance3D);}publicoverridevoid_Process(doubledelta){if(_multiMeshnull)return;ulongt1Time.GetTicksMsec();floatdt(float)delta;for(inti0;iInstanceCount;i){// 从累计角度重建旋转避免持续乘矩阵产生缩放/正交误差。_rotationAngles[i]Mathf.PosMod(_rotationAngles[i]_rotationSpeeds[i]*dt,Mathf.Tau);WriteBasis(i*TransformStride,newBasis(_rotationAxes[i],_rotationAngles[i]));}// 每帧一次批量提交不再逐个调用 Rotate 或 SetInstanceTransform。_multiMesh.Buffer_transformBuffer;ulongt2Time.GetTicksMsec();GD.Print(t2-t1);}privatevoidWriteBasis(intoffset,Basisbasis){// Basis.X/Y/Z 是列向量MultiMesh 缓冲区需要按行写入。_transformBuffer[offset]basis.X.X;_transformBuffer[offset1]basis.Y.X;_transformBuffer[offset2]basis.Z.X;_transformBuffer[offset4]basis.X.Y;_transformBuffer[offset5]basis.Y.Y;_transformBuffer[offset6]basis.Z.Y;_transformBuffer[offset8]basis.X.Z;_transformBuffer[offset9]basis.Y.Z;_transformBuffer[offset10]basis.Z.Z;}}经过运行发现每一帧率耗时高达100毫秒左右。从视觉上对比会发现差距非常大。帧率对比采用Mono实体同时旋转25万个Mesh网格FPS低到可怜的9帧/秒采用ECS框架同样的网格数量同时旋转高达79帧/秒ECS框架适合超多的实体的场景。

相关新闻

VLAN+链路聚合+静态路由:企业级网络综合组网实战指南

VLAN+链路聚合+静态路由:企业级网络综合组网实战指南

1. 从一个真实组网需求说起:为什么要把VLAN、链路聚合和静态路由放在一起用很多刚接触企业级网络的朋友会有个疑问:交换机上划VLAN我懂,链路聚合我也懂,路由器上写静态路由我也懂,但把这三样东西凑到一张拓扑里&#x…

2026/10/18 7:41:06 阅读更多 →
核心网络协议梳理与排障实战:HTTP、TCP/IP、DNS、SSH、FTP

核心网络协议梳理与排障实战:HTTP、TCP/IP、DNS、SSH、FTP

网络协议这东西,平时不接触的人觉得它高高在上,接触了又觉得知识点碎得跟散沙一样。但其实,不管你是做开发的、搞运维的,还是偶尔需要自己折腾一下服务器、翻翻路由器配置的“兴趣型工程师”,只要能把HTTP、IP、SSH、F…

2026/10/18 7:41:06 阅读更多 →
artcraft:轻量级创意工具集的设计与实现

artcraft:轻量级创意工具集的设计与实现

1. 项目缘起与整体设计思路1.1 为什么会有 artcraft 这个想法做创意工具这些年,我最大的感受就是:大部分所谓的“创作辅助工具”,其实都在帮倒忙。你要么被一堆参数面板淹没,要么被强制绑定某个平台、某种格式,最后做出…

2026/10/18 7:41:06 阅读更多 →

最新新闻

《华为团队工作法》华为人才管理和薪酬激励:构建四位一体点燃员工热情的激励体系

《华为团队工作法》华为人才管理和薪酬激励:构建四位一体点燃员工热情的激励体系

本 115 页 PPT 适配企业人才管理、薪酬激励、干部管理类咨询方案与 HR 培训课件编制。基于华为人才管理体系核心实践,系统拆解人才选配、评估、干部任用、人才成长、文化锻造、薪酬激励、全面激励、健康成长八大模块。涵盖 STAR 行为面试、人才搭配四宫格、绩效能力…

2026/10/18 14:57:52 阅读更多 →
STM32智能家居监测系统实战:从传感器选型到MQTT上云完整代码解析

STM32智能家居监测系统实战:从传感器选型到MQTT上云完整代码解析

简介:基于STM32微控制器的智能家居监测系统代码包,面向嵌入式与物联网开发者,解决室内温度、湿度、光照、PM2.5和甲醛等环境参数的实时采集与远程查看问题。整体设计涵盖多传感器接入、ESP8266 WiFi上云、QT上位机可视化以及手动/自动双模式控…

2026/10/18 14:57:52 阅读更多 →
具身智能多维协同优化研究(16):TVA-VLA-World-FRA系统集成与测试方法

具身智能多维协同优化研究(16):TVA-VLA-World-FRA系统集成与测试方法

前沿技术探索:FRA核心定义与设计理念FRA(Factorized Robotic Agent, FRA,亦称:因式分解机器人智能体)是一套因式化数实融合一体化新型智能系统,核心设计理念是全链路系统解耦,将机器人作业的感知…

2026/10/18 14:57:52 阅读更多 →
Amlogic T982/T968 开发指南:选型、编译、烧录与调试避坑

Amlogic T982/T968 开发指南:选型、编译、烧录与调试避坑

简介:Amlogic T982/T968技术开发文档是一份面向技术支持工程师和软件开发工程师的官方技术手册,聚焦基于BDS Android R SDK的芯片方案开发,适合需要完成Android系统定制、底层调试及产线烧录的嵌入式开发者。内容覆盖SDK代码获取与版本编译、…

2026/10/18 14:57:52 阅读更多 →
专科生论文写作难?用AI学术写作工具从选题到降重全流程拆解

专科生论文写作难?用AI学术写作工具从选题到降重全流程拆解

专科生写论文,真的是一道跨不过去的坎。选题没方向,框架搭不起来,语言写得像聊天,查重一改就废。我见过太多同学在宿舍对着电脑熬到凌晨,导师一句“重改”就打回原点。如果你正卡在这个状态里,那么这篇关于…

2026/10/18 14:57:52 阅读更多 →
Oracle数据库时区版本调整实战:DBMS_DST脚本集与DST补丁避坑指南

Oracle数据库时区版本调整实战:DBMS_DST脚本集与DST补丁避坑指南

简介:这份资源是面向Oracle数据库管理员与运维工程师的时区版本调整脚本包,用于将Oracle数据库的时区版本升级至最新,通常需配合官方时区补丁一起使用,适合需要处理时区数据、排查时区相关报错的DBA参考。压缩包内共4个SQL脚本文件…

2026/10/18 14:56:52 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →