ETH官方钱包

前往
大廳
主題

godot存檔讀檔

月月鴞 | 2023-06-24 12:03:50 | 巴幣 0 | 人氣 457

同步發表於blog

紀錄一下godot4中存檔和讀檔的方式,使用的程式碼都來自於參考資料。

參考資料  


其中在官方範例中loading/serialization為存讀檔案的示範,展示了JSON和ConfigFile的方式。  
而別人寫的範例中多示範了兩種方式,readme中有另外備註了不同類型的比較,其中還有備註了PackedScene(保存場景)的方式時間最久、而且檔案與更新的遊戲可能不相容。

此表格來自範例1備註
儲存與讀取類型
Text
Binary
Standard format
Stores all data types
JSON
?
?
ConfigFile
? ? ?
Custom resource
? ? ?
PackedScene
? ? ?

下方範例json的部分抓官方文件範例加上簡單註解,其餘則是範例中簡單截出的語法。


#### json
文件中推薦建立虛列化格式來方便處理存檔,在這邊處理存檔資料。  
```gdscript
func save():
    var save_dict = {
        "filename" : get_scene_file_path(),
        "parent" : get_parent().get_path(),
        "pos_x" : position.x, # Vector2 is not supported by JSON
        "pos_y" : position.y,
        "attack" : attack,
        "defense" : defense,
        "current_health" : current_health,
        "max_health" : max_health,
        "damage" : damage,
        "regen" : regen,
        "experience" : experience,
        "tnl" : tnl,
        "level" : level,
        "attack_growth" : attack_growth,
        "defense_growth" : defense_growth,
        "health_growth" : health_growth,
        "is_alive" : is_alive,
        "last_attack" : last_attack
    }
    return save_dict
```
存檔,用FileAccess開啟/建立檔案後開始抓資料寫入(store_line)。  
```gdscript
func save_game():
    var save_game = FileAccess.open("user://savegame.save", FileAccess.WRITE)
    var save_nodes = get_tree().get_nodes_in_group("Persist")
    for node in save_nodes:
        # Check the node is an instanced scene so it can be instanced again during load.
        if node.scene_file_path.is_empty():
            print("persistent node '%s' is not an instanced scene, skipped" % node.name)
            continue

        # #####重點在這區 檢查設定的格式是否存在並使用
        # Check the node has a save function.
        if !node.has_method("save"):
            print("persistent node '%s' is missing a save() function, skipped" % node.name)
            continue

        # Call the node's save function.
        var node_data = node.call("save")

        # JSON provides a static method to serialized JSON string.
        var json_string = JSON.stringify(node_data)

        # Store the save dictionary as a new line in the save file.
        save_game.store_line(json_string)
```
讀檔,先確認檔案是否存在,存在的話讀取並塞回遊戲中。  
```gdscript
func load_game():
    if not FileAccess.file_exists("user://savegame.save"):
        return # Error! We don't have a save to load.

    # We need to revert the game state so we're not cloning objects
    # during loading. This will vary wildly depending on the needs of a
    # project, so take care with this step.
    # For our example, we will accomplish this by deleting saveable objects.
    var save_nodes = get_tree().get_nodes_in_group("Persist")
    for i in save_nodes:
        i.queue_free()

    # Load the file line by line and process that dictionary to restore
    # the object it represents.
    var save_game = FileAccess.open("user://savegame.save", FileAccess.READ)
    while save_game.get_position() < save_game.get_length():
        var json_string = save_game.get_line()

        # Creates the helper class to interact with JSON
        var json = JSON.new()

        # Check if there is any error while parsing the JSON string, skip in case of failure
        var parse_result = json.parse(json_string)
        if not parse_result == OK:
            print("JSON Parse Error: ", json.get_error_message(), " in ", json_string, " at line ", json.get_error_line())
            continue

        # Get the data from the JSON object
        var node_data = json.get_data()

        # Firstly, we need to create the object and add it to the tree and set its position.
        var new_object = load(node_data["filename"]).instantiate()
        get_node(node_data["parent"]).add_child(new_object)
        new_object.position = Vector2(node_data["pos_x"], node_data["pos_y"])

        # Now we set the remaining variables.
        for i in node_data.keys():
            if i == "filename" or i == "parent" or i == "pos_x" or i == "pos_y":
                continue
            new_object.set(i, node_data[i])
```

#### config file
存檔  
```gdscript
    var config_file := ConfigFile.new()
    for actor in get_tree().get_nodes_in_group("actors"):
        config_file.set_value("actors", actor.name, actor.serialize_config_file())
    config_file.save(SAVE_PATH_CONFIG_FILE)
```

讀檔
```gdscript
    if not FileAccess.file_exists(SAVE_PATH_CONFIG_FILE):
        $UILayer/UI/LoadConfigFile.disabled = true
        return
    clear_actors()
    var config_file := ConfigFile.new()
    config_file.load(SAVE_PATH_CONFIG_FILE)
    for key in config_file.get_section_keys("actors"):
        var actor := Actor.instantiate()
        actor.init_config_file(config_file.get_value("actors", key))
        $Actors.add_child(actor)
        actor.owner = $Actors
```

#### custom resource
存檔  
```gdscript
    var actor_data: Array[ActorData] = []
    for actor in get_tree().get_nodes_in_group("actors"):
        actor_data.append(actor.serialize_custom_resource())
    var save_resource := SaveResource.new(actor_data)
    ResourceSaver.save(save_resource, SAVE_PATH_CUSTOM_RESOURCE)
```

讀檔
```gdscript
    if not FileAccess.file_exists(SAVE_PATH_CUSTOM_RESOURCE):
        $UILayer/UI/LoadCustomResource.disabled = true
        return
    clear_actors()
    var save_resource := ResourceLoader.load(SAVE_PATH_CUSTOM_RESOURCE, "SaveResource")
    for actor_data in save_resource.actor_data:
        var actor := Actor.instantiate()
        actor.init_custom_resource(actor_data)
        $Actors.add_child(actor)
        actor.owner = $Actors
```

#### packed scene
存檔  
```gdscript
    var scene := PackedScene.new()
    scene.pack($Actors)
    ResourceSaver.save(scene, SAVE_PATH_PACKED_SCENE)
```

讀檔
```gdscript
    if not FileAccess.file_exists(SAVE_PATH_PACKED_SCENE):
        $UILayer/UI/LoadPackedScene.disabled = true
        return
    $Actors.free()
    var scene := ResourceLoader.load(SAVE_PATH_PACKED_SCENE, "PackedScene")
    add_child(scene.instantiate())
```

#### 刪除檔案
```gdscript
DirAccess.remove_absolute("檔案路徑")
```

創作回應

更多創作