如何确定厚度与宽度? (使用光线投射)

时间:2017-08-08 19:47:44

标签: unity3d raycasting

视觉辅助
厚度与宽度:here

请查看简短的GIF 这里的厚度与宽度不同,因为有多个壁,因为有外筒和内筒。厚度是圆柱体任何一侧的外/内壁之间的距离的度量,其中厚度是从一端到另一端的距离,包围中间空间。

提供的GIF快速概要
- 每次单击都会创建原点(蓝色)和目标点(橙色)球体,以表示用户单击的位置以及用于计算距离的解释终点(显示在GUI上)。

原点定义了用户在物体对撞机表面上点击的位置,目的地定义了与原点的世界Y轴垂直的点,其中第二条射线朝向第一条射线投射,撞击另一侧。对撞机。

电流:

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{

//obtain the vector where the ray hit the collider.
    hitPoint = hit.point; //origin point
//offset the ray, keeping it along the XZ plane of the hit
    Vector3 offsetDirection = -1 * hit.normal;
//offset a long way, minimum thickness of the object
    ray.origin = hit.point  + offsetDirection * 100;
//point the ray back at the first hit point
    ray.direction = (hit.point - ray.origin).normalized;
//raycast all, because there might be other objects in the way
    RaycastHit[] hits = Physics.RaycastAll(ray);
    foreach (RaycastHit h in hits)
    {
        if (h.collider == hit.collider)
        {
            hitBack = h.point; //destination point
        }
    }
}

目前,宽度是适当的功能。我想计算厚度而不必进入对象内部(如gif所示)。

精彩参考
http://answers.unity3d.com/questions/386698/detecting-how-many-times-a-raycast-collides-with-a.html

这家伙基本上和我有同样的问题,并且有一个可能有效的解决方案。我不确定Linecasting与Raycasting的工作方式。

1 个答案:

答案 0 :(得分:1)

请:

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{

//obtain the vector where the ray hit the collider.
    hitPoint = hit.point; //origin point
//offset the ray, keeping it along the XZ plane of the hit
    Vector3 offsetDirection = -1 * hit.normal;
//offset a long way, minimum thickness of the object
    ray.origin = hit.point  + offsetDirection * 100;
//point the ray back at the first hit point
    ray.direction = (hit.point - ray.origin).normalized;

替换:

//raycast all, because there might be other objects in the way
    RaycastHit[] hits = Physics.RaycastAll(ray);
    foreach (RaycastHit h in hits)
    {
        if (h.collider == hit.collider)
        {
            hitBack = h.point; //destination point
        }
    }

获得MirrorMirror's富有洞察力的帖子,以及@ryemoss提供的工具性建议和帮助):

int counter = 0;
bool calculating = false; //set this to true on click
Vector3 Point, PreviousPoint, Goal, Direction;
Point = ray.origin;
Goal = hit.point;
Direction = ray.direction;

PreviousPoint = Vector3.zero;
while (calculating == true)
{
    counter++;
    RaycastHit hit2;
    if (Physics.Linecast(Point, Goal, out hit2))
    {
        if(counter > 100)
        {
            hitBack = hitPoint;
            counter = 0;
            calculating = false;
            break;
        }
        PreviousPoint = hit2.point;
        Point = hit2.point + (Direction / 10000f);
    }
    else
    {
        if (PreviousPoint == Vector3.zero)
            hitBack = hitPoint;
        else
            hitBack = PreviousPoint;

        calculating = false;
        counter = 0;
    }
}

Linecast与Raycast
使用光线投射,您可以设置起始点,方向和要在该方向上检查的距离,通过线条播放,您只需设置起点和终点,并在两点之间进行检查。

因此,如果您具体了解最终目的地,请使用线路广播,如果您想要检查特定方向但没有特定的终点,请使用光线投射。

<强>解决方案
首先,使用初始raycast获取第一个点hit.point。然后,将ray.origin设置为对撞机外部的世界空间中的一个点(我们首先碰撞的对象的对撞机以获取hit.point),并将ray.direction设置为在第一个点面对光线,然后命中.point。

最后,使用while循环在ray.origins新位置创建一个新的linecast(每次通过while循环更新,直到linecast到达hit.point),每次与对象发生碰撞直到linecast到达命中点。一旦达到hit.point,就意味着对象的每个表面都被击中,并且在每次击中时,创建一条新线,直到一条线到达第一个初始点hit.point。要计算厚度,请获取第一个匹配点,hit.point和反向播放前的点击命中hit.point,PreviousPoint之间的距离。

<强>更新
1 - 修改代码以正确处理单面对象(例如:平面) 2 - 添加计数器以防止无法进行计算的特殊情况 3 - 提高可读性。