跳至正文
版本:bleeding-edge 🩸

追踪与光线投射

如何在运行时使用追踪与光线投射来获取世界信息。

追踪提供了一种在地图中进行延伸并获取线段上存在何种物体的反馈的方法。使用它们时,你需要提供两个端点(起点和终点位置),物理系统会在这些点之间“追踪”一条线段,并报告它击中的任何 Actor。追踪与其他软件套件中的光线投射或光线追踪本质上是相同的。

信息

Trace 仅在客户端可用,因为服务器不运行世界物理。如果服务器需要结果,请通过远程事件发送(并进行校验,因为客户端可以发送任何内容)。

以下示例将向你展示如何获取玩家正在注视的物体以及注视的位置。

Client/Index.lua
-- 每 100 毫秒进行一次追踪
Timer.SetInterval(function()
local local_player = Client.GetLocalPlayer()
if (not local_player) then return end

-- 获取相机位置和玩家瞄准的方向
local camera_location = local_player:GetCameraLocation()
local direction = local_player:GetCameraRotation():GetForwardVector()

-- 从相机位置沿瞄准方向乘以 5000 进行追踪
-- 即在该方向上追踪 5000 个单位
local trace_max_distance = 5000

local start_location = camera_location
local end_location = camera_location + direction * trace_max_distance

-- 确定要追踪的对象类型(WorldStatic - 静态网格体 - 以及 PhysicsBody - Prop)
local collision_trace = CollisionChannel.WorldStatic | CollisionChannel.PhysicsBody

-- 设置追踪模式(我们希望返回 Entity 并绘制调试线)
local trace_mode = TraceMode.ReturnEntity | TraceMode.DrawDebug

-- 执行追踪。TraceMode.DrawDebug 会在追踪线段中绘制一条调试线
local trace_result = Trace.LineSingle(start_location, end_location, collision_trace, trace_mode)

-- 如果击中某物,在该位置绘制一个调试点
if (trace_result.Success) then

-- 如果击中 Actor,则将点设为红色或绿色
local color = Color(1, 0, 0) -- 红色

if (trace_result.Entity) then
color = Color(0, 1, 0) -- 绿色

-- 在这里你可以检查击中了哪个 Actor,例如
-- if (trace_result.Entity:IsA(Character)) then ...
end

-- 在击中位置绘制一个持续 5 秒、大小为 10 的调试点
Debug.DrawPoint(trace_result.Location, color, 5, 10)
end
end, 100)
提示

要追踪玩家的瞄准位置,优先使用 Player:GetCameraLocation() 和 Player:GetCameraRotation(),而不是使用 Viewport.DeprojectScreenToWorld() 对屏幕中心进行反投影。相机旋转本身就是瞄准方向,而反投影方向会跟随渲染相机,包括相机震动、武器摆动和相机延迟,这会使结果抖动。对于非瞄准的点(例如鼠标光标),请保留使用 DeprojectScreenToWorld。

提示

正如你所见,我们可以向 Trace 传递按位运算符,以便一次追踪多个 CollisionChannel!在 CollisionChannels 之间使用 | 即可实现此目的。

其他追踪形状​

除了线段之外,还可以使用形状进行追踪,这对于检查某个物体是否适合放置在某处或检测某个区域内的物体非常有用。它们都有 Single 版本(返回首次命中)和 Multi 版本(返回所有命中):

形状单次多次
线段Trace.LineSingle()Trace.LineMulti()
球体Trace.SphereSingle()Trace.SphereMulti()
盒体Trace.BoxSingle()Trace.BoxMulti()
胶囊体Trace.CapsuleSingle()Trace.CapsuleMulti()
提示

仅当你使用匹配的 TraceMode 标志(例如 TraceMode.ReturnEntity 或 TraceMode.ReturnPhysicalMaterial)请求时,结果表才会包含某些字段(例如 Entity 或 SurfaceType)。