我的游戏构建在某些用户那里随机出现黑屏,唯一的恢复方法是关闭并重新启动游戏。我为了找出这个问题简直抓狂。我在整个游戏中添加了 Debug.Log,做了我能想到的一切,但仍然无法确定是哪个脚本导致了问题。

编辑器版本:6000.3.24, 6000.4.10

构建平台:Windows

我从玩家的 Player.log 中得到了这些错误信息:

屏幕位置超出视锥范围(屏幕位置 0.000000, 0.000000)(摄像机矩形 0 0 1920 1080)
屏幕位置超出视锥范围(屏幕位置 1340.000000, 575.000000)(摄像机矩形 0 0 1920 1080)
屏幕位置超出视锥范围(屏幕位置 1340.000000, 575.000000)(摄像机矩形 0 0 1920 1080)


屏幕位置超出视锥范围(屏幕位置 inf, -234.402145)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, -1091.332886)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, -1239.882324)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, -981.883850)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, -1600.114624)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, -1806.460327)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, 926.342407)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, 1018.614258)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, 801.913879)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, 842.428284)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, 695.100098)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, 709.894409)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, 802.519104)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, 766.500854)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 inf, 836.807007)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 0.000000, 0.000000)(摄像机矩形 0 0 2560 1440)
屏幕位置超出视锥范围(屏幕位置 935.000000, 356.000000)(摄像机矩形 0 0 2560 1440)

这些错误重复了很多次。然而,我在自己的系统上还未能复现该问题。

我编写了这些包装方法,试图在问题发生时识别是哪个脚本调用了投影方法,但遗憾的是它们没有捕获到任何东西:

public static class ProjectionDiagnostics
{
public static Vector3 WorldToScreenPoint(Camera camera, Vector3 worldPosition, UnityEngine.Object caller, string operation)
{
Vector3 result = camera == null ? new Vector3(float.NaN, float.NaN, float.NaN) : camera.WorldToScreenPoint(worldPosition);
LogIfInvalid(camera, worldPosition, result, caller, operation, "world");
return result;
}
public static Vector3 WorldToViewportPoint(Camera camera, Vector3 worldPosition, UnityEngine.Object caller, string operation)
{
Vector3 result = camera == null ? new Vector3(float.NaN, float.NaN, float.NaN) : camera.WorldToViewportPoint(worldPosition);
LogIfInvalid(camera, worldPosition, result, caller, operation, "world");
return result;
}
public static Vector3 ScreenToWorldPoint(Camera camera, Vector3 screenPosition, UnityEngine.Object caller, string operation)
{
Vector3 result = camera == null ? new Vector3(float.NaN, float.NaN, float.NaN) : camera.ScreenToWorldPoint(screenPosition);
LogIfInvalid(camera, screenPosition, result, caller, operation, "screen");
return result;
}
public static bool ScreenPointToLocalPointInRectangle(RectTransform rectangle, Vector2 screenPosition, Camera camera, UnityEngine.Object caller, string operation, out Vector2 localPosition)
{
localPosition = Vector2.zero;
bool result = rectangle != null && RectTransformUtility.ScreenPointToLocalPointInRectangle(rectangle, screenPosition, camera, out localPosition);
if (!result)
{
localPosition = Vector2.zero;
}
if (rectangle == null || camera == null || !IsFinite(screenPosition) || !IsFinite(localPosition))
{
Debug.LogError($"Projection diagnostic: {operation}; caller={Describe(caller)}; camera={Describe(camera)}; " +
$"rectangle={Describe(rectangle)}; screen={screenPosition}; local={localPosition}");
}
return result;
}
private static void LogIfInvalid(Camera camera, Vector3 input, Vector3 output, UnityEngine.Object caller, string operation, string inputSpace)
{
if (camera == null || !IsFinite(input) || !IsFinite(output))
{
Debug.LogError($"Projection diagnostic: {operation}; caller={Describe(caller)}; camera={Describe(camera)}; " +
$"{inputSpace}={input}; result={output}");
}
}
private static bool IsFinite(Vector2 value)
{
return IsFinite(value.x) && IsFinite(value.y);
}
private static bool IsFinite(Vector3 value)
{
return IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.z);
}
private static bool IsFinite(float value)
{
return !float.IsNaN(value) && !float.IsInfinity(value);
}
private static string Describe(UnityEngine.Object value)
{
return value == null ? "null" : value.name;
}
}

还有什么其他因素可能导致这些视锥错误?这些错误可能是来自 Unity 内部 UI/输入/射线投射管线或其他内部系统,而不是来自我脚本的直接调用吗?