try / catch / finally

trycatchfinally 语句可在您的游戏中用于错误检查并允许您测试代码块并控制发生任何运行时异常时发生的情况.使用这些将防止异常结束游戏并向用户显示标准错误消息,但这意味着您将必须处理在这种情况下接下来发生的事情,例如保存日志文件 - 并优雅地结束游戏(请注意,如果您选择什么都不做,您的游戏可能会变得不稳定并且无法正常运行)。

最基本的 try 语法如下:

try
{
    <statement1>;
    <statement2>;
    ...
}

但是,如果 try 没有任何内容来实际处理代码可能产生的任何异常,将不会很有帮助,因此我们通常将其与 catch 配对,语法如下:

try
{
    <statement1>;
    <statement2>;
    ...
}
catch(<variable>)
{
    <statement1>;
    <statement2>;
    ...
}

catch 的作用是允许您在捕获到前一个 try 的异常时运行以下块中提供的额外代码。如果这是运行时异常,则提供的变量可用于访问包含以下信息的 struct

{
message : "",               // a string that is a short message for this exception
longMessage : "",           // a string that is a longer message for this exception
script : "",                // a string that describes where the exception came from
stacktrace : [ "", "" ],    // an array of strings that is the stack frame the exception was generated
}

一个简单的使用示例如下所示:

var a = 0, b = 0, c = 0;
try
{
    c = a div b;
}
catch( _exception)
{
    show_debug_message(_exception.message);
    show_debug_message(_exception.longMessage);
    show_debug_message(_exception.script);
    show_debug_message(_exception.stacktrace);
}

您可能希望无论是否抛出异常都运行一些代码,因此您可以添加一个 finally 块。 finally 语法是:

finally
{
    <statement1>;
    <statement2>;
    etc...
}

值得注意的是,您可以将这些组合在一起,即:

注意,在finally块中,你不能使用breakcontinueexitreturn语句,因为它们在这里没有意义,如果使用它们,编译器将产生错误。

最后,您还可以将各种 try / catch / finally 相互嵌套,例如:

var a = 0, b = 0, c = 0;
try
{
    try
    {
        c = a div b;
    }
    finally
    {
        ++a;
    }
}
catch(_exception)
{
    ++a;
    show_debug_message(_exception.message);
    show_debug_message(_exception.longMessage);
    show_debug_message(_exception.script);
    show_debug_message(_exception.stacktrace);
}
finally
{
    show_debug_message("a = " + string(a));
}

值得注意的是,您可以接管默认的 GML 错误消息并通过调用函数 exception_unhandled_handler() 使用您自己的处理程序代码。此运行时函数允许您提供自定义方法以供您在游戏中发生任何未处理的异常时调用。