Flutter 真 3D 游戲引擎來了,flame_3d 了解一下

在剛剛結束的 FlutterNFriends 大會上,Flame 展示了它們關于 3D 游戲的支持:flame_3d ,Flame 是一個以組件系統(Flame Component System, FCS)、游戲循環、碰撞檢測和輸入處理為核心的 Flutter 游戲框架,而這個架構的一個關鍵特點就是:純 Dart 和 Flutter 的開發模式,在此之前 flame 在 2D 領域已經開發了不少小游戲。

而本次要聊的 flame_3d 屬于 Flame 生態系統的一個官方擴展包,flame_3d 是在 Flame 已有的 FCS 上進行擴展的支持,比如:

  • 在Flame 2D中,游戲對象通常是 Component 的子類 ,例如 SpriteComponent 用于渲染圖像
  • 在 flame_3d 則是引入了新的三維組件類型,比如 MeshComponent,它們也繼承自 Component 基類,但是在其之上有 Component3D 的相關實現

這種繼承關系主要是為了新的 3D 對象,能夠無縫地融入已有的 Flame 游戲循環和組件管理,例如一個 MeshComponent 可以像 2D 的 SpriteComponent 一樣被添加到 World ,并自動參與到游戲的更新(update)和渲染(render)循環,也能讓原本熟悉 Flame 2D 的開發者更便捷進入到 3D 領域:

而在 flame_3d 里,三維場景的根節點是還是 FlameGame 類,它負責管理整個游戲 ,而所有 3D 對象都通常被添加到一個 World3D 組件:

  • World3D 組件作為一個邏輯容器來組織場景內容
  • CameraComponent3D 它定義了三維世界的投影方式和視點位置

而在內部,flame_3d 會攔截 Flame 的渲染循環,從而利用 Flutter GPU 的低級API來執行三維渲染任務,例如:

將三維網格、材質和燈光信息發送到 GPU 進行著色和光柵化,這個過程發生在 Flutter 的 build 之外,也避免了造成 Flutter UI 層的性能瓶頸的可能。

所以目前而言,flame_3d 十分依賴于 Flutter GPU + Impeller , flutter_gpu 作為 Flutter 3.24 提供的一個實驗性功能包,它為 Dart 語言暴露了 Impeller 渲染引擎的低級接口,它可以通過編寫 Dart 代碼和 GLSL 著色器在 Flutter 中構建和集成自定義渲染器,而無需 Native 平臺代碼,允許開發者直接訪問 GPU 資源和執行自定義著色器。

簡單來說就是,Flutter GPU 是 Impeller 對于 HAL 的一層很輕的包裝,并搭配了關于著色器和管道編排的自動化能力,也通過 Flutter GPU 就可以使用 Dart 直接構建自定義渲染器。

Flutter GPU 和 Impeller 一樣,它的著色器也是使用 impellerc 提前編譯,所以 Flutter GPU 也只支持 Impeller 的平臺上可用。

當然,實際上直接使用 Flutter GPU 十分復雜,比如一個簡單的繪制就需要:

  • 獲取 GPUContext
  • GpuContext.createCommandBuffer 創建一個 CommandBuffer
  • CommandBuffer.createRenderPass 創建一個 RenderPass
  • 使用各種方法設置狀態/管道并綁定資源 RenderPass
  • 附加繪圖命令 RenderPass.draw
  • CommandBuffer 使用 CommandBuffer.submit (異步)提交繪制,所有 RenderPass 會按照其創建順序進行編碼

而在 flame_3d 通過抽象出一系列核心三維組件來簡化開發:

  • MeshComponent: 這是最基本的可渲染三維組件,用于表示三維網格(Mesh),通過屬性可以加載不同類型的網格,例如圓錐體(ConeMesh)和圓柱體(CylinderMesh),甚至支持復雜的模型解析和骨骼動畫
  • LightComponent: 負責在場景中添加光源,影響 3D 物體的著色效果
  • Material: 材質定義了 3D 對象表面的外觀特性,例如顏色和紋理,目前默認提供了一個SpatialMaterial,開發者也可以編寫自定義材質來使用自己的著色器
  • VectorQuaternion: 主要是用于方便進行三維空間的向量運算和旋轉變換

這里需要注意的是,Flutter 目前并不原生支持著色器文件的打包,而為了解決這個問題,flame_3d 提供了一個自定義的 Dart 腳本,開發者可以將他們的頂點著色器(.vert)和片段著色器(.frag)文件存放在一個指定的shaders 目錄下,并確保文件名稱相同,,然后 :

通過運行命令 dart pub run flame_3d:build_shaders 自動編譯并打包著色器,并放置到assets/shaders目錄中提供運行時加載 。

而針對 flame_3d 官方也提供了一些 demo ,例如 collect_the_donut 就是一個非常不錯的例子,它很好的展示了 flame 如何 3D 領域的開發轉變為大家熟悉的 Flutter 面向對象的開發模式

例如在項目里,你可以通過 ModelParser 加載對應的模型資源,對應上面動圖,在這里:

  • rogue 就是我們操作的角色模型
  • floor 是地板模型
  • donut 是甜甜圈模型
  • skeleton 是小兵模型
  • walls 是墻體模型

而在實際使用上也并不復雜,比如對于我們操作的角色,在項目里對應的是 Player 封裝,Player 類是一個繼承自 ModelComponent 的自定義組件,并且通過混入 HasGameReference 獲取對游戲實例的引用,并實現了 KeyboardHandlerTapCallbacks 接口,用于處理鍵盤輸入和點擊事件。

Player 類定義了一些關鍵屬性,例如玩家的動作 _action、武器 _weapon、是否奔跑 _isRunning、死亡計時器 _deathTimer 等,而構造函數中默認將玩家的武器設置為 knife,并通過 _updateWeapon 方法隱藏其他武器節點,僅顯示當前武器。

對于玩家動作,這里通過 action 屬性管理,通過設置動作時啟動計時器 _actionTimer,并調用 stopAnimation 停止當前動畫,這里的動畫對應的是 flame_3d 里的 AnimationState 動畫狀態機

set action(PlayerAction? value) {if (_actionTimer != 0.0) {return;}_action = value;_actionTimer = value?.timer ?? 0.0;stopAnimation();
}

而玩家的視角可以通過 lookAngle 屬性管理,設置時會更新模型的旋轉,lookAt 屬性返回玩家當前視角方向的向量,同時玩家位置通過 _input_handleMovement 方法更新,支持基于鍵盤輸入的移動邏輯:

lookAngle += -_input.x * _rotationSpeed * dt;
final movement = lookAt.scaled(-_input.y * speed * dt);
position.add(movement);

_updateAnimation 方法根據玩家當前狀態(動作、移動、奔跑等)播放對應的動畫,例如攻擊時播放攻擊動畫,移動時播放行走或奔跑動畫,靜止時播放待機動畫:

if (action != null) {playAnimationByIndex(0, resetClock: false);
} else if (isMoving && _isRunning) {playAnimationByName('Running_A', resetClock: false);
}

可以看到,很多底層操作 flame_3d 都幫我們做了隔離,在上層你只需要操作熟悉的對象和 API ,比如將 PlayerWeapon.knife 換成 PlayerWeapon.twoHandedCrossbow

而對于地板,在項目里對應的是Floor 類,它是一個自定義的地板組件,繼承了 flame.Component,用于在游戲場景中生成一個由多個地板段組成的地板網格。

Floor 的會接收一個 Vector2 size 參數,表示地板的寬度和深度,地板的生成邏輯基于網格劃分,網格的單元大小由常量 _floorSegmentSize 定義,起始位置 start 是一個 Vector3,計算方式確保地板網格居中于場景:

網格的生成邏輯是通過嵌套的 for 循環,遍歷地板的寬度和深度,將每個網格單元的位置偏移量計算出來,并創建 _FloorSection 實例,每個實例的 position 屬性設置為計算后的位置,并添加到當前組件中:

final position = start.clone()..x += x * _floorSegmentSize..z += y * _floorSegmentSize;
add(_FloorSection()..position.setFrom(position));

_FloorSection 繼承自 ModelComponent,表示地板的單個網格單元,對應模型是通過 Loader.models.floor 加載,并設置了初始位置偏移量,使地板稍微低于默認高度:

同理,Demo 項目里的Wall 也是繼承自 flame.Component,用于在游戲場景中生成一段由多個墻段組成的墻體:

image-20250903141910222

對于 Wall 的來說主要接收兩個參數:startend,分別表示墻體的起點和終點,然后通過計算 end - start 得到方向向量 direction,并將墻體的初始位置設置為起點加上方向向量的一半長度:

final direction = end - start;
final position = start + direction.scaledTo(_wallSegmentSize / 2);

對于墻段生成邏輯,主要由多個固定大小的墻段組成,每段的大小由常量 _wallSegmentSize 定義,通過 while 循環,逐步減少剩余距離 totalDistance,并在每次迭代中添加一個 _WallSection 實例,每個墻段的旋轉通過 Quaternion.axisAngle 計算,使其與墻體方向對齊:

final rotation = Quaternion.axisAngle(up,atan2(start.z - end.z, start.x - end.x),
);
add(_WallSection(wallIndex: randomInt(0, Loader.models.walls.length),position: position,rotation: rotation,),
);

同樣道理,這里的 _WallSection 也繼承自 ModelComponent,表示墻體的單個段,它的構造函數接收墻段的索引、位置和旋轉,并從 Loader.models.walls 中加載對應的墻體模型:

另外還有光源演示, Demo 里的光源主要體現在幾個隨機移動的黑點,對應項目里的 Wisp 對象,它繼承自 LightComponent,并通過 HasGameRef 混入獲取對游戲實例的引用,它的主要功能是創建一個動態移動的光源,模擬螢火蟲的效果:

對于光源,同樣有一個內部模型對象 _VisualLight ,它同樣繼承自 MeshComponent,用于渲染光源的視覺效果,這里主要使用了一個小型球體網格 SphereMesh,半徑為 0.05,材質為 SpatialMaterial,顏色與光源一致:

最后少不了 Camera,在 Demo 里使用 ThirdPersonCamera 實現了一個自定義的 3D 攝像機組件,它主要是繼承自 CameraComponent3D,并通過 HasGameReference 混入獲取對游戲實例的引用,而它的主要功能是實現第三人稱視角,跟隨玩家角色的移動和方向:

ThirdPersonCamera 里它主要是設置了攝像機的視野角度(fovY)、初始位置(position)、上方向向量(up)以及目標點(target),例如position 設置為 Vector3(-18, 6, -18),表示攝像機初始位于玩家后方偏左上方的位置。

position: Vector3(-18, 6, -18),
up: Vector3(0.8, 1, 0.8),
target: Vector3(0, 0, 0),

update 方法在每幀調用,用于更新攝像機的位置和目標點,首先計算目標偏移量 targetOffset 和目標視角點 targetLookAt,分別基于玩家的位置和視角方向進行偏移:

final targetOffset = player.position + _positionOffset;
final targetLookAt = player.position + player.lookAt;

接著,使用線性插值公式更新攝像機的位置和目標點,使其平滑地跟隨玩家移動和旋轉,插值速度由 _cameraLinearSpeed_cameraRotationSpeed 控制:

position += (targetOffset - position) * _cameraLinearSpeed * dt;
target += (targetLookAt - target) * _cameraRotationSpeed * dt;

另外還有個值得聊的是 HUD,實際上也就是,用于在屏幕右上角顯示當前分數,事實上其實就是使用 flame_3d 里的 TextPaint ,它可以把你需要的文本內容直接選入到屏幕:

await camera.viewport.add(Hud());static final textHuge = TextPaint(style: _style.copyWith(fontSize: 64));class Hud extends Component with HasGameRef<CollectTheDonutGame> {void render(Canvas canvas) {super.render(canvas);Styles.textHuge.render(canvas,game.score.toString().padLeft(2, '0'),Vector2(game.size.x - _margin,_margin,),anchor: Anchor.topRight,);}
}

可以看到,flame_3d 大大簡化了 Flutter GPU 的使用,同時也給了沉寂這么久的 Flutter GPU 一個落地場景,由于需要 Flutter GPU 和 Impeller 支持,目前 flame_3d 只支持 Android、iOS 和 macOS ,同時由于 flame_3d 還是實驗性階段,所以 API 穩定性還沒有保證。

對于 flame 而言,在理想情況下他們甚至希望 flame_3d 的用戶完全不需要知道和理解 Flutter GPU,他們的目標是將 Flutter GPU 抽象為一個方便 3D 開發的 API,這不僅簡化了創建渲染目標、設置顏色和深度紋理以及配置深度模板等操作,還包含支持更高級的 API,例如幾何形狀、紋理/材質渲染以及創建可以使用這些形狀和材質的網格,最終把這一切和 有的 FCS 緊密結合。

另外本次 Flame 現場還在現在不是用 Flutter GPU 制作了一個小 Demo ship_game,通過覆蓋 Raymarching 、 Volumetric Raymarching 、Weight maps 和 Ordered Dithering 來展示了 Flame 原生的能力:

可以看到,在 flame 在加持下,Flutter 在游戲領域的能力確實越來越強,也希望 Flutter GPU 可以早日發布穩定版本,把這個老餅給畫完。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/95736.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/95736.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/95736.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

無需公網IP,電腦隨時與異地飛牛同步互聯保持數據一致性

最近小白有這樣一個煩惱&#xff1a;隨身帶著的電腦每天都在更新內容&#xff0c;于是就會有很多很多的存稿。電腦的空間開始變得不夠用了。各式各樣的圖片、視頻、文稿等內容&#xff0c;如果要整理到飛牛NAS上&#xff0c;好像很麻煩&#xff0c;而且每次都是需要回到家里才能…

數據庫中間件ShardingSphere v5.2.1

數據庫中間件ShardingSphere v5.2.1 文章目錄數據庫中間件ShardingSphere v5.2.1一 概述1 數據庫的瓶頸2 優化的手段3 主從復制4 讀寫分離5 分庫分表5.1 背景5.2 垂直分片5.3 水平分片6 ShardingSphere簡介二 ShardingSphere-JDBC講解1 讀寫分離實現1.1 基于Docker搭建MySQL主從…

[Upscayl圖像增強] Electron主進程命令 | 進程間通信IPC

第三章&#xff1a;Electron主進程命令 歡迎回來&#x1f43b;??? 在第一章&#xff1a;渲染器用戶界面&#xff08;前端&#xff09;中&#xff0c;我們探索了您與之交互的按鈕和菜單。然后在第二章&#xff1a;AI模型中&#xff0c;我們了解了讓您的圖像看起來更棒的&qu…

電競護航小程序成品搭建三角洲行動護航小程序開發俱樂部點單小程序成品游戲派單小程序定制

功能列表&#xff1a;商家入駐 成為管事 平臺公告 客服密鑰 客服管理 發單模板 快捷發單 自定義發單 打手入駐 訂單裁決 即時通訊 &#xff08;接單者員與發單者&#xff09; 打手排行 邀請排行 余額提現技術棧&#xff1a;前端uniapp 后端java

Redis數據庫基礎

1.關系型數據庫和NoSQL數據庫數據庫主要分為兩大類:關系型數據庫與NoSQL數據庫關系型數據庫&#xff0c;是建立在關系模型基礎是的數據庫&#xff0c;其借助集合代數等數學概念和方法來處理數據庫中的數據主流的MySQL&#xff0c;Oracle&#xff0c;MS SQL Server 和DB2都屬于這…

【Java實戰?】Java日志框架實戰:Logback與Log4j2的深度探索

目錄一、日志框架概述1.1 日志的作用1.2 常見日志框架1.3 日志級別二、Logback 框架實戰2.1 Logback 依賴導入2.2 Logback 配置文件2.3 日志輸出格式自定義2.4 Logback 進階配置三、Log4j2 框架實戰3.1 Log4j2 依賴導入3.2 Log4j2 配置文件3.3 Log4j2 與 SLF4J 整合3.4 日志框架…

基于WFOA與BP神經網絡回歸模型的特征選擇方法研究(Python實現)

說明&#xff1a;這是一個機器學習實戰項目&#xff08;附帶數據代碼文檔&#xff09;&#xff0c;如需數據代碼文檔可以直接到文章最后關注獲取 或者私信獲取。 1.項目背景 在大數據分析與智能建模領域&#xff0c;高維數據廣泛存在于金融預測、環境監測和工業過程控制等場景…

??AI生成PPT工具推薦,從此以后再也不用擔心不會做PPT了??

對于很多人老說&#xff0c;做ppt實在太麻煩了&#xff0c;快速制作出專業且美觀的PPT成為眾多人的需求&#xff0c;AI生成PPT工具應運而生&#xff0c;極大地提升了PPT制作的效率。以下為大家推薦多個實用的AI生成PPT工具。 1、AiPPT星級評分&#xff1a;★★★★★ AiPPT是一…

CentOS系統停服,系統遷移Ubuntu LTS

CentOS官方已全面停止維護CentOS Linux項目&#xff0c;公告指出 CentOS 7在2024年6月30日停止技術服務支持&#xff0c;(在此之前 2022年1月1日起CentOS官方已經不再對CentOS 8提供服務支持&#xff09;&#xff0c;詳情見CentOS官方公告。 一、系統遷移評估 用戶需要開始計…

Linux知識回顧總結----文件系統

上章講的是 os 如果管理被打開的文件&#xff0c;那么沒有被打開的文件&#xff08;也就是在磁盤單中的文件&#xff09;使用文件系統進行管理。了解完這一章&#xff0c;我們就可以理解我們如果想要打開一個文件的是如何找到整個文件&#xff0c;然后如何把它加載到內存中的&a…

iOS藍牙使用及深入剖析高頻高負載傳輸丟包解決方案(附源碼)

最近開發了一套iOS原生的藍牙SDK&#xff0c;總結了一些有價值的踩過的坑&#xff0c;分享出來給有需要的同學做個參考。 一、藍牙的使用 iOS有一套封裝好的完善的藍牙API &#xff0c;可以很便捷的實現與藍牙的連接和通信&#xff0c;藍牙通信的大體流程如下&#xff0c;先對基…

Python 正則表達式實戰:用 Match 對象輕松解析拼接數據流

摘要 這篇文章圍繞 Python 的正則表達式 Match 對象&#xff08;特別是 endpos、lastindex、lastgroup 以及 group / groups 等方法/屬性&#xff09;做一個從淺入深、貼近日常開發場景的講解。我們會給出一個真實又常見的使用場景&#xff1a;解析由設備/服務發來的“拼接式”…

基于Pygame的六邊形戰術推演系統深度剖析——從數據結構到3D渲染的完整實現(附完整代碼)

1. 項目概述與技術選型 戰術推演系統是軍事訓練和游戲開發中的重要組成部分,它能夠模擬真實的戰術場景,為用戶提供策略思考的平臺。本文將深入分析一套基于Python Pygame框架開發的城市巷戰戰術推演系統,該系統采用六邊形網格布局,實現了恐怖分子與反恐精英的對抗模擬,具…

支持二次開發的代練App源碼:訂單管理、代練監控、安全護航功能齊全,一站式解決代練護航平臺源碼(PHP+ Uni-app)

一、技術架構&#xff1a;高性能與跨平臺的核心支撐前端框架Uni-app&#xff1a;基于Vue.js的跨平臺框架&#xff0c;支持編譯至微信小程序、H5、iOS/Android App及PC端&#xff0c;代碼復用率超80%&#xff0c;顯著降低開發成本。實時通信&#xff1a;集成WebSocket實現訂單狀…

AI熱點周報(8.31~9.6): Qwen3?Max?Preview上線、GLM-4.5提供一鍵遷移、Gemini for Home,AI風向何在?

名人說&#xff1a;博觀而約取&#xff0c;厚積而薄發。——蘇軾《稼說送張琥》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 目錄一、3分鐘速覽版&#xff1a;一張表看懂本周AI大事二、國內&#xff1a;模型與生態的…

異步操作終止2

您提的這個問題非常棒&#xff0c;說明您思考得非常深入&#xff01;您完全正確&#xff0c;我之前的示例中使用的 return; 會中斷 handleDraw 函數中所有后續的邏輯&#xff0c;這在很多場景下并不是我們想要的。 我們的目標是只中斷畫圖這一個特定的邏輯&#xff0c;而讓函數…

《AI大模型應知應會100篇》第67篇 Web應用與大模型集成開發實踐——1小時打造國產大模型智能客服系統

第67篇&#xff1a;Web應用與大模型集成開發實踐——1小時打造國產大模型智能客服系統 一句話核心價值&#xff1a;無需翻墻&#xff01;用Flask國產大模型API&#xff08;通義/文心一言/訊飛&#xff09;快速構建合規Web問答系統&#xff0c;電商客服人力成本直降70%&#xff…

python系列之綜合項目:智能個人任務管理系統

不為失敗找理由&#xff0c;只為成功找方法。所有的不甘&#xff0c;因為還心存夢想&#xff0c;所以在你放棄之前&#xff0c;好好拼一把&#xff0c;只怕心老&#xff0c;不怕路長。 python系列之文件操作&#xff1a;讓程序擁有"記憶"的超能力&#xff01;一、項目…

鴻蒙UI開發實戰:解決布局錯亂與響應異常

文章目錄鴻蒙UI開發實戰指南&#xff1a;解決ArkUI聲明式布局錯亂、組件不顯示與事件響應異常引言ArkUI聲明式開發的技術優勢開發痛點與本文價值布局錯亂問題常見原因固定像素單位使用不當布局嵌套層級過深Flex布局屬性配置錯誤響應式布局缺失解決方案彈性單位適配&#xff1a;…

B.50.10.09-RPC核心原理與電商應用

RPC核心原理與電商應用實戰 第1章&#xff1a;RPC核心概念與價值 1.1. 什么是 RPC&#xff1f; RPC (Remote Procedure Call)&#xff0c;即遠程過程調用&#xff0c;是一種允許一臺計算機&#xff08;客戶端&#xff09;上的程序&#xff0c;調用另一臺計算機&#xff08;服務…