请继续阅读,了解如何使用 Unity 的调试类改进您的质量保证和调试过程。
虽然您可能已经熟悉了 Debug.Log函数,Unity 调试类还支持许多其他方便的函数,可以帮助您加快测试和调试速度。本页介绍了如何使用调试类在场景和游戏视图中实现小工具可视化,如何从脚本在编辑器中暂停播放模式,以及更多提示。
如果你有使用 Unity 的经验,那么你可能已经使用过控制台窗口来显示编辑器生成的错误、警告和其他信息。当然,您也可以使用调试类将自己的信息打印到控制台。
但您并不仅限于查看 Debug.Log 消息。在创建向控制台窗口输出字符串时,可以指定三种类型(错误、警告和消息)之一,每种类型都有各自的图标类型。
这三种变体分别是
- Debug.Log ("This is a log message.")
- Debug.LogWarning ("This is a warning message.")
- Debug.LogError ("This is an error message.")
您可以使用控制台窗口根据自己的偏好过滤邮件。您还可以利用控制台窗口中启用的 "错误暂停 "功能,因为通过调试类写入控制台的任何错误都会导致 Unity 的 "播放 "模式暂停。
所有输出到控制台窗口的内容,无论是 Unity 还是你自己的信息,都会添加到日志文件中,你可以参考日志文件查看应用程序中出现问题的地方。每个操作系统存储日志文件的位置不同,因此请查看文档,了解每个系统的规格。
当出现错误或异常时,控制台窗口会显示堆栈跟踪和错误信息,以帮助您了解错误是如何发生的,以及源于何处。虽然Debug.Log允许您向控制台发送信息,但您也可以配置堆栈跟踪中显示的详细程度。
默认情况下,控制台中的输出会链接到生成消息的代码行,这样就可以轻松识别导致条目出现的代码行、方法或函数调用序列。
如果脚本无法在所选的集成开发环境中打开,请访问文件 > 首选项 > 外部工具 ,然后从下拉菜单中选择"外部脚本编辑器"。
您可以通过编辑器中的文件 > 构建设置... > 播放器设置... > 其他设置来配置堆栈跟踪中显示的信息。
每种日志类型都有以下选项:
如果日志变得拥挤,请使用控制台的搜索功能。当您输入搜索词时,控制台会过滤信息,只显示包含匹配文本的信息。
单击控制台菜单按钮,从菜单中选择日志条目 > [X] 行,其中 [X] 是每个条目要显示的行数。
字符串 字符串格式方法可以创建内嵌格式化变量数据的字符串。调试类有 Debug.LogFormat使用相同的语法。
第一个参数是格式化的信息字符串。通过在大括号中包含索引值,参数 index-1 将被使用ToString方法(如果存在)或 System 字符串转换方法替换。在上述代码示例的第 14 行,{0} 将被origin.ToString() 代替。
一个更复杂的例子是这样的:
Debug.LogFormat("At Start transform.position={0}, transform.rotation={1}", transform.position, transform.rotation);
{0} 将被参数 1(transform.position)替换,而 {1} 将被参数 2(transform.rotation)替换。在每种情况下,都将使用 Vector3 和四元数属性的 ToString 方法。结果将是这样的
"原点为 (0.00, 0.00, 0.00)
UnityEngine.Debug:LogFormat (string,object[])”
您还可以为这些日志方法提供可选的第二个参数,以表明消息与特定的 GameObject 相关联:
Debug.LogWarning("I come in peace!", this.gameObject);
在显示格式化变量数据时,Debug.LogFormat 有警告和错误两种版本:
- Debug.LogWarningFormat("Cube.position.x 的值是 {0:0.00}",transform.position.x)
- Debug.LogErrorFormat("Cube.position.x 的值是 {0:0.00}",transform.position.x)
如果使用 Debug.Logformat 向控制台发送浮点数值,默认显示将在小数点后显示六个数字。您可以使用自定义数字格式化字符串来控制这种行为。
Debug.LogFormat("pi = {0:0.00}", Mathf.PI);
通过使用冒号,格式化字符串 0.00 将显示数值的整数部分、小数分隔符以及分隔符后的两个数字。最后一个数字将根据下一个数值四舍五入,采用大家熟悉的四舍五入方法。
在这个例子中,输出结果是:圆周率 = 3.14
Debug.Assert() 与 Debug.Log() 方法类似,但它不是向控制台记录信息,而是测试一个条件,如果条件为假,则显示一条错误信息。它用于在开发过程中验证假设和捕捉错误。
断言是检查程序是否进入意外状态的好方法。它们就像在 if 语句中嵌入 Log。当你在处理一个依赖于类属性分配的方法时,断言可以帮助你追踪错误。
调用 Debug.Assert() 时,它需要两个参数:要测试的条件和条件为假时要显示的可选信息。如果条件为真,则什么也不会发生,程序继续运行。如果条件为假,程序将停止运行,并在编辑器中显示错误信息。
void SetColor(Color color)
{
Debug.Assert(material != null, "ChangeColor: material not assigned");
material.SetColor("_Color", color);
}
如果调用 SetColor 时未分配材质,控制台中将显示 "SetColor: material not assigned"(SetColor:未分配材质)。
Debug.Break()是 Unity 调试类提供的一种方法,用于暂停游戏的执行,并在代码的当前点进入调试器。通过它,您可以检查游戏状态,并逐行检查代码,查找并修复错误。
调用 Debug.Break() 时,会停止游戏的执行并打开调试器窗口。这样您就可以检查游戏状态,并根据需要调试代码。您可以使用调试器逐步检查代码、设置断点以及检查内存中的变量和对象。
例如,您可能希望在 NPC 进入玩家角色的目标距离时停止游戏。当游戏中断时,您可以在检查器中查看其状态:
float dist = Vector3.Distance(transform.position, npc.position);
if ( dist < 5) Debug.Break();
Debug.DrawLine 和 Debug.DrawRay 是 Unity 的 Debug 类提供的两个方法,用于可视化调试。它们可用于测试和可视化物理相关代码,如碰撞和射线发射。这两种方法都允许您绘制一条在游戏和场景视图中都可见的彩色线条。例如,您可以使用 Debug.DrawRay 可视化子弹的轨迹或激光束的路径,使用 Debug.DrawLine 可视化碰撞器的边界或物体的移动。
Debug.DrawLine 用于在场景中的两点之间绘制直线:
Debug.DrawLine(transform.position, target.position, Color.white, 0, false);
它需要 2 到 5 个参数:起点、终点和可选颜色。例如,以下代码将在起点和终点之间画一条白线:
public static void DrawLine(Vector3start,Vector3end,Color color= Color.white, float duration = 0.0f, bool depthTest = true);
参数
- 开始世界空间中线条起始点
- 结束:世界空间中的点,即线条的终点
- 颜色线条颜色
- 持续时间显示该行的时间(秒)。0 显示单帧行
- 深度测试线条是否会被前景物体遮挡
在代码示例中,连接到骨架 GameObject 的 MonoBehaviour 脚本的 Update 方法产生了上图所示的图像。只有在游戏视图中启用了小工具,才能看到这一行。单击游戏视图窗格右上方的小工具按钮启用它们。在场景视图中也可以看到这条线。
DrawLine 的替代品是 DrawRay。Debug.DrawRay 用于在场景中绘制一条射线,射线从指定的原点开始,向指定的方向延伸。默认情况下,这是一条无限长的射线。当通过 Debug.DrawRay() 绘制的射线撞到碰撞点时,它会在交点处停止,不再继续前进。这种行为与 Unity 中用于检测场景中物体间碰撞的光线投射相同。
这里的第二个参数定义了线条的方向和长度。直线将从起点画到起点 + 方向:
public static void DrawRay(Vector3start,Vector3dir,Color color= Color.white, float duration = 0.0f, bool depthTest = true);
代码示例中的参数是
- 开始世界空间中线条起始点
- dir:直线在世界空间中的方向和长度
- 颜色线条颜色
- 持续时间显示行的时间(秒);0 显示单帧行
- 深度测试线条是否会被前景物体遮挡
下面是另一个代码示例:
Vector3 dir = transform.TransformDirection(Vector3.forward) * 3;Debug.DrawRay(transform.position, dir, Color.white, 0, false);
在本代码示例中,附加到骨架 GameObject 的 MonoBehaviour 脚本的 Update 方法会产生上图所示的结果。带有长度的射线可用于调试近程测试。在这里,射线长度为 3 个世界单位。如果攻击应该从 3 个单位开始,那么你就可以很直观地测试出 3 个单位在场景中的长度。
Gizmos 是在 Unity 中进行可视化调试的强大工具。通过它们,您可以在场景视图中绘制简单的二维和三维图形、线条和文本,从而轻松查看和了解游戏世界中发生的一切。
只需几行代码,您就可以在 "场景 "视图中绘制简单的形状和线条。这使它们成为快速制作原型和测试游戏机制的理想工具。它们是实时绘制的,因此你可以立即看到代码修改的结果,并做出必要的修改。
Gizmos 可以直观地显示复杂的游戏机制,单靠代码可能难以理解。例如,如上图所示,您可以使用 Gizmos 画出一条显示弹丸轨迹的线,或者将触发区的边界可视化。
使用小工具创建可视化辅助工具,让其他团队成员更容易理解你的代码和游戏机制。
小玩意对性能的影响很小,因此可以随意使用而不会降低性能。
小工具图标位于 "场景 "和 "游戏 "视图的右上角。要添加自定义小工具,需要添加一个包含 OnDrawGizmos 回调的脚本,如下代码示例所示。该脚本将绘制一个线框立方体,其位置比游戏对象的位置靠前 3 个世界单位。立方体的大小由 Vector3 类型的类属性vsize定义:public Vector3 vsize = new Vector3(1f, 1f, 1f);
void OnDrawGizmos()
{
// 在变换的位置上绘制一个黄色球体
Gizmos.color = Color.yellow;
Vector3 position = transform.position + transform.TransformDirection(Vector3.forward) * 3;
Gizmos.DrawWireCube(position, vsize);
}
点击小工具下拉菜单,控制可见度。任何带有 OnDrawGizmos 回调的脚本都会被列出。
查看文档,进一步了解 Gizmo 类的其他有用方法。
抛出异常是编程中的一种技术,用来表示程序执行过程中出现了错误或异常情况。您可以使用此方法阻止线程继续执行,以防止进一步损坏。
在 Unity 中,抛出异常的方式与其他编程语言相同。
如果抛出了异常,但代码中没有捕获和处理,程序执行通常会停止,你会被抛出应用程序并返回操作系统。在 Unity 中,程序会立即停止执行,运行时环境会查找可以处理异常的 "捕获 "块。如果找不到捕获块,程序将终止,异常将被记录到控制台。
抛出异常很有帮助,因为这样可以将错误处理逻辑与程序逻辑的其他部分分离开来,有助于编写更简洁的代码。通过抛出异常,可以向调用者发出出错的信号,而不必依赖返回值或全局状态来传达错误信息。
要在 Unity 中抛出异常,可以使用throw关键字,后面跟一个异常对象。这里有一个例子:
if (target == null)
{
throw new System.NullReferenceException("target not set!");
}
当你在编辑器中运行代码时,它会捕捉到抛出的错误并执行 Debug.LogError(),而不是让 Unity 或应用程序崩溃。
在 Unity 中使用异常可以及早捕捉错误。它还能为您提供更多有关错误发生位置和原因的信息,从而使调试变得更容易。
在这些文章中了解更多有关测试、调试和提高 Unity 项目性能的信息:
- 如何使用 Roslyn 分析器调试游戏代码
- 如何使用 Unity 测试框架为游戏运行自动测试
- 使用 Microsoft Visual Studio Code 加快调试工作流程
- 如何使用 Microsoft Visual Studio 2022 调试代码
- Unity 项目的测试和质量保证技巧
通过这些电子书深入了解 Unity 开发人员的高级最佳实践和说明:
在 Unity最佳实践中心可以找到更多高级资源。