Godot 游戏的加载与保存

【Godot 保存和加载游戏-01:简单方法介绍】 https://www.bilibili.com/video/BV19r421H7kM/?share_source=copy_web&vd_source=210b0b0bede87c353444923de149ef38

以下是该B站视频的笔记。


1-简单方法
    节点排序
        Container
            SaveButton
            LoadButton
        SaverLoader
            挂载脚本,连接按钮
    SaverLoader.gd
        func save_game():
            var file=FileAccess.open("res://savegame.data",FileAccess.WRITE)
            file.store_var(player.global_position)
            file.store_var(player.health)
            file.close()
        func load_game():
            var file=FileAccess.open("res://savegame.data",FileAccess.READ)
            player.global_position=file.get_var()
            player.health=file.get_var() #写入与读取的顺序要一致
            file.close()
        #认识Vector2,人类不可读
2-格式选择JSON    int、float、String、Array、Dictionary
    SaverLoader.gd
        func save_game():
            var file=FileAccess.open("user://savegame.json",FileAccess.WRITE)
            
            var saved_data={}
            saved_data['player_global_position']=player.global_position
            saved_data['player_health']=player.health

            var json=JSON.stringify(saved_data)
            file.store_string(json)
            file.close()
        func load_game():
            var file=FileAccess.open("user://savegame.json",FileAccess.READ)
            var json=file.get_as_text()
            var saved_data=JSON.parse_string(json)

            player.health=saved_data['player_health']
            player.global_position=saved_data['player_global_position']
            file.close()
        #JSON不认识Vector2,会把position变成字符串,所以须把它拆分成xy
        #人类可读
3-格式选择字典
    在简单方法中,把字典写入.data文件中
4-格式选择自定义资源
    saved_game.gd
        class_name SavedGame
        extends Resource
        @export var player_position:Vector2
        @export var player_health:float
    SaverLoader.gd
        func save_game():
            var saved_game:SavedGame=SavedGame.new()
            saved_game.player_position=player.global_position
            saved_game.player_health=player.health
            ResourceSaver.save(saved_game,'user://save_game.tres')
        func load_game():
            var saved_game:SavedGame=load('user://save_game.tres') as SavedGame
            player.global_position=saved_game.player_position
            player.health=saved_game.player_health
5-动态游戏元素的处理
    saved_game.gd
        @export var fish_positions:Array[Vector2]=[]
    SaverLoader.gd
        保存
            for fish in get_tree().get_nodes_in_group('fish'):
                saved_game.fish_positions.append(fish.global_position)
        加载
            #先清除当前的鱼
            for fish in get_tree().get_nodes_in_group('fish'):
                fish.get_parent.remove_child(fish)
                fish.queue_free()
                #若直接用queue,则节点会在树里待到最后一帧才山删除,可能有副作用
            #再读取
            var fish_scene=preload('')
            for position in saved_game.fish_positions:
                var new_fish=fish_scene.instantiate()
                world_root.add_child(new_fish)
                new_fish.global_position=position
6-通用方法的构建
    保存加载器不用知道节点内部信息
        将保存分为两个阶段,收集和保存
        加载同上,鱼、水雷要清除,而入口等静态物不要
    saved_data.gd
        class_name SavedData
        extends Resource

        @export var position:Vector2
        @export var scene_path:String
    saved_game.gd
        class_name SavedGame
        extends Resource

        @export var player_position:Vector2
        @export var player_health:float
        @export var saved_data:Array[SavedData]=[]
    fish.gd
        func on_save_game(saved_data:Array[SavedData]):
            #让节点决定自己是否被保存
            if _dying:
                return
            var my_data=SavedData.new()
            my_data.position=global_position
            my_data.scene_path=scene_file_path
            saved_data.append(my_data)
        func on_before_load_game():
            get_parent().remove_child(self)
            queue_free()
        func on_load_game(saved_data:SavedData):
            global_position=saved_data.position
    SaverLoader.gd
        func save_game():
            var saved_game:SavedGame=SavedGame.new()

            saved_game.player_position=player.global_position
            saved_game.player_health=player.health

            var saved_data:Array[SavedData]=[] #game_events分组管理
            get_tree().call_group('game_events','on_save_game',saved_data)
            saved_game.saved_data=saved_data

            ResourceSaver.save(saved_game,'user://save_game.tres')
        func load_game():
            var saved_game:SavedGame=load('user://save_game.tres') as SavedGame
            
            player.global_position=saved_game.player_position
            player.health=saved_game.player_health

            get_tree().call_group('game_events','on_before_load_game')

            for item in saved_game.saved_data:
                var scene=load(item.scene_path) as PackedScene
                var restored_node=scene.instantiate()
                world_root.add_child(restored_node)

                if restored_node.has_method('on_load_game'):
                    restored_node.on_load_game(item)
7-扩展通用方法
    新建脚本
        class_name SavedThisData
        extends SavedData
        增加属性
8-存档兼容性
    机制更新后,加载旧存档可能报错
        比如鱼被攻击后变小,二次则死。
        新建的SavedFishData,旧版本的SavedGame没有它
        报错 var my_data:SavedFishData=saved_data as SavedFishData
    纠正
        func on_load_game(saved_data:SavedData):
            global_position=saved_data.position

            if saved_data is SavedFishData:
                scale=saved_data.scale
            #旧存档不应用新属性
9-存档安全性
    玩家修改血量为一万
        检查血量在合理范围内
    在存档中添加代码,存档被加载时,代码会自动执行,恶意发布植入代码的存档
        插件SafeResourceLoader
            取消选择示例文件夹,项目设置里勾选并重加载项目
        func load_game():
            var saved_game:SavedGame=SafeResourceLoader.load()

            if saved_game==null:
                print('Saved game was unsafe!')
                return
        


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值