1456110n7qr3279209kres.png
  GameRes游资网授权发布 文/瀚阳

  虽然此前写了5篇角色的文章,但我只是简短地提到了地形检测。知道角色站在什么地形上是非常重要的话题,因为很多角色的行为往往都取决于所站的地形。做好地形检测,可以明显提升体验的流畅度。

1441095dfd6fr4deegdsks.png
  射线直接从底部球心直接向下打出。在角色站在斜坡的情况下,下面的点是不正确的。而当角色钳住地面的时候,那个点会让角色稍稍与斜坡交叉。对于陡峭的坡体来说,这个问题就更加明显了。

  幸运的是,我们有救兵Physics.SphereCast。与其投射一条细微的射线出去,我们可以投射一个球体。这样就能解决上面提到的问题,从而确保角色总是完全在地表之上。

  在使用SphereCast能够顺利工作的同时,也带来了一些问题。首先是SphereCast碰到碰撞体边缘的时候,hit.normal返回的是两个相邻面的插值。这与Vector3.Lerp函数来类似。

144111jjdj6pc6nxwpp67x.png
  我们的角色是上不去85度墙的。对于这个墙来说我们的SphereCast的碰撞点是标记,而不是脚下方的平面。这会使得我们的角色会认为自己站在陡坡上,而不是平地上。

  最常见的办法是用Physics.SphereCastAll。它会理想地同时打中墙体与地面,然后我们可以遍历所有碰撞点,从而找到合适的立足点。不幸的是,SphereCastAll只能每个对象拣选一个碰撞点,也就是说如果墙体与地面是同一个对象,那么这个方案会出错。

  对于上面的问题,我们可以通过减小SphereCast的半径来解决。这样确实能解决一些问题,但不是全部。我们还是要想一种可靠的方法来来处理贴着陡坡这个问题。

  「PS: 在SuperCharacterController中,陡坡的定义是SuperCollisionType组件的StandAngle值定义的,可以放在所有与角色碰撞的碰撞体上。」

  为了解决这个问题,可以想象一下我们脚底下某种地形,如果没有被陡坡影响,我们是能够通过SphereCast检测出来的。为了找到这个地面,我们可以在SphereCast打中的地方用Raycast。这是主要用于检验是否存在这块地面,而且可以获取它的法线。

144111z65gpog1t5dd7g9g.png
  最初SphereCast的碰撞点在标记位置。因为我们与陡坡有碰撞,我们可以Raycast(红色)来检测陡坡之下是否有一块地面在我们之下(紫色)。

  这让我们知道下面有什么,但是由于用了Raycast,而不是SphereCast,我们会又一次遇到之前的问题,碰撞点会让地形与球体重合。给定我们有的信息(脚下地形的法线),我们可以将其转换为近似于SphereCast的数据吗?答案是Yes。

  每当你从底部向下SphereCast,然后碰到了一个表面,就会就在碰撞表面法线与碰撞点之间存在一种联系。在我们从斜坡碰撞点向下打射线得到正确地面的法线之后,我们的任务就是找到底部向下SphereCast与地面的交点。下面我们看看二维的情况,然后再回来解决三维问题。

144114hw2u38xybyxxbs7h.png
  通过sine与cosine计算碰撞点的位置

  现在我么可以用这些值来调整的位置(乘上半径)。

  「PS: 在SuperCharacterController中,近似计算SphereCast值的方法叫SimulateSphereCast。」

  以上就是超级角色中用到所有地形检测技术。不像之前的文章,这里地形检测话题是很开放的–上面只是其中的一种,但我法线它在实际中运行的很好。

  相关阅读Unity自定义角色(一):碰撞检测

锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛