Godot 演示项目:Runtime Save/Load —— 绕过资源导入系统的运行时文件加载与保存实战

发布时间:2026/10/3 13:35:32

Godot 演示项目:Runtime Save/Load —— 绕过资源导入系统的运行时文件加载与保存实战 示例工程【免费下载链接】godot-demo-projectsDemonstration and Template Projects项目地址https://gitcode.com/GitHub_Trending/go/godot-demo-projects点击查看免费下载本指南围绕 godot-demo-projects 仓库中的 runtime_save_load 演示项目系统讲解如何在不经过 Godot 资源导入系统Import System的前提下于运行时直接加载与保存图片、音频、3D 场景glTF、ZIP 压缩包、字体与纯文本等各类文件。读完本文你将掌握Image、AudioStreamOggVorbis/MP3/WAV、GLTFDocument/FBXDocument、FontFile、ZIPReader/ZIPPacker与FileAccess等核心类的运行时读写用法并理解其与 PCK 打包、资源导入、游戏存档序列化之间的边界可直接应用到用户生成内容UGC、DLC 扩展包等真实场景。项目概览为什么需要绕过资源导入系统在 Godot 中常规的资源使用方式是把图片、音频、场景等资源导入Import进项目最终随导出打包进 PCK 文件。这种方式适合「开发者预先准备、内容固定」的资源。但当内容来自用户运行时产生如玩家上传的头像、自制的模型、自定义关卡包时不可能在每次导出前重新导入因此需要一套「运行时直接从磁盘读写文件」的方案。runtime_save_load 演示项目 正是展示这一能力的官方示例。它的核心主张体现在项目自述中本项目展示如何在不经过 Godot 资源导入系统的情况下加载和保存各种文件类型。这对于在运行时加载/保存图片、声音、3D 场景和 ZIP 压缩包等用户生成内容非常有用且无需用户通过 Godot 生成 PCK 文件。项目基于 GDScript 编写渲染后端为 CompatibilityOpenGL对应配置可在 project.godot 中看到renderer/rendering_methodgl_compatibility主场景为res://runtime_save_load.tscn并开启了run/low_processor_modetrue以降低闲置时的 CPU 占用。支持的文件类型清单能力文件类型可运行时加载并保存图片JPEG、PNG、WebP、3D 场景glTF 2.0、ZIP 压缩包、纯文本文件可运行时加载仅加载图片TGA、BMP、SVG、3D 场景FBX、音频Ogg Vorbis、MP3、WAV、字体TTF、OTF、WOFF、WOFF2、PFB、PFM、BMFont演示目录下 examples 为每种类型都准备了可直接试用的样例images/下同源的godot_icon共 6 种格式png、jpg、webp、tga、bmp、svgaudio/下的item_spawn有 ogg、mp3、wav 三种编码fonts/提供 TTF/OTF/WOFF2 三种字体3d_scenes/gltf/提供带纹理贴图的塑料椅 glTF 场景misc/下则是example.zip与file.txt。快速上手运行演示项目用 Godot 4.x 打开 loading/runtime_save_load/project.godot项目配置config/featuresPackedStringArray(4.7)需 Godot 4.7 或兼容版本。点击运行主场景 runtime_save_load.tscn 会加载一个文件浏览器 UI。在顶部的FilePath输入框中直接输入文件路径或点击Browse按钮通过文件对话框选择examples/目录中的任一文件。程序会根据文件扩展名自动识别类型并在下方的Result区域显示对应预览图片纹理、音频播放按钮、3D 场景视图、字体字形预览、ZIP 文件列表或纯文本内容。预览成功后点击Export按钮可将当前内容保存为指定格式的新文件。界面结构一个场景承载六种查看器runtime_save_load.tscn 将全部 UI 组织在一个Control根节点下并通过visible切换不同查看器其结构对理解脚本逻辑很有帮助输入区FilePathLineEdit、Browse按钮与FileDialogfile_mode0即打开文件模式。结果区Result/CenterContainerPlainTextViewer滚动容器 Label用于显示纯文本。TextureViewerTextureRect显示图片。AudioPlayer按钮内含AudioStreamPlayervolume_db-10.0与时长信息 Label。SceneViewerSubViewportContainer SubViewport开启 MSAA、scaling_3d_scale2.0 Camera3D 三盏方向光KeyLight/FillLight/BackLight Zoom 滑块HSlidermin_value-100.0、max_value-0.1。FontViewerLabel用预览字体渲染字母、数字与符号表。ZIPViewerHSplitContainer左侧FileListItemList列出压缩包内文件右侧FilePreviewLabel显示选中文件的 UTF-8 文本内容。ErrorLabel加载失败时的错误提示。导出区Export按钮与独立FileDialogaccess2即文件系统访问。场景中所有信号均在 tscn 末尾通过[connection]声明绑定例如text_submitted、file_selected、item_selected、value_changed分别对应脚本中的_on_file_path_text_submitted、_on_file_dialog_file_selected、_on_zip_viewer_item_selected、_on_scene_viewer_zoom_value_changed等回调。核心实现open_file 的分发逻辑整个加载流程集中在 runtime_save_load.gd 的open_file(path)方法中。它将路径转为小写后按扩展名依次匹配图片、音频、3D 场景、字体、ZIP最后以纯文本作为兜底func open_file(path: String) - void: var path_lower : path.to_lower() # 图片分支 if path_lower.ends_with(.jpg) or path_lower.ends_with(.jpeg) \ or path_lower.ends_with(.png) or path_lower.ends_with(.webp) \ or path_lower.ends_with(.svg) or path_lower.ends_with(.tga) \ or path_lower.ends_with(.bmp): # ... # 音频分支 elif path_lower.ends_with(.ogg) or path_lower.ends_with(.mp3) \ or path_lower.ends_with(.wav): # ... # 3D 场景分支 elif path_lower.ends_with(.gltf) or path_lower.ends_with(.glb) \ or path_lower.ends_with(.fbx): # ... # 字体分支 elif path_lower.ends_with(.ttf) or path_lower.ends_with(.otf) \ or path_lower.ends_with(.woff) or path_lower.ends_with(.woff2) \ or path_lower.ends_with(.pfb) or path_lower.ends_with(.pfm) \ or path_lower.ends_with(.fnt) or path_lower.ends_with(.font): # ... # ZIP 分支 elif path_lower.ends_with(.zip): # ... # 兜底按纯文本打开 else: var file_contents : FileAccess.get_file_as_string(path) # ...图片一行代码完成格式探测与加载图片分支是整个演示中代码最简洁的因为它直接调用Image.load_from_file(path)—— 该方法会根据文件扩展名自动探测格式并完成读取同时覆盖 JPEG/PNG/WebP/SVG/TGA/BMP 七种格式var image : Image.load_from_file(path) reset_visibility() export_file_dialog.filters [*.png ; PNG Image, *.jpg, *.jpeg ; JPEG Image, *.webp ; WebP Image] texture_viewer.visible true texture_viewer.texture ImageTexture.create_from_image(image)脚本注释明确指出如果需要错误处理或更细粒度的控制例如控制 SVG 的加载缩放比例应改用Image类的load_*_from_buffer()系列方法与load_svg_from_string()。音频按格式选择对应的 AudioStream 类音频分支依据扩展名分别使用三个静态工厂方法将文件直接构造成可播放的AudioStream资源if path_lower.ends_with(.ogg): audio_stream_player.stream AudioStreamOggVorbis.load_from_file(path) elif path_lower.ends_with(.mp3): audio_stream_player.stream AudioStreamMP3.load_from_file(path) elif path_lower.ends_with(.wav): audio_stream_player.stream AudioStreamWAV.load_from_file(path)加载成功后脚本会显示播放按钮并计算音频时长roundi(stream.get_length())后格式化为MM:SS。需要注意如果数据已在内存中PackedByteArray可改用AudioStreamOggVorbis.load_from_buffer()这类缓冲区方法。3D 场景GLTFDocument 与 FBXDocument 的运行时装配glTF 分支使用GLTFDocumentGLTFState完成「文件 → 节点树」的转换前者负责加载数据后者保存加载状态。成功加载后调用generate_scene(gltf_state)生成根节点并挂到 SubViewport 下的场景查看器中var gltf_document : GLTFDocument.new() var gltf_state : GLTFState.new() var error : gltf_document.append_from_file(path, gltf_state) if error OK: scene_viewer_root_node gltf_document.generate_scene(gltf_state) reset_visibility() scene_viewer.add_child(scene_viewer_root_node) export_file_dialog.filters [*.gltf ; glTF Text Scene, *.glb ; glTF Binary Scene] scene_viewer.visible true else: show_error(Couldn\t load %s as a glTF scene (error code: %s). % [path.get_file(), error_string(error)])FBX 分支的结构与之完全对称只是换用FBXDocument与FBXState。场景查看器中的Zoom滑块通过_on_scene_viewer_zoom_value_changed控制正交相机projection1的size滑块取值范围为负值-100.0 ~ -0.1scene_viewer_camera.size abs(value)数值越小绝对值越大表示放大倍率越高。字体动态字体与位图字体的区分加载字体分支创建FontFile根据扩展名区分两类加载方式.fnt/.fontBMFont 位图字体走load_bitmap_font()其余 TTF/OTF/WOFF/WOFF2/PFB/PFM 走load_dynamic_font()var font_file : FontFile.new() if path_lower.ends_with(.fnt) or path_lower.ends_with(.font): font_file.load_bitmap_font(path) else: font_file.load_dynamic_font(path) if not font_file.data.is_empty(): font_viewer.add_theme_font_override(font, font_file) reset_visibility() font_viewer.visible true export_button.disabled true成功加载后通过add_theme_font_override把字体应用到一个 48 号字号的 Label 上直接预览字形。脚本用font_file.data.is_empty()判断加载是否成功失败则进入show_error流程。ZIP 压缩包ZIPReader 的只读浏览ZIP 分支创建ZIPReader打开压缩包后列出内部全部文件并禁用列表中以/结尾的目录项zip_reader.open(path) var files : zip_reader.get_files() files.sort() export_file_dialog.filters [*.zip ; ZIP Archive] reset_visibility() for file in files: zip_viewer_file_list.add_item(file, null) zip_viewer_file_list.set_item_disabled(-1, file.ends_with(/)) zip_viewer.visible true当用户选中列表项时_on_zip_viewer_item_selected用zip_reader.read_file(文件名)取出原始字节再get_string_from_utf8()转为文本预览。值得一提的扩展场景Godot 的「Export PCK/ZIP」功能生成的 ZIP 文件同样可以被读取其中包含的是导入后的 Godot 资源而非原始工程文件而若要作为 DLC 追加数据包无缝集成到虚拟文件系统演示注释推荐改用ProjectSettings.load_resource_pack()。运行时保存Export 按钮背后的写入逻辑_on_export_file_dialog_file_selected(path)根据当前可见的查看器类型决定写入方式纯文本用FileAccess.open(path, FileAccess.WRITE)store_string()写回最后close()。图片从texture_viewer.texture.get_image()取回Image再按目标扩展名调用save_png()、save_jpg()质量常量为JPG_QUALITY 0.9或save_webp()。注释特别说明 WebP 默认无损保存需要有损时可通过Image.save_webp()的可选参数调整。3D 场景用GLTFDocument.append_from_scene(scene_viewer_root_node, gltf_state)把预览中的节点树转回 glTF 状态再write_to_filesystem(gltf_state, path)落盘。输出是文本.gltf还是二进制.glb由目标路径扩展名决定二进制写盘更快、体积更小、更适合内嵌纹理但文本格式更易于调试。ZIP创建ZIPPackeropen(path)后遍历zip_reader.get_files()对每个文件依次start_file()→write_file()→close_file()最后close()。若打开失败会push_error并中止。两处「无法导出」的限制也在代码中明确标注音频中的 Ogg Vorbis 与 MP3 无法在运行时导出为标准格式只有 WAV 源可通过AudioStreamWAV.save_to_wav()保存为 WAV字体同样只能通过ResourceSaver保存为 Godot 专属的.res格式。因此这两个分支下export_button.disabled true。边界与注意事项原文档的脚注部分给出了三条关键边界项目中均有对应实现佐证自定义二进制格式操作自定义二进制格式可以通过FileAccess与PackedByteArray类实现但演示未展示。这意味着文本/压缩包之外的结构化数据读写需要自行封装字节流逻辑。SVG 程序化生成可以先用文本方式程序化生成 SVG 内容再用FileAccess写入带.svg扩展名的文件。仓库中 examples/images/godot_icon.svg 正是可被Image.load_from_file()直接加载的 SVG 样例。FBX 运行时加载的已知问题文档明确提到 Godot 的 issue #96043即运行时 FBX 加载存在已知缺陷。FBX 分支在append_from_file返回非OK时同样会通过show_error展示error_string(error)错误码实际项目中建议优先使用 glTF 作为跨引擎交换格式。与 Serialization 演示的互补关系本演示关注「文件级 I/O」而仓库中的 loading/serialization 演示Saving and Loading / Serialization关注「游戏进度级 I/O」展示如何使用ConfigFile与JSON保存游戏状态。原文档明确给出分工建议前者解决「导出的游戏如何在运行时读取未导入的文件」后者解决「游戏进度如何持久化」两者配合即可覆盖从存档数据到 UGC 资源的完整读写需求。示例资产与许可examples/3d_scenes/gltf/ 下的plastic_monobloc_chair_01_1k.gltf及配套纹理diff/nor/arm 三张 JPG 与一个.bin缓冲文件来自 Poly Haven采用 CC0 1.0 通用许可examples/audio/ 下的音频文件来自 Red Eclipse 项目采用 CC BY-SA 4.0 国际许可examples/fonts/ 内的 Inter 字体遵循 SIL Open Font License 1.1。在自有项目中使用或二次分发这些示例资产时需保留对应的许可声明。赞分享示例工程【免费下载链接】godot-demo-projectsDemonstration and Template Projects项目地址https://gitcode.com/GitHub_Trending/go/godot-demo-projects点击查看免费下载相关推荐Godot 音频输出设备运行时切换实战Audio Device Changer 演示项目源码解析godot-demo-projectsGodot 音频输出设备运行时切换实战Audio Device Changer 演示项目源码解析godot demo projects 本文基于 godo示例工程komorebi 快速保存与加载窗口 Resize 布局尺寸quick-save-resize 与 quick-load-resize 实战指南komorebi 快速保存与加载窗口 Resize 布局尺寸quick save resize 与 quick load resize 实战指南 导读 qui桌面应用CANN Runtime 运行时配置接口实战系统参数与 Device/Stream 资源限制管理CANN Runtime 运行时配置接口实战系统参数与 Device/Stream 资源限制管理 本篇技术指南聚焦 CANN Runtime 的运行时配置接口CANNAscend人工智能性能剖析系统编程上一篇金融数据输入输出Python处理CSV、Excel和数据库的完整教程下一篇如何为深蓝词库转换添加新的输入法格式Source Generator 自动注册的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/3 14:20:34

Copilot通过MCP连接MySQL:配置流程与常见排错指南

要让 Copilot 直接查数据库,听起来像是个挺魔幻的需求,但我花了大概一个晚上的时间,把 VS Code 里的 Copilot 通过 MCP 接上了本机的 MySQL,现在它真的能帮我查表结构、查数据、甚至做简单的统计分析了。整个过程没有想象中复杂&a…

2026/10/3 14:20:34

正则匹配实战:从规则原理到性能避坑指南

正则匹配这个东西,很多人第一反应是“不就是查个字符串吗”,但真到了线上日志排查、数据清洗、接口参数校验的时候,才发现自己写出来的表达式要么匹配不到、要么误杀一片。我过去几年里在项目里被正则坑过无数次,也靠它救过急&…

2026/10/3 14:20:34

PDF转CAD全流程解析:判断图纸类型、选对工具、搞定后处理

干工程这行,最烦的不是自己画图,而是别人递来一份PDF让你“帮忙转成CAD”。尤其设计院、施工单位和加工厂之间流转图纸时,PDF几乎成了默认格式——甲方发过来的是扫描版蓝图,客户甩过来的是一份标着“最终版”的PDF总平图&#xf…

2026/10/3 14:20:34

MySQL运维实战:部署、排障、优化与同步全解析

做后端开发那些年,被 MySQL 的安装、启动、连不上、性能崩塌轮流折腾过的次数,说实话比工作年限还多。如今再回头看,管理 MySQL 的本质早就不是敲几条命令那么简单——你要能把一个新库从 Windows 本地跑起来,也能在 Linux 裸机或…

2026/10/3 14:20:34

PGA自聚焦原理与MATLAB实现:ISAR相位误差校正实战

简介:在雷达成像领域,ISAR与SAR成像常因目标非合作运动而引入高阶相位误差,导致图像方位向散焦、轮廓模糊甚至出现重影。相位梯度自聚焦(PGA)作为经典的运动补偿算法,无需依赖孤立强散射点,通过…

2026/10/3 14:15:34

异步电机矢量控制Simulink仿真:从零搭建到PI参数调试全攻略

搞交流异步电机的矢量控制仿真,说难也难,说简单也简单。难在转子磁场定向的原理绕来绕去容易把人绕晕,简单在只要把坐标变换、电流环、SVPWM这几块搭明白,Simulink里是可以一步步复现的。这篇文章我按当年自己从零搭模型的实际路径…

2026/10/2 8:16:46

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/10/2 18:20:53

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 10:48:55

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 0:04:31

国内大学生必备的AI写作辅助软件是哪款?

国内高校学生在论文写作过程中,越来越依赖AI辅助工具提升效率,主流方案以本土化全流程工具为核心,结合通用大模型与专业插件,覆盖选题构思、框架搭建、初稿撰写、查重降重、格式调整等关键环节,本文将深入解析当前主流…

2026/10/3 0:04:31

Codex接入Jev模型完整指南:配置方法、本地部署与踩坑排查

最近不少人在讨论 Codex 搭配 Jev 这套玩法,我一开始没太当回事,直到自己把 Jev 接进 Codex跑了几轮编码任务之后,才明白那些说“直接起飞”的人是怎么想的。Codex 作为工具本身已经够能打了,但模型固定、上下文策略固定&#xff…

2026/10/3 0:04:31

GitHub 热门: NVIDIA/Model-Optimizer

👋 Hi,我擅长 AI 大模型应用落地、意识解码与 AI 开发工具链 。 💡 创业路上,用技术换时间,一起把 AI 变成生产力 🚀 >GitHub 热门: NVIDIA/Model-Optimizer 凌晨两点,你刚把跑通了的 Qwen3.…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑