14. 技巧:调试您的代码#

Lua是一门很不错的语言。然而,其在调试上却稍有困难。网上或许能找到一些针对独立运行的Lua脚本的调试器(例如vscode能下载的到的各种Lua debugger),但却不适用于FK。

因此,本文将试图为你扫清Lua调试方面的障碍。

假设你正使用Windows系统,那么启动FK的时候,应该是一个游戏窗口+一个黑色的命令行窗口。调试工作基本就是在黑色窗口进行的。

14.1. 使用debugger.lua#

这是比较简单的调试方法,FreeKill在lib中引用了debugger.lua作为调试库。

以下只简要介绍一下用法,最详细的详情请去项目官网查看: slembcke/debugger.lua

当你想要在代码中下断点时,就调用 dbg() 函数。当执行到这里时,就会停下来并在命令行中显示类似gdb的界面。

例如:

local room = player.room

dbg() -- 相当于下了断点,后面就可以来此进行调试
player:drawCards(1)

上面的代码中就调用了debugger.lua,让程序进行了中断,然后命令行就进入了调试界面。

提示

在默认的双击启用exe带有的命令行中,颜色可能会显示的非常奇怪。

如果你遇到了颜色不能正常显示的问题,推荐你使用Git Bash或者Windows Terminal之类的终端模拟器,然后在命令行中通过FreeKill.exe来启动游戏。

下面来说说调试的基本用法:使用 h 命令显示帮助信息。debugger.lua已经被我中文化了。

小技巧

其实也可以用lua自带的 debug.debug() 进行交互式调试,不过功能比debugger.lua弱得多了。

警告

在Linux上使用FreeKill -s开服时不能用这个调试器!因为stdin已经被服务端shell占用了,所以无法调试。

14.2. 利用VSCode的Lua调试插件进行调试#

更加便利且直观的办法是利用VSCode中的Lua调试器插件来进行调试。首先下载actboy168的Lua Debug插件:

../../_images/13-1.jpg

然后在工作区下(请确保工作区是FreeKill游戏目录,也就是含有FreeKill.exe那个目录)找到.vscode文件夹, 没有就新建一个,在其中创建launch.json和tasks.json两个文件(图中settings.json是我自己的配置):

../../_images/13-2.jpg

首先在tasks.json中写入:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "launch-freekill-client-debug",
      "type": "shell",
      "command": "./FreeKill.exe",
      "options": {
        "env": {
          "FREEKILL_LUA_DEBUG": "client"
        }
      },
      "isBackground": true,
    },
    {
      "label": "launch-freekill-server-debug",
      "type": "shell",
      "command": "./FreeKill.exe",
      "options": {
        "env": {
          "FREEKILL_LUA_DEBUG": "server"
        }
      },
      "isBackground": true,
    }
  ]
}

然后在launch.json中写入:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "以客户端调试模式启动FreeKill",
      "type": "lua",
      "request": "attach",
      "stopOnEntry": false,
      "address": "127.0.0.1:5927",
      "preLaunchTask": "launch-freekill-client-debug"
    },
    {
      "name": "以服务端调试模式启动FreeKill",
      "type": "lua",
      "request": "attach",
      "stopOnEntry": false,
      "address": "127.0.0.1:5928",
      "preLaunchTask": "launch-freekill-server-debug"
    },
  ],
}

保存好两个文件之后,在左侧栏的“运行和调试”页面中会出现新的选项,按需要选择 客户端调试模式或者服务端调试模式,选定完成后按下绿色小三角图标启动任务, 此时游戏会启动。这里以服务端调试模式启动为例。

../../_images/13-3.jpg

备注

写作这一段时,由于调试插件本身的一个bug,无法很便利的直接调试所有Lua, 只好像这样分成两个不同的模式启动。

游戏启动后,选择自己要调试的Lua文件(服务端的话,一般是触发技以及某些其他技能的生效), 例如以标准版技能“刚烈”为例。

鼠标移动到行号数字后,左侧会出现透明红色小点,点击红色点以添加断点:

../../_images/13-4.jpg

然后开一局游戏并设法发动刚烈,这样游戏会暂停,编辑器的窗口此时也应当弹出,此时进入调试界面。 调试侧栏中有许多有用的信息,首先,我们可以在“变量”栏中直接查看变量的值,对于table型还可以展开:

../../_images/13-5.jpg

我们可能还希望调查一些特定表达式的值,可以通过“监视”栏去查看。点击加号或者双击监视栏下的空白区域, 就可以添加想要查看的表达式的值了。

../../_images/13-6.jpg

调试侧栏中其他功能不再详细介绍,剩下需要仔细留意的是位于代码编辑器顶部的调试操作面板,介绍如图:

../../_images/13-7.jpg

功能就这么多,祝调试顺利!你也可以在游戏运行的途中,在编辑器中途增加或删除断点, 调试器会为你正常中断的。

当关闭掉游戏程序后,调试就算作结束。

14.3. 一些在调试中可能有用的函数#

debugger.lua的话,在调试器中直接输入Lua语句就能执行。

以下是一些可能用得到的函数:

14.3.1. print#

遇事不决print,这是当时没有调试器可用时候的措施。简单但却实用。

现在可以直接用debugger.lua的 p 命令输出表达式的值了,无需再自己写一堆。

14.3.2. p#

p 也是个函数,是inspect库的包装。它能详细输出表中的所有值,包括元表。

因此在使用它输出和类相关的东西的时候还是放弃为好...

14.3.3. json.encode#

将不含循环引用的表转换为json字符串。或许会很有用吧。但是不如p就是了。

14.3.4. GameLogic:dumpEventStack()#

输出当前的事件栈。在处理插结的时候能派上用场。