1.2 环境搭建与入门
环境搭建的目标不是“把软件装上”,而是得到一条可重复的开发链路:能创建项目、能运行、能看到日志、能定位资源,并能在未来把同一项目交给另一台机器继续工作。很多初学者在第一天就把项目放在下载目录、把图片散在桌面、把临时脚本复制进多个文件,几周后才发现无法判断哪个版本可以运行。本节从一个小而完整的 Hello World 开始,同时建立以后会一直受用的秩序。
安装前的准备
从 Defold 官方网站下载与你的操作系统匹配的编辑器版本,并优先选择稳定发布版本。首次启动时,编辑器可能会下载构建所需的组件;网络环境不稳定时,请等待它完成而不是反复强制退出。安装完成后,先在菜单中确认编辑器版本,并记录到项目的 README 或开发日志中。这样当团队成员遇到“我的机器上能运行”的差异时,至少有一个明确的排查起点。
除了编辑器,建议准备三个轻量工具。第一是文本比较工具,用来查看脚本或配置的改动;第二是图像处理工具,用来检查透明边缘、像素尺寸和导出格式;第三是版本控制工具。即使你暂时不熟悉 Git,也应尽早让项目处于版本控制之下。游戏项目的资源和脚本会同时变化,能回看一次错误改动的价值远高于“记得自己改过什么”的信心。
为项目选择一个没有空格和特殊符号的本地路径,例如 ~/Projects/defold/sky-runner。不要把正在开发的项目放进云盘同步根目录;同步软件可能在构建时锁定文件,也会制造难以解释的冲突。云盘可用于备份,但版本控制仓库才应是协作和回退的主渠道。若要在移动设备上测试,还应尽早确认设备连接、开发者模式和签名需求;这些平台步骤不必等到游戏完成才面对。
创建项目与理解 game.project
启动编辑器后,选择新建项目。开始阶段应选空项目或官方最简模板,而不是一上来载入结构庞大的示例。给项目取一个英文标识,例如 sky_runner;玩家看到的中文名称可稍后在项目设置中填写。创建后,最值得先打开的文件是 game.project。它保存应用名称、显示尺寸、启动集合、渲染和平台等关键配置,是项目的“总开关”,但不是日常玩法代码的容器。
请把 Display 下的宽高当成设计参考分辨率,而不是唯一设备尺寸。比如横屏游戏可以先以 1280×720 设计,竖屏游戏可以先以 720×1280 设计。界面和镜头仍要面对不同长宽比,不能依赖“所有手机都刚好一样”。初期只需确定横竖方向、目标帧率和一个可读的窗口标题;其余设置保持默认,等有明确需求时再调整。一次性修改大量配置会让问题来源变得模糊。
项目创建后立即运行一次。即使看到的是空窗口,也说明编辑器、构建工具和默认启动集合已经连通。若启动失败,先看 Console 中最早出现的错误,而不是只看最后一行。常见原因包括路径权限、资源引用失效或配置文件语法错误。把完整错误文本复制到开发日志,随后在一个没有自定义资源的空项目里复现,通常能很快区分环境问题和项目问题。
认识编辑器:先掌握四个区域
Assets 面板是项目文件的入口。它显示图片、图集、集合、脚本、GUI、音频和配置等资源。这里的目录不是纯粹的视觉分类:资源之间的引用会影响构建依赖,因此移动文件后要及时修正引用。初学时不要频繁改变顶层结构;先建立稳定的目录,再让内容在其中增长。
Outline 面板描述当前编辑资源的内部层次。打开集合时,它列出游戏对象、嵌套集合和组件;打开 GUI 时,它列出节点、字体和材质等依赖。可以把它看成当前文件的结构树。选择树中的项目后,Properties 面板会显示可编辑属性。与其记忆每一个属性,不如养成先问“我现在选中的是资源、对象还是组件”的习惯。选错层级是很多初学者修改无效的原因。
代码编辑器用于编写 Lua 脚本。脚本文件通常从 init(self)、update(self, dt)、on_input(self, action_id, action)、on_message(self, message_id, message, sender) 等回调开始。不要急于在每个脚本中写齐所有回调;只实现当前需要的部分,能让逻辑更短、更容易读。Console 则是运行反馈的主要入口。成功时它会显示构建和启动信息,失败时会提供文件路径、行号和调用栈。把 print() 当作暂时的观察手段,不要用它代替有目的的断点和测试。
做一个真正有用的 Hello World
一个好的 Hello World 不应只是屏幕上出现一句文字,而应触及一条最小的游戏路径:集合启动、对象存在、脚本初始化、输入到达、状态变化、画面反馈。先新建一个集合,命名为 main.collection,并把它设为启动集合。然后在集合中创建一个名为 controller 的游戏对象,为它添加脚本组件 controller.script。
在脚本中可以先写入如下最小逻辑:
function init(self)
self.count = 0
print("Hello, Defold!")
end
function on_input(self, action_id, action)
if action_id == hash("tap") and action.pressed then
self.count = self.count + 1
print("点击次数:" .. self.count)
end
end
接下来创建 input binding 文件,为鼠标左键、触摸或键盘空格绑定动作名 tap,并在项目设置中引用该输入配置。运行后点击窗口,Console 应递增输出次数。这个例子看似朴素,却已经验证了三件重要事情:脚本被附着到对象上,输入映射按动作名而非硬件细节工作,运行时状态应保存在 self 中。以后把日志改为 GUI 文字、把点击改为跳跃按钮,底层思路并不会改变。
为了增加可见反馈,可以再建立一个 GUI 场景,放入文本节点,并由 GUI 脚本接收 set_count 消息后更新文字。控制器不直接操作 GUI 内部节点,而是发送一条带有数值的消息。这样做比直接把所有代码放进 GUI 脚本多一步,但它提前建立了“玩法和显示分离”的边界。当计分方式、界面皮肤或本地化改变时,维护成本会明显更低。
推荐的初始目录
目录服务于查找和边界,不是为了看起来专业。一个适合入门并可自然扩展的结构如下:
assets/
images/ # 原始图片与导入资源
audio/ # 音乐、音效
fonts/
collections/
main.collection
levels/
game_objects/
player/
enemies/
scripts/
systems/
lib/
gui/
screens/
widgets/
input/
game.input_binding
这里的关键不是目录名称必须完全一致,而是每一种资源有固定归宿。scripts/systems 放全局协调逻辑,如游戏状态和关卡加载;scripts/lib 放不直接依附某个对象的可复用函数;某个角色特有的脚本则可与角色资源放在同一目录。不要建立一个无限膨胀的 misc 或 new 文件夹,它们只会把未作决定的问题延后。
文件名建议使用英文 kebab-case 或 snake_case,并让资源名表达角色而非类型。例如 player-run.atlas、pause-menu.gui、coin-pickup.wav 比 new2.atlas、test.gui 更容易定位。游戏对象的 id、组件 id 与脚本中的消息地址也应保持可读。名称不是注释的替代品,但好的名称能使大量简单关系无需额外解释。
开发时的短循环
每次只改一个小假设,然后运行验证。一个实用循环是:写下目的;修改一到两个文件;运行;观察视觉效果和 Console;记录结果;再决定下一步。避免同时修改输入、物理、资源和界面,否则当角色不动时无法判断究竟哪一层出错。对看似无关的错误,也先回退到“上一次可运行状态”并比较差异,而不是持续在损坏状态上叠加补丁。
热重载可以提高脚本和资源调试效率,但它不是初始化流程的替代品。某些状态只在完整启动时建立,某些资源引用或集合层级的改动也需要重新运行才能可靠验证。养成在阶段性完成后进行冷启动测试的习惯,能提前发现依赖旧状态的隐患。发布构建与编辑器运行也并非完全等价;后续进行平台发布前,必须在目标环境中做完整验证。
本节检查清单
完成本节后,你应能回答以下问题:项目根目录在哪里;game.project 管理哪些全局设置;启动集合是什么;脚本为何要附着在游戏对象上;输入动作名在哪里定义;日志应该去哪里看;新图片、脚本、界面分别放在哪个目录。如果有一个问题回答不清,不要急着进入复杂功能,回到 Hello World 把那条链路再走一遍。
环境本身不会让游戏变得有趣,但可靠的环境能让每一次创意验证都更便宜。下一节将详细解释集合、游戏对象、组件、精灵、图块和碰撞体这些积木,之后我们就能用它们搭建第一个真实的可玩场景。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。