Organizations

14 results for Godot
  • Godot分包方案 主要针对的是在 Godot 实现 Unity 的 AB包(Asset Bundle Package) 概念. 对于商业游戏来说都会把非核心资源切分成网络包, 通过CDN把资源包发布上加速资源下载速度; 也就是默认启动游戏应用都会生成空白游戏场景, 之后会把资源包从CDN更新到最新业务代码之中. 这种方式也算是一种热更新方式, 通过将非核心功能(场景|皮肤等)提取出来设置动态客户端的资源替换. 很有必要的流程, 可以直接做些临时的动态皮肤热更不用全面覆盖更新, 已上架的游戏不修改版本可以直接更新 这里需要说明的是, 以下示例都是采用 Godot C# 版本开发, 方便契合 Unity 转移到 Godot 开发; 并且 C# 能够尽可能复用 .net 相关的第三方社区扩展, 比如 Protobuf 这些相关的功能. 不过目前截止在 Godot 4.5 版本还无法做 Web 打包, H5 游戏支持需要后续版本解决才能出包 这里想构建项目, 并且追加两个场景分别是初始化入口场景和网络加载场景, 注意后续 C# 版本脚本文件都是尽可能采用 .net 规范(大驼峰): 注意: 一般推荐材质贴图单独封成材质包抽离出来, 做到 美术 和 业务 分离 一般需要准备材质表来加载其中所有的材质路径, 比如: user://Packages/UI.pck → https://cdn.localhost/Packages/UI.pck 这里具体流程如下: 请求远程接口确定目前最新版本的材质包文件 MD5 哈希码 获取本地 UI.pck MD5哈希码是否匹配, 不匹配需要删除本地的 pck 包 启动网络下载到本地 pck 资源, 写入到 user://xxx 最好和远程路径匹配方便映射 下载完成之后通过 ProjectSettings.
    Godot 游戏开发 Created Sat, 11 Oct 2025 22:31:37 +0800
  • Godot 集成 Protobuf Godot 版本默认指 Godot C# 版本 目前的 Godot 默认版本的 GDScript 脚本第三方的 Protobuf 库水平高低不平, 并且本身 Godot ABI 维护变动之下很容易某些属性|特性|方法在更新之后出现异常 所以如果需要采用 Godot 做网络序列化传输, 建议采用 C# 版本而非官方默认版, 从而才能利用上 .net 相关周边的第三方组件优势. 以上文档都是采用 LTS 版本的 .net 库相关 默认构建之后的项目之下有 XXXX.csproj 的 C# 配置文件, 这里就是主要的 .net 相关项目配置: <!-- 请留意这里, 这里代表默认采用 Godot-NET 自定义绑定, 也就是其实内部并不是完全支持全部 net 相关 --> <!-- 所以有些打包命令可能无法唤起, 像是 Protobuf 可能在常规 C# 项目当中引入可能没办法触发 Protobuf-Tools 自动打包命令 --> <!-- 需要注意的是因为采用的是 Godot.Net 绑定, 所以这里面默认加载目录分隔符号是 '/' 而不用区分 '\\' 和 '/' --> <Project Sdk="Godot.
    Godot 游戏开发 Created Sun, 28 Sep 2025 20:34:52 +0800
  • Godot版本Web部署 需要注意目前版本号: Godot4.2.2.stable, 听说后续版本会优化修复 这里采用了简单空项目用来检查显示鼠标的项目, 打出来的包大小为 wasm 单个文件大小竟然达到 47.0 MB(开启调试导出) | 34.0MB(不导出调试)! 或许你接触到日常游戏就会感觉到这个容量没什么, 但是可要知道这是 Web浏览器 受限于 Web 的权限导致资源大部分都是直接访问加载. 可以想象打开网页每次需要下载 48|34 MB 资源才能进游戏黑屏加载, 移动端网络环境特别复杂3G/4G/宽带网等情况 在没有分包加载情况, wasm 和 worker.js 加载及其恐怖且伴随兼容性问题, 目前已知某些浏览器是无法支持: 微信H5内核浏览器 部分Chromium打包浏览器 部分FireFox浏览器 之前安全性问题导致 SharedArrayBuffer 被禁用, 知道后续修改规范要求强制 https 同源访问才放出. 这里提供测试的 Godot 测试地址方便查看: 测试地址, 点击左边连接可以测试访问(服务器在国外可能速度比较慢) 这里可以看出其加载的异常状态: 这恐怖的包体是必须预先下载总合计 48|34 MB, 服务器哪怕开启大量的资源压缩技术( cf/gzip/br 等, 但是本身 wasm 也是压缩过了 ) 也没办法避免庞大胞体, 这也是不得不放弃开发 Godot 的 Web 版本原因, 其他还有大量国内浏览器带来的兼容问题. 官方GitHub也有人讨论 这个问题 本地测试脚本 Godot 导出项目之后需要在本地测试样例项目是否运行成功, 这里依靠 Python 挂载服务( serve.py 文件 ):
    Godot Created Tue, 04 Jun 2024 18:34:49 +0800
  • 状态同步 网络游戏的同步策略是作为服务端的必修课, 并且在其中接触到以下两种同步方式: 状态同步: 相对来说宽泛的同步条件, 对于数据同步精度不需要超高进度级别情况 帧同步: 适合少数人竞技短时局势的对局游戏, 要求对局所有人都有高精度高频率数据交换 帧同步在 FPS|格斗|MOBA 中都有更好的表现, 游戏选手操作能够达到媲美高精度电脑级别, 所以对于数据同步要求极高 帧同步由于高频率高精度的同步请求导致性能消耗极高所以没办法持久常年运行, 帧同步只接收客户端推送操作来让服务端演算, 帧同步的游戏更像是将游戏当中客户端负责部分移交给到服务端, 所以在操作|响应方面体验更加贴近客户端体验. 但是帧同步带来更大的知识点: 定点数, 内|外插值补偿帧, 同步步骤记录 目前就我接触到有以下方案来处理服务端状态同步: 自己从头编写 物理碰撞|寻路算法 在服务端处理方式使得客户端和服务端计算结果一致, 客户端负责提交操作让服务端一起计算结果保存在服务器. 依靠游戏服务端自带的 DedicatedServer, 在服务端上挂载业务游戏自带的场景服务器, 用户提交的数据依靠自己编写服务端构建重新包装推送到游戏自带服务器. 纯客户端实现的服务端, 基本比较知名的就是 Unity3D 的 ET(基于C#) 的集成开发服务端, 内部算法数据直接延用游戏引擎内部的方法 目前主流游戏开发引擎都自带 DedicatedServer 用来方便服务端挂载, Unity3d|UE|Godot 都支持挂载 从头实现在服务端实现客户端所需的 物理碰撞|寻路算法 之类对于服务端功底要求很高, 从数学到程序方面都要去从头开始设计; 而如果对游戏实时性要求不是那么高的话, 可以优先选用 状态同步 来构建, 所有这里着重讲解的就是 状态同步. 帧同步 涉及的知识点太过高深, 我至今都没办法说已经入门, 更别说深入了解构建样例. 状态同步 首先如果要做状态同步要准备构建出场景地图, 场景地图一般是为 2D(x,y)|3D(x,y,z) + block(碰撞不允许进入地区) + path(场景路线,玩家寻路直接检索路线最短点移动过去执行路线移动); 这里场景地图甚至需要客户端编辑器做好地图编辑器工具方便导出给服务端使用, 后续还有物理碰撞需要在服务端的 Update 做更新同步处理, 让服务端也可以模拟物理碰撞从而同步客户端的操作.
    Godot Created Thu, 02 May 2024 01:59:24 +0800
  • 网络游戏的场景同步 回归到游戏本质就是对于游戏客户端角色的操控, 单机游戏客户端通过操作指令来操作让其位移; 如果架构在网络游戏该怎么规划? 怎么把这方面的指令操作移交到服务端执行? 对于网络游戏来说, 客户端传上来的有可能是伪造数据, 最常见开启 变速齿轮 让游戏环境速度加速的情况, 这时候客户端肆无忌惮手动数据封包推送大量数据打乱游戏内部所有平衡. 但还有种情况是不需要在服务端频繁维护玩家实体状态, 场景中位移频繁都要提交到服务端对于CPU消耗比较庞大, 而有的场景实际上不具有太大的意义. 最常见的某些场景约等于材料本( 游戏中负责材料产出的副本 ), 这种玩家支付体力实际上只需最后结算奖励发放, 所以没必要同步太多细节. 需要明确几种游戏环境情况, 根据这些游戏环境才需要判断是否是否需要同步客户端场景同步: 多人同步: 这种是最常见需要同步操作场景, 因为场景内状态并不是单个玩家拥有的, 需要实时推送给同场景的不同玩家客户端 对战同步: 双人对战竞技场这种也是比较广泛场景, 常见用于双方竞技排名的情况, 最后决出的就是竞技分数和输赢情况 大逃杀模式: 最近兴起的多玩家在大地图互相猎杀的游戏, 这里面设计区域分块设计和多玩家状态同步设计, 这种中小厂目前没有驾驭的能力 塔防游戏: 塔防需要有具体的出怪逻辑和建筑攻击不断算血, 所以需要定时模拟计算攻击范围和血量变动. 上面就是比较常见的情况, 其实能够看出具体大部分都是强交互的情况, 这些情况也十分消耗CPU资源; 因为本身作为单机调用 Update 的情况就十分频繁, 而现在需要上万同时在线请求来维持游戏运转, 可以想象你上万人同时在线游玩来执行服务器的 Update 的 CPU 消耗也是非常惊人的. 偏轻度弱交互的移动端游戏, 则尽可能避免这种频繁需要消耗服务端 CPU 情况, 所以对于明确平台是移动端大部分采用相对简单的状态同步方式而非频繁帧同步. 建议如果对游戏服务端没有概念的, 可以先学习 skynet 试着学习 agent 概念设计和实现; 其中最主要概念就是对于单人在场景和玩法之中其实在服务端看来就是对自己所在数据的 自娱自乐, 轻度弱交互其实就是游玩游戏策划提供的玩法并且写入到服务端数据库. 这里按照最常见游戏帧( 60帧=Update每1/60s执行,30帧=Update每1/30s执行 ), 这种情况下需要在服务端动态创建 Update 定时器来处理. 高频率定时器 1/60s=16.7ms, 所以需要构建出 16.
    Godot 游戏开发 Created Sun, 07 Apr 2024 13:27:59 +0800
  • 建筑系统构建 网络游戏当中比较常见建筑功能经过大量版本迭代, 移动端为了节约性能消耗从地图区块拖动放置演变到固定建筑解锁; 这里先从客户端说明怎么去设计两种系统, 基本上只需要掌握这两种方式就能应对: PixelBuild: 允许玩家拖动建筑在平面上建成单位, 只要在平面不冲突就允许灵活构建单位 UnlockBuild: 平面上已经预设好建筑单位, 只需要按照条件激活该建筑进行工作 两者首先是必须要生成平面, 这里采用 Godot 来编写样例( Unity|UE 实际上思路也差不多 ); 现在构建最简单的生成 矿场(Gold) 和 农场(Farm), 具体自定义策划作用: Gold: 建成矿场之后 每5s 会提取游戏的金币资源到个人资源 Farm: 建成农场之后 每5s 会提取游戏的体力资源到个人资源 注意: 初始的资源收获周期是允许策划自定义的, 这里可以先考虑写死做成初版. 首先是像素点构建出建筑, 具体最后完成结果类似如下( PixelBuild ): 之后第二种建筑解锁方式就类似如下, 直接满足条件解锁激活建筑即可( UnlockBuild ): 注意: 之后内容要求具有一定服务端设计经验才能理解, 主体还是做状态同步到服务器共享. 如果想要达到满足玩家自由交互性, 最好采用 像素构建 让玩家在指定区域内选择构建建筑; 而如果只是简单想做个建筑解锁出资源点让玩家定时上线 收菜 获取收益的话, 直接采用 解锁激活 来激活建筑. 解锁建筑 这种建筑解锁方式目前大部分另外简称为 家园系统, 主要就是提供给玩家升级解锁产出游戏资源来维持游戏内部的经济系统; 以比较知名的二次元品类 “明日方舟” 为例, 初版内部就是家园解锁建筑从而生产出游戏内部货币 “龙门币” 等, 这种简单家园系统不需要太多客户端逻辑, 可能只需要 玩家等级提升|游戏货币解锁|游戏任务解锁 然后服务端协议统治下就能处理. 这方式只需要服务端去自行检查是否满足条件通知客户端解锁即可, 客户端所需要做的就是接收到协议获取多少秒之后可以领取的道具就行了
    Godot 游戏开发 Created Wed, 03 Apr 2024 20:40:56 +0800
  • 游戏授权登录服务端 游戏登录授权最好和游戏端脱离开来, 有时候需要接入
    Godot 游戏开发 Created Sun, 17 Mar 2024 00:34:44 +0800
  • 网络游戏在线奖励设计 在线奖励是网络游戏比较常见的, 客户端表现常见: 客户端加载在线时长奖励表 确定目前最后一次领取完时间戳 确认最后领取时间与当前时间戳差距 显示差距时间秒数确定可以被领取 点击推送指定时间戳满足条件奖励id 服务端判断是否满足,满足更新玩家资源信息 这种设计最常见早期二次元游戏品类的体力槽设计, 相当于每分钟回复1点体力然后玩家依靠体力解锁游玩副本. 这里先以最基础的在线体力增值做样例, 配置数据库字段和业务Actor来设计对应功能. 首先必须要在玩家信息实体当中挂载对应的体力相关字段, 主要用于记录玩家体力值相关数据: /** * 玩家实体对象 * 异步保存数据到数据库之中, 同时挂载在进程内存中用于读写 */ @Entity @Table(name = "tbl_player_info") public class PlayerInfoModel { /** * 玩家第三方登录uid, 这里采用主键自递增记录 */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(nullable = false, columnDefinition = "BIGINT COMMENT '主键ID,同时也是标识玩家UID'") private Long uid; /// 以下体力值系统是必须的 ------------------------------------------------------ /** * 体力值 */ @Column(nullable = false, columnDefinition = "INT COMMENT '体力值'") private Integer health = 10; /** * 体力值最后更新时间 */ @Column(nullable = false, columnDefinition = "BIGINT COMMENT '体力值最后更新时间'") private Long healthUpdateTime = 0L; /// 其他略.
    Godot 游戏开发 Created Thu, 14 Mar 2024 13:15:00 +0800
  • 策划CSV转JSON共享 这里可以 参考样例 日常的游戏开发中, 策划编辑配置表一般都是通过 Excel 在 Windows 环境进行配置, 如果是传统的 APP 开发, 一般都是在 WEB 网页端进行配置(在生成 JSON 下载), 所以对于 APP 开发和游戏开发这就存在里比较大的差异, 导致目前我们做很多游戏类应用玩法我们都是采用后者或者采用让产品去编辑 Json|XML 的方式, 更复杂的情况甚至去代码中编写配置表. 这里有 客户端代码库 做CSV据转JSON样例 具体表格格式如下: ##这是一个测试 ID 名字 描述 速度 int string string float 1 谢大脚 我是谢大脚 3.3 2 赵四 我不是找死 3.4 具体每一行数据的作用: 第一行: 策划的关注的表注视信息, 采用 ## 开头标识格式表( 实际上我感觉这行可有可无 ) 第二行: 需要表达的字段属性名, 可以是中文但最好是采用英语防止某些环境字符集导致的问题 第三行: 指定描述第二行对应属性的数据类型, 需要简单向策划或者产品做取值讲解让他们配置 实际上可以第一行就是字段中文含义, 第二行就是字段在代码的 key 取值, 注意策划也是必须要看懂的字段意义 优化之后我常规是这样处理: 标识 名字 描述 速度 key name desc speed int string string float 1 谢大脚 我是谢大脚 3.
    Godot 游戏开发 Created Tue, 12 Mar 2024 23:12:46 +0800
  • 场景过渡 最近在制作游戏过程之中碰到就是场景要过渡切换到另外另外场景, 在单机游戏和网络游戏当中场景切换应对方式感觉有所不同: 单机游戏: 常见开源项目场景切换都是直接无状态重载场景, 之后加载本地保存的数据 网络游戏: 所有场景优先加载到场景隐藏, 之后根据需要切换指定场景显示, 所有场景都不会释放而是采用隐藏处理. 在这种过程之中, 常常纠结于去怎么实现, 像 Godot 单机方面直接 SceneManagent 那样直接切换这种情况是不需要说明, 主要最近像开发 H5 品类的网络游戏, 一直在思考怎么做到状态维持的网络游戏转场切换. 读取场景是在当前场景还是之后场景? 场景黑屏切换过渡场景要求下个场景需要有相同的黑屏切换保持切换状态. 这里面的是需要保证场景A和场景B过渡场景都需要保持一致, 也就是场景A在黑屏读条准备加载场景B的过程之中, 这种情况要求所有被切换都要求先做好场景铺垫. 之后就是另外默认场景带有黑屏方式做转换: 这里把过渡放置在需要切换的场景, 默认 show 的时候自带黑屏读条等待初始化之后等待去展示. 这种切换方式其实更灵活点, 这样把切换加载读条逻辑转移到所在场景处理, 而且不会出现因为上个场景和当前场景冲突. 前置场景加载并非一无是处, 比如需要启动的时候动态加载所有资源的情况; 有的关卡需要常驻加载大场景的情况, 这时候就需要专门做过渡场景来处理. 在随机性大地图等动态地图情况就需要这样在切换成读条来动态构建地图, 这种构建过程的时间就需要动态创建场景之后附加到节点之后等待完成展示. 这里追加个 ColorRect 的颜色渐变样例: ''' 基于 ColorRect 颜色区块做的淡入淡出功能 ''' extends ColorRect class_name Fade ''' 默认初始化隐藏状态 ''' @export var is_hidden:bool = false ''' 淡入淡出的速度 ''' @export var speed:float = 1 ''' 是否还在执行切换 ''' var _running:bool = false ''' 确定是否淡入还是淡出 ''' var _use_fade_in:bool = false ''' 淡入事件信号 ''' signal fade_in_event ''' 淡出事件信号 ''' signal fade_out_event ''' 初始化 ''' func _ready(): if is_hidden: print_debug("hidden") hide() else: print_debug("display") show() set_process(false) '''' 调用淡入 ''' func fade_in(): color.
    Godot 游戏开发 Created Mon, 04 Mar 2024 17:45:14 +0800
Next