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

Unity中保持射线水平沿物体表面发射Raycast的实现问题求助

任意旋转容器表面射线发射与液面网格生成修复方案

你之前的方案失效核心原因是强制将射线方向的Y分量置0,本质是把物体自身的局部轴向强行投影到世界空间XZ平面,完全丢失了物体多轴旋转带来的倾斜信息,最终射线方向和实际物体表面方向不符。
具体修复实现逻辑如下:

  • 先获取采样点对应物体表面的世界空间法向量:如果是通过预发射射线得到的采样点,可以直接读取RaycastHit.normal属性;如果是规则基础碰撞体的固定点采样,可先计算局部空间的表面法向量,再调用transform.TransformDirection()转换为世界空间法向量,完全保留物体的旋转信息。
  • 计算贴合表面的射线发射切向量:不需要手动修改任何向量分量,直接使用Unity内置的Vector3.OrthoNormalize()方法,输入表面法向量和任意不共线参考向量,即可得到两个正交的、完全贴合当前表面的切向量,该计算结果不受物体旋转角度影响。
  • 射线发射防误触处理:射线起点从表面采样点沿法向量向外偏移极小值(推荐0.001f ~ 0.01f),避免射线和当前物体自身碰撞体产生误检测。
    示例实现代码:
// 假设hit为提前采样得到的物体表面RaycastHit结果
Vector3 surfaceNormal = hit.normal;
Vector3 surfaceTangent, surfaceBitangent;

// 避免法向量和参考向量共线导致计算失败
if (Mathf.Abs(Vector3.Dot(surfaceNormal, Vector3.up)) < 0.999f)
{
    Vector3.OrthoNormalize(ref surfaceNormal, ref Vector3.up, out surfaceTangent, out surfaceBitangent);
}
else
{
    Vector3.OrthoNormalize(ref surfaceNormal, ref Vector3.right, out surfaceTangent, out surfaceBitangent);
}

// 发射沿表面延伸的射线
Ray surfaceRay = new Ray(hit.point + surfaceNormal * 0.005f, surfaceTangent);
if (Physics.Raycast(surfaceRay, out RaycastHit surfaceHit, 2f))
{
    // 此处处理表面射线的击中结果,用于液面网格顶点采样
}

针对自定义拼接容器的液面生成需求,你可以在完成全表面采样后,对所有采样点的高度值做平面拟合校验,过滤容器拼接缝隙产生的异常采样值,最终生成的液面网格会更平滑稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 11:15:03