2017-08-08 130 views
1

视觉辅助
厚度VS宽度:here如何确定厚度与宽度? (使用光线投射)

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

上的GIF快速概要提供
-On每次点击原点(蓝色)和目的地点被创建(橙色)球体来表示,其中用户点击和用于计算距离的解释结束点(显示在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相互作用。

+0

让我们[在聊天中继续讨论](http://chat.stackoverflow.com/rooms/151438/discussion-between-ryemoss-and-jtth)。 – ryeMoss

回答

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 vs Raycast
通过射线广播,您可以设置起点,方向和距离,以便在该方向上进行检查,使用线阵广播可以简单地设置起点和终点,并在这两点之间进行检查。

因此,如果您明确知道最终目的地,请使用linecast,如果您想检查特定方向但没有特定终点,请使用raycast。

解决方案
首先,使用初始raycast来获取第一个点hit.point。然后,将ray.origin设置到对撞机外面的世界空间中的一个点(我们首先碰撞的对象的对撞机以获得hit.point),并将ray.direction设置为面向第一个点处的射线,hit 。点。

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

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