运行时文件加载和保存

参见

更多关于游戏进度的保存和读取的信息见 保存游戏

有时,当你希望玩家能够在项目中加载用户生成的内容时,:ref:exporting packs, patches, and mods <doc_exporting_pcks> 并不理想。它要求用户通过Godot编辑器生成PCK或ZIP文件,其中包含Godot导入的资源。

运行时文件加载和保存的示例用例包括:

  • 加载为游戏设计的纹理包。

  • 加载用户提供的音轨,在游戏内的电台中播放。

  • 加载自定义关卡和 3D 模型,可以使用能够导出 glTF 的任意 3D DCC 设计(包括 Godot 在运行时保存的 glTF 场景)。

  • 为菜单和 HUD 使用用户提供的字体。

  • Saving/loading 一种文件格式,该文件格式可以包含多个文件,但仍然可以被其他应用程序轻松读取(ZIP)。

  • Loading 由另一个游戏或程序创建的文件,甚至是来自另一个非Godot游戏的游戏数据文件。

运行时文件加载可以和 HTTP 请求结合起来,直接加载互联网上的资源。

警告

请勿用这种运行时加载的方法来加载属于项目本身的资源,这种做法的效率较低,无法利用 Godot 的资源处理功能(例如翻译重定向)。详见 导入流程

参见

You can see how saving and loading works in action using the Run-time File Saving and Loading (Serialization) demo project.

纯文本文件和二进制文件

Godot 的 FileAccess 类提供了读写文件系统中文件的方法:

  1. func save_file(content):
  2. var file = FileAccess.open("/path/to/file.txt", FileAccess.WRITE)
  3. file.store_string(content)
  4. func load_file():
  5. var file = FileAccess.open("/path/to/file.txt", FileAccess.READ)
  6. var content = file.get_as_text()
  7. return content

为了处理自定义二进制格式(例如加载 Godot 不支持的文件格式),class_FileAccess`提供了几种读写整数、浮点值、字符串等数据类型的方法。这些 FileAccess 方法的名称以 ``get_` 和 store_ 开头。

If you need more control over reading binary files or need to read binary streams that are not part of a file, PackedByteArray provides several helper methods to decode/encode series of bytes to integers, floats, strings and more. These PackedByteArray methods have names that start with decode_ and encode_. See also 二进制序列化 API.

图像

Image’s Image.load_from_file static method handles everything, from format detection based on file extension to reading the file from disk.

If you need error handling or more control (such as changing the scale an SVG is loaded at), use one of the following methods depending on the file format:

Godot 还可以在运行时使用以下方法保存几种图像格式:

那些有着 to_buffer 前缀的方法将图片保存至 PackedByteArray 中,而不是文件系统。这对于通过网络发送图像或将图像发送到 ZIP 压缩包 中非常有用,而无需将其写入文件系统。它可以通过降低 I/O 利用率来提高性能。

备注

如果在3D曲面上显示加载的图像,请确保调用:ref:image.generate_mipmaps<class_image_method_generate_mip maps> ,以便在远处观察时纹理看起来不会有颗粒感。在2D中,当遵循以下说明时,这也很有用:ref:reducing aliasing when downsampling <doc_multiple_resolutions_reducing_aliasing_on_downsampling> 。

加载图像并将其显示在:ref:class_TextureRect 节点中的示例(需要转换为:ref:class_ImageTexture):

  1. # Load an image of any format supported by Godot from the filesystem.
  2. var image = Image.load_from_file(path)
  3. # Optionally, generate mipmaps if displaying the texture on a 3D surface
  4. # so that the texture doesn't look grainy when viewed at a distance.
  5. #image.generate_mipmaps()
  6. $TextureRect.texture = ImageTexture.create_from_image(image)
  7. # Save the loaded Image to a PNG image.
  8. image.save_png("/path/to/file.png")
  9. # Save the converted ImageTexture to a PNG image.
  10. $TextureRect.texture.get_image().save_png("/path/to/file.png")

音视频文件

Godot支持在运行时加载Ogg Vorbis音频。请注意,并非*all* 扩展名为 .ogg 的文件都可以是ogg-Vorbis文件。有些可能是Ogg Theora视频,或者在Ogg容器中包含Opus音频。这些文件在Godot中将 not 作为音频文件正确加载。

通过 AudioStreamPlayer 节点加载 Ogg Vorbis 音频文件的示例:

  1. $AudioStreamPlayer.stream = AudioStreamOggVorbis.load_from_file(path)

通过 VideoStreamPlayer 节点加载 Ogg Theora 视频文件的示例:

  1. var video_stream_theora = VideoStreamTheora.new()
  2. # File extension is ignored, so it is possible to load Ogg Theora videos
  3. # that have an `.ogg` extension this way.
  4. video_stream_theora.file = "/path/to/file.ogv"
  5. $VideoStreamPlayer.stream = video_stream_theora
  6. # VideoStreamPlayer's Autoplay property won't work if the stream is empty
  7. # before this property is set, so call `play()` after setting `stream`.
  8. $VideoStreamPlayer.play()

备注

Godot还不支持MP3或WAV文件的运行时加载。在实现之前,使用脚本实现运行时WAV加载是可行的,因为:ref:class_AudioStreamWAV 的`data`属性风险脚本。

仍然可以使用: ref:AudioStreamWAV.save_to_wav <class_AudioStreamWAV_method_save_to_wav> ,这对于按程序生成的音频或麦克风录音非常有用。

3D 场景

Godot在编辑器和导出项目中都对glTF 2.0提供了一流的支持。同时使用:ref:class_gltfdocument 和ref:class_gltfstate ,Godot可以以文本 (.gltf) 和二进制 (.glb)格式加载和保存导出项目中的glTF文件。二进制格式应该是首选,因为它写得更快、更小,但文本格式更容易调试。

加载glTF场景并将其根节点附加到场景的示例:

  1. # Load an existing glTF scene.
  2. # GLTFState is used by GLTFDocument to store the loaded scene's state.
  3. # GLTFDocument is the class that handles actually loading glTF data into a Godot node tree,
  4. # which means it supports glTF features such as lights and cameras.
  5. var gltf_document_load = GLTFDocument.new()
  6. var gltf_state_load = GLTFState.new()
  7. var error = gltf_document_load.append_from_file("/path/to/file.gltf", gltf_state_load)
  8. if error == OK:
  9. var gltf_scene_root_node = gltf_document_load.generate_scene(gltf_state_load)
  10. add_child(gltf_scene_root_node)
  11. else:
  12. show_error("Couldn't load glTF scene (error code: %s)." % error_string(error))
  13. # Save a new glTF scene.
  14. var gltf_document_save := GLTFDocument.new()
  15. var gltf_state_save := GLTFState.new()
  16. gltf_document_save.append_from_scene(gltf_scene_root_node, gltf_state_save)
  17. # The file extension in the output `path` (`.gltf` or `.glb`) determines
  18. # whether the output uses text or binary format.
  19. # `GLTFDocument.generate_buffer()` is also available for saving to memory.
  20. gltf_document_save.write_to_filesystem(gltf_state_save, path)

备注

加载glTF场景时,必须设置*基本路径*,以便可以正确加载纹理等外部资源。从文件加载时,基本路径会自动设置为包含该文件的文件夹。从缓冲区加载时,必须手动设置此基本路径,因为Godot无法推断此路径。

若要设置基本路径,请在你的GLTFState实例上设置:ref:GLTFState.base_path <class_GLTFState_property_base_path> ,然后*调用* :ref:` GLTFDocument.append_from_buffer<class_GLTCDocument_method_append_from _buffer>` 或 GLTFDocument.append_from_file

字体

FontFile.load_dynamic_font 支持以下字体文件格式:TTF、OTF、WOFF、WOFF2、PFB、PFM

另一方面,FontFile.load_bitmap_font 支持`BMFont<https://www.angelcode.com/products/bmfont/>`__ format (.fnt or .font)。

此外,可以使用Godot对 系统字体 的支持加载系统上安装的任何字体。

根据文件扩展名自动加载字体文件,然后将其作为主题覆盖添加到 Label 节点的示例:

  1. var path = "/path/to/font.ttf"
  2. var path_lower = path.to_lower()
  3. var font_file = FontFile.new()
  4. if (
  5. path_lower.ends_with(".ttf")
  6. or path_lower.ends_with(".otf")
  7. or path_lower.ends_with(".woff")
  8. or path_lower.ends_with(".woff2")
  9. or path_lower.ends_with(".pfb")
  10. or path_lower.ends_with(".pfm")
  11. ):
  12. font_file.load_dynamic_font(path)
  13. elif path_lower.ends_with(".fnt") or path_lower.ends_with(".font"):
  14. font_file.load_bitmap_font(path)
  15. else:
  16. push_error("Invalid font file format.")
  17. if not font_file.data.is_empty():
  18. # If font was loaded successfully, add it as a theme override.
  19. $Label.add_theme_font_override("font", font_file)

ZIP 压缩包

Godot支持使用 ZIPReaderZIPPacker 类读取和写入ZIP档案。这支持任何ZIP文件,包括Godot的 “Export PCK/ZIP”功能生成的文件(尽管这些文件将包含导入的Godot资源,而不是原始项目文件)。

备注

使用 ProjectSettings.load_resource_pack 将Godot导出的PCK或ZIP文件加载为 additional data packs。DLC更喜欢这种方法,因为它可以无缝地与其他数据包(虚拟文件系统)交互。

这种ZIP档案支持可以与运行时图像、3D场景和音频加载相结合,提供无缝的改装体验,而无需用户通过Godot编辑器生成PCK/ZIP文件。

示例列出 ItemList 节点中ZIP存档中的文件,然后将从中读取的内容写入新的ZIP存档(本质上是复制存档):

  1. # Load an existing ZIP archive.
  2. var zip_reader = ZIPReader.new()
  3. zip_reader.open(path)
  4. var files = zip_reader.get_files()
  5. # The list of files isn't sorted by default. Sort it for more consistent processing.
  6. files.sort()
  7. for file in files:
  8. $ItemList.add_item(file, null)
  9. # Make folders disabled in the list.
  10. $ItemList.set_item_disabled(-1, file.ends_with("/"))
  11. # Save a new ZIP archive.
  12. var zip_packer = ZIPPacker.new()
  13. var error = zip_packer.open(path)
  14. if error != OK:
  15. push_error("Couldn't open path for saving ZIP archive (error code: %s)." % error_string(error))
  16. return
  17. # Reuse the above ZIPReader instance to read files from an existing ZIP archive.
  18. for file in zip_reader.get_files():
  19. zip_packer.start_file(file)
  20. zip_packer.write_file(zip_reader.read_file(file))
  21. zip_packer.close_file()
  22. zip_packer.close()