# GodotDataModelExample **Repository Path**: smalldyy/godot-data-model-example ## Basic Information - **Project Name**: GodotDataModelExample - **Description**: No description available - **Primary Language**: Unknown - **License**: WTFPL - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-02-07 - **Last Updated**: 2024-02-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 如何管理你的游戏数据?比如说你的玩家?他有诸多数据需要管理,生命值,攻击力,位置,甚至库存。 一个简单的想法就是将他们作为变量存放在一个类似player.gd的脚本中。这并不能说是一个错误,但我觉的一定有更好的方法。 在最近的学习中,我发现了一个不错的思路,在我介绍这个思路之前,我还有一个问题需要大家思考,你了解Godot中的“资源”吗? ```gdscript extend Resouce @export var value:float = 100.0 ``` 请问,这是资源吗? 答案显然是否定的,就像继承Node的脚本不能被成为Node,继承Resource的脚本也不能称为资源————他们仅仅都是**脚本**。 当脚本被具体的创建为 xxx.tres 后,**xxx.tres** 才能被称之为资源。 如果你不清楚如何将脚本创建为资源,我建议你对此概念进一步了解。 资源可以作为变量导出,导出的资源会被展开,资源中的导出字段会被显示在编辑器中。 ![alt text](image.png) 资源会在编辑器的操作下创建实例,此实例类似智能指针,他是基于引用计数的,除非你执行了唯一化操作,否则它就只会产生唯一的一个实例,就如同**单例**一般。 是的,它可以作为自动加载的单例的替代方案。 Godot 还提供了 `ResourceSaver ` 用于将资源存储在磁盘上。 可以看到,将资源作为游戏实体的数据支撑是一个不错的想法,它将关联的数据集合起来,易于管理,并且能更加容易的序列化。 它的另一个类似于单例特性,可以用来做什么呢?例如一个事件总线? 在这个示例中,我们创建了一个UI事件总线作为资源 ui_event.gd ``` extends Resource #################################################################################### # UI事件总线 所有更新UI的操作均可在此处创建信号 # 将 UIEvent 作为成员变量,在编辑器中快速选择对应的资源文件 # 由于资源是对脚本实例的计数引用,因此所有选择上述资源文件的对象都将拥有同一份UIEvent实例 从而完成信号通信 #################################################################################### class_name UIEvent signal hp_info_changed(current:float, total:float) ``` 在此资源中创建信号,用来通知所有人关心的人,某项UI需要更新了。 信号的发送方需要创建此类型(UIEvent)的变量,然后在编辑器中快速加载一个对应类型的tres文件,如果资源还没有创建,则创建一个新的ui_event资源,同时另存为将其保存为tres资源文件。 信号的接受方也需要创建此类型(UIEvent)的变量,然后在编辑器中点击快速加载,选中创建好的tres文件即可。链接你感兴趣的信号,然后处理它。 这样,发送方和接受方使用的便是同一个资源实例,他们的信号能够互通。 在这个示例中,点击O和P可以加血扣血,你可以观察到我们是如何通过一个资源作为事件总线,从而通知UI进行更新的。我们还用资源的方式创建玩家的数据模型,集中管理数据,同时方便的在编辑器中编辑。 对了,我们还实现了一个血条,可以作为UI参考学习,玩的开心!。 update 数据驱动的物品系统 用GD代码一个个实现物品的逻辑实在不是一个好注意,将来我们还需要实现技能系统,BUFF系统。 这些系统的运作最终都会指向一个东西,那就是效果器,Effevtive,我目前还不知道这个东西的正确翻译,暂时就以Effective代替吧。 Effective代表最终执行的一段具体逻辑:扣血,加血,停止移动,禁止释放技能(可以加上TAG用来精细化控制,但我们目前不考虑这个)。到了Effective的具体实现逻辑这个级别,我们就不追求配置了,万物都是配置出来的听上去非常coooooool,但是绝对会让你的代码变得一团糟,包络万象的逻辑一定是一团乱麻并且难以维护的。 我们用gd将需要的Effective编写脚本,将参数导出,然后做一个apply函数,就大功告成了。 我们还需要一个复杂Effective,用来表示多个Effective的组合,从而让他有更强大的表现能力,例如多个扣血组合可以组成流血,我们力求让这种构造更加简单。 复杂Effective设计到Efftive的组合,因此我们要丰富Effective的细节 执行结束后 发送信号 effective_finsihed 有了Effective就可以将Effective构建成Buff 物品系统... 所有物品的效果都使用Effective实现