Unity3D-游戏中的技能碰撞检测

摘要:
在游戏战斗中,我们会使用各种碰撞检测来判断是否击中目标,例如扇区检测、圆形检测和矩形检测。后羿在王者荣耀中的大招是一个长矩形的碰撞体。事实上,一些对撞机组件封装在Unity3D引擎中以检测碰撞。但是当我最近写帧同步算法时,我发现U3D中冲突算法的执行顺序是不可控的,这会导致不同步的现象,所以我不得不强迫自己写冲突检测算法。

在游戏战斗中,我们会用到各种各样的碰撞检测,来判断是否打中了目标

比如扇形检测/圆形检测

Unity3D-游戏中的技能碰撞检测第1张

还有矩形检测,王者荣耀里后羿的大招就是一个很长的矩形碰撞体

Unity3D-游戏中的技能碰撞检测第2张

这些在Unity3D引擎中其实都封装好了一些Collider组件去检测碰撞,但是我最近写帧同步算法的时候,发现U3D中的碰撞算法执行顺序不可控,会导致不同步的现象,所以就只好苦逼的自己写碰撞检测算法了。

我们游戏是一个3D动作类游戏,大概的碰撞可以分为几类

  1. 圆柱体(把人/怪物的碰撞设定位一个圆柱体,U3D里是胶囊体,是为了解决一些边缘精度问题,但是我们游戏里的话圆柱就够用了)
  2. 球体
  3. 立方体

需要检测的碰撞有

1.检测圆柱体跟球体的碰撞

2.立方体跟圆柱体的碰撞

具体实现:

1.球体跟圆柱体碰撞检测

 1     /// <summary>
 2     /// 检测球体跟圆柱体碰撞
 3     /// </summary>
 4     /// <param name="x1">球体X</param>
 5     /// <param name="y1">球体Y</param>
 6     /// <param name="z1">球体Z</param>
 7     /// <param name="r1">球体半径</param>
 8     /// <param name="x2">圆柱体X</param>
 9     /// <param name="y2">圆柱体Y</param>
10     /// <param name="z2">圆柱体Z</param>
11     /// <param name="r2">圆柱半径</param>
12     /// <param name="h2">圆柱体高度</param>
13     public static bool CheckCircleAndCylinderCollider(float x1, float y1, float z1, float r1,
14     float x2, float y2, float z2, float r2, float h2)
15     {
16         float dx = x2 - x1;
17         float dy = y2 - y1;
18         float dz = z2 - z1;
19         float disSqua = (dx * dx) + (dz * dz);
20         float rSqua = (r1 + r2) * (r1 + r2);
21         bool heightCheck = Math.Abs(y1 - y2) < r1 + h2 / 2;
22         return heightCheck && disSqua < rSqua;
23     }

1.检测两个圆有没有相交

2.检测Y轴的距离是否小于球半径+圆柱体高度的一半

这里是把球体也当成了圆柱体进行检测,好处就是:效率高。 缺点是:不精确,没有考虑X,Z轴的旋转

但由于我们游戏中圆柱体不会有X,Z轴的旋转,所以这样的做法是最高效的

精确性问题:把圆柱体变成胶囊体,两端用两个球体来计算检测,这样会更精确,同时性能也会降低

2.立方体跟圆柱体的碰撞

这里先把问题简化成矩形跟圆形的碰撞检测

Unity3D-游戏中的技能碰撞检测第3张

计算方法是先找到矩形上离圆形最短距离u,然后再比较u是否小于圆形的半径r

1. 首先利用绝对值把 p - c 转移到第一象限,下图显示不同象限的圆心也能映射至第一象限,这不影响相交测试的结果:

Unity3D-游戏中的技能碰撞检测第4张

2. 然后,把 v 减去 h,负数的分量设置为0,就得到圆心与矩形最短距离的矢量 u。下图展示了4种情况,红色的u是结果。

Unity3D-游戏中的技能碰撞检测第5张

 最后要比较u和r的长度,若距离少于r,则两者相交。可以只求u的长度平方是否小于r的平方 

具体做法可以参考这里:https://www.zhihu.com/question/24251545

对于AABB包围盒,这样就已经可以检测碰撞了,但是如果矩形是旋转的OBB包围盒呢?

我这里是实现了一个OBB的包围盒类,记录了坐标,角度,碰撞检测的时候先把圆的角度旋转到OBB的坐标系里

利用旋转公式:

x2 = x * Mathf.Cos(rad) - z * Mathf.Sin(rad);

z2= x * Mathf.Sin(rad) + z * Mathf.Cos(rad);

然后再用那篇文章里说的方式计算矩形跟圆是否相交

最后再通过两者 Y轴的距离 < (圆柱体高度+立方体的高度)/2 ,如果小于则相交

这种方法的优势:效率高,而且精确

缺点是这个3D的OBB只能沿Y轴旋转,不过也够用了 

如果像王者荣耀类型的游戏,感觉不需要扩展到3D,2D检测应该就够用了

免责声明:文章转载自《Unity3D-游戏中的技能碰撞检测》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇pyinstaller设置icon图标出现“struct.error: unpack requires a buffer of 16 bytes”mysql查询语句中使用星号真的慢的要死?下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

sikuli简介

Sikuli脚本自动化,你在屏幕上看到的任何东西。Sikuli是一个开放源码的最初的用户界面设计组织在麻省理工学院的研究项目。现在是保持并进一步协调与开源社区开发的Sikuli实验室在美国科罗拉多州博尔德大学。Sikuli的MIT许可证下发布的。当然,你也可以使用sikuli的javaAPI使其在java环境下运行。小例子大体上了解sikuli的界面,下面来...

CentOS7 初始化配置

允许新TCP连接net.ipv4.TCP _ tw_ reuse=1net.ipv4.TCP _ mem=945000009150000009270000000net.ipv4 TCP _ fin_ Timeout=1#启用keepalive时,TCP发送keepalive消息的频率。默认值为2小时net.ipv4.tcp _keepalive_Time=3...

解决IDEA打包出现中文乱码的问题

解决方案:1.打开IDEA文件中的设置。...

【问题】如何批量导出AI文件里内嵌的图片

截止目前为止,新版的AI里面没有直接可以批量导出内嵌图片的选项,手动一个个导出实在太麻烦了。有人说用Phantasm插件可以导出,但新版的找不到对应支持的插件版本,所以这里就不说了。这里介绍一种简单粗暴的方法。...

转:(WIN)S04-CH01 PCIE XDMA开发环境搭建以及环路测试

XDMAIP使用部分教程分LINUX篇和WINDOWS篇两个部分。通过实战,面向应用,提供给大家XILINXFPGAPCIE应用解决方案。本教程以MK7160FA作为样机测试。这是一款高性价比的FPGA开发板。而M_AXI_LITE挂载的BRAM是需要进行BAR空间操作,所以地址设置为0x80000000...

plsql 导出查询结果

单击青色按钮,表示所查询的所有数据都将导出到指定文件,而不仅仅是以下列表中显示的数据行;无需单击“获取最后一页”按钮。注意:选择导出到excel文件时,需要注意默认导出为*。xlsx格式。您可以选择*。xls格式,但*。xls格式只能容纳65536行数据。如果要导出的数据超过最大值,则必须更改为*。xlsx格式!如果您仍然使用此格式,后面的数据将覆盖以前的数...