You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lua光线投射异常排查:新高效光线投射代码问题咨询

排查Lua光线投射代码的异常问题

先把你的代码片段整理成更清晰的格式,方便分析:

-- 射线方向向量(角度r转弧度)
vectorX, vectorY = math.cos(r * math.pi/180), math.sin(r * math.pi/180)

-- 墙体线段的方向向量(v[1],v[2]是起点,v[3],v[4]是终点)
wallDistanceX, wallDistanceY = v[3] - v[1], v[4] - v[2]

-- 墙体的垂直向量
wallParallelX, wallParallelY = -wallDistanceY, wallDistanceX

-- 相机到墙体起点的向量
rayX, rayY = v[1] - cam.x, v[2] - cam.y

-- 计算射线参数t(Distance)
Distance = (rayX * wallParallelX + rayY * wallParallelY) / (vectorX * wallParallelX + vectorY * wallParallelY)

-- 不完整的交点范围判断
if (math.min(v[1],v[3]) <= (cam.x + Distance * vectorX) and math.max(v[1],v[3]) >= (cam.x + Dista...

接下来逐个分析可能引发异常的点,以及对应的修复方案:

1. 除数为零的致命错误

你的分母vectorX * wallParallelX + vectorY * wallParallelY是射线方向向量和墙体垂直向量的点积。如果射线和墙体完全平行,这个点积会等于0,直接触发Lua的attempt to divide by zero错误,导致程序崩溃。

修复方案:
计算前先判断分母是否接近0(考虑浮点精度误差,不要直接判断等于0),如果是则跳过当前墙体:

local denominator = vectorX * wallParallelX + vectorY * wallParallelY
-- 用极小值规避浮点精度问题
if math.abs(denominator) < 1e-6 then
    -- 射线与墙体平行,无有效交点,跳过
    goto continue
end
Distance = (rayX * wallParallelX + rayY * wallParallelY) / denominator

2. 变量拼写错误

最后一行的Dista是Distance的拼写错误,这会导致attempt to index global 'Dista' (a nil value)错误,直接中断代码执行。

修复方案:
把Dista改成完整的Distance即可。

3. 交点范围判断不完整

你只判断了交点的X坐标是否在墙体的X区间内,但完全忽略了Y坐标的范围。这会导致程序把墙体线段延长线上的点当成有效交点,比如射线穿过墙体端点的延长线时,会错误判定为碰撞。

修复方案:
补充Y轴的范围判断,同时优化区间判断的写法:

local intersectX = cam.x + Distance * vectorX
local intersectY = cam.y + Distance * vectorY

-- 检查交点是否在墙体线段的X和Y区间内
local inXRange = intersectX >= math.min(v[1], v[3]) and intersectX <= math.max(v[1], v[3])
local inYRange = intersectY >= math.min(v[2], v[4]) and intersectY <= math.max(v[2], v[4])

if inXRange and inYRange then
    -- 有效交点,继续后续处理
    -- ...
end

4. 忽略射线方向的有效性(负Distance)

如果计算出的Distance是负数,说明交点在相机的后方(射线起点的反方向),这时候这个交点是无效的,不能作为墙体碰撞点,否则会导致渲染出相机背后的墙体,引发视觉异常。

修复方案:
添加Distance的正负判断:

if Distance > 0 and inXRange and inYRange then
    -- 仅处理前方的有效交点
    -- ...
end

5. 向量逻辑的潜在问题

你的rayX, rayY是相机到墙体起点的向量,但在参数方程推导中,正确的射线参数方程应该是:射线点 = 相机位置 + t * 射线方向向量,墙体线段的参数方程是:墙体点 = v1 + s * 墙体方向向量。你的投影计算逻辑虽然能得到t,但如果墙体端点的选择逻辑有偏差,可能会出现计算误差。

优化建议:
改用标准的线段-射线交点算法,逻辑更清晰也更容易排查问题:

-- 标准线段-射线交点计算
local x1, y1 = cam.x, cam.y       -- 射线起点
local x2, y2 = cam.x + vectorX, cam.y + vectorY -- 射线方向终点
local x3, y3 = v[1], v[2]         -- 墙体起点
local x4, y4 = v[3], v[4]         -- 墙体终点

local denom = (x1 - x2)*(y3 - y4) - (y1 - y2)*(x3 - x4)
if math.abs(denom) < 1e-6 then
    goto continue -- 平行或重合,无有效交点
end

local t = ((x1 - x3)*(y3 - y4) - (y1 - y3)*(x3 - x4)) / denom
local u = -((x1 - x2)*(y1 - y3) - (y1 - y2)*(x1 - x3)) / denom

-- t>0表示在射线前进方向,u在0-1之间表示在线段上
if t > 0 and u >= 0 and u <= 1 then
    local intersectX = x1 + t*(x2 - x1)
    local intersectY = y1 + t*(y2 - y1)
    -- 处理有效交点的逻辑
end

6. 角度输入的合法性

如果变量r不是有效的数字(比如NaN、nil),math.cos和math.sin会返回NaN,后续所有计算都会变成NaN,导致异常。

修复方案:
在计算方向向量前,先检查r的合法性:

if type(r) ~= "number" or r ~= r then -- r ~= r 用来判断NaN
    -- 设置默认角度,比如朝向正右
    r = 0
end
vectorX, vectorY = math.cos(r * math.pi/180), math.sin(r * math.pi/180)

内容的提问来源于stack exchange,提问作者crazicrafter1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:40:06