2024-11-21-Godot存档

2024-11-21-Godot存档

十一月 21, 2024

存档实现

基本思路

使用 Resource

图片,音频,脚本,都以此格式调用

默认状态下无法保存任何东西

但是可以以此创建新类

创建代码 >> 选择代码继承自 Rersource


创建 class_name SceneData

保存玩家状态,创建二位矢量变量

想以文件形式保存,需要加@export 关键词

希望保存方向 就保存关键词

C# 写法

1
2
3
4
5
6
7
8
using Godot;
using System;

public partial class PlayerData : Resource
{
[Export] public int money;
[Export] public bool IsNovice;
}

保存按钮的设计

通过实例化 SceneData 来进行数据保存

通过@export 关键词设置的变量可以连接到Player的对象,获取Player对象的属性。

通过player.get_child(0)获取第一个子节点

然后就可以访问字节点的内容

然后设置实例化的对象的属性,将对象使用ResourceSaver.save()来保存即可。

save()方法填两个参数,资源对象和路径。

路径可以选择user://

不同的文件后缀名会存在不同的编码

res后缀为二进制格式

tres后缀为可阅读编码格式

Example Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void _on_save(){

playerHero = GetNode<PlayerHero>("PlayerHero");

var playerData = new PlayerData();


playerData.money = playerHero.money;
playerData.IsNovice = playerHero.IsNovice;


ResourceSaver.Save(playerData, "user://PlayerData.res");
GD.Print("存档成功");

}

读取存档

通过 ResourceLoader.load()方法直接读取存档文件即可。

1
var data = ResourceLoader.load() as SceneData

ps: 注意这里使用load返回后需要转为SceneData对象,否则无法访问相关属性

上述为代码为GDScript C#应该有其他的写法

读取后将玩家的属性设置为存档中的内容即可

Example Code:

1
2
3
4
5
6
7
8
9
public void _on_load(){
var data = ResourceLoader.Load("user://PlayerData.res") as PlayerData;

playerHero.IsNovice = data.IsNovice;
GD.Print(data.IsNovice);
GD.Print("读档成功");

_Ready();
}

More Example About PackedScene

SAVE部分

节点的各种属性(大小,位置,状态)都可以打包为 PackedScene

@export var box_array: Array[PackedScene]

通过一个Array来保存所有物体的状态

  • 获取所有物体的方法
    • 使用group分组功能 可以获得同属于此组的节点
    • 属于同一组的物体会被打上同一个标签
    • Node >>> Group 面板设置分组
    • 通过get_tree().get_nodes_in_group("Box")获取全部Box标签的物体

示例代码

1
2
3
4
5
6
7
var boxes = get_tree().get_nodes_in_group("Box")
// 获取全部 Box 标签的文件对象
for box in boxes:
var box_scene = PackedScene.new()
box_scene.pack(box)
data.box_array.append(box_scene) // 也就是把每个box box_scene.pack进去后就直接添加给 data.box_array就可以了

LOAD部分

先把当前箱子节点删了,然后通过存档来设置和创建节点。

  • 通过get_tree().get_nodes_in_group("Box")获取全部Box标签的物体
  • 然后将其循环遍历所有物体
  • 使用 box.queue_free() 删除当前存在的箱子节点
  • 同时循环所有的存档中的box 并 使用box.instantiate()将其转换为节点
  • 使用get_tree().current_scene.add_child(box_node) 将其加入到场景树中

加载碰撞体

勾选Freeze属性让其无法参与物理计算

设置 box_node.freeze = ture

1
2
3
4
5
6
7
8
9
10
11
12
var data = ResourceLoader.load("路径") as SceneData
player.global_position = data.player_posision
player.get_child(0).flip_h = data.is_facing_left
for box in get_tree().get_nodes_in_group("分组名"):
box.queue_free()
for box in data.box_array:
var box_node = box.instantiate()
get_tree().current_scene.add_child(box_node)
box_node.feeeze = true // 冻结
await get_tree().create_time(0.1).timeout // 等待
for box in get_tree().get_nodes_in_group("分组名"):
box_node.feeeze = false // 解冻

知识点来源于:

【【Godot干货】优雅地保存任何数据!基于Resource类的存档系统】