当前位置:网站首页>Unity 射线与碰撞范围检测【踩坑记录】
Unity 射线与碰撞范围检测【踩坑记录】
2022-07-08 00:52:00 【地狱火堡垒】
射线检测
射线检测在2D和3D的区别比较大
一定要加上对应的Collider组件
对应的函数只检测对应的Collider,
Physics.Raycast是不会检测到Collider 2D的(这个让我有一次debug了好久才发现)对应API如下
Physics.Raycast(Vector3 origin,Vector3 direction,out RaycastHit hitinfo,float distance,int LayerMask);
//origin:射线的起始点,因为是位置坐标所以使用Vector3表示
//direction:射线的方向,因为是方向坐标所以使用Vector3表示
//hitinfo:一个结构体,可以储存碰撞体的所有信息。你可以声明一个空的然后直接代入就可以
//下面是可选参数:
//distance:射线检测的距离
//LayerMask:图层,如果输入图层的序号就可以只检测这个图层的相应物体,
可以使用Debug.DrawLine(Vector3 origin,Vector3 destination,Color color)和Debug.DrawRay(Vector3 origin,Vector3 direction,Color color)来使射线可视化
此外因为Ray都是由两个Vector3变量构造而成的,而2D世界都是Vector2,只能用Vector2变量表示了。
当从物体中心点发出时,检测到的第一个碰撞体却是自己。
那我们该怎么解决这个问题呢?答案是Physics2D.queriesStartInColliders = false;这样如果碰撞体是我们射线所在起点的内部时,我们不让它返回该碰撞体。
为什么LayerMask是int
LayerMask的形式是int。它表示的是你图层的序号的二次方倍
就是相当于一个二进制数,需要检测的图层的对应位置为1,其余为0
- 1 << 10 打开第10的层。 等价于
1 << LayerMask.NameToLayer(“Ground”);也等价于LayerMask.GetMask((“Ground”); - ~(1 << 10) 打开除了第10之外的层。(取反符号)
- ~(1 << 0) 打开所有的层。
- (1 << 10) | (1 << 8) 打开第10和第8的层。
2D碰撞检测
Unity的物理引擎是基于PhysX的,但有时候游戏需要可配置的物理效果,按帧或者是时间线的方式来产生类似的效果。
Rigidbody 2D
选用了Rigidbody 2D组件的话,不能修改transform.position,而是要使用Rigidbody2D.position或Rigidbody2D.rotation
Body Type
- Dynamic: 表示动态刚体,完全模拟物理效果,与任何Rigidbody 2D都会发生物理效果,但是效率最低,只适合角色使用
- Kinematic: 表示运动学,只能和Dynamic刚体碰撞,如果需要和其他类型碰撞或者是需要触发碰撞事件,需要勾选
Use Full Kinematic Contacts. - Static: 和Dynamic发生碰撞效果,和Kinematic只能发生碰撞事件(需要勾选
Use Full Kinematic Contacts)
碰撞事件
我们除了可以在碰撞者和被碰撞者上监听碰撞事件外,如果监听碰撞的元素比较多,还能将碰撞事件抛出去由外部统一处理。
void Start()
{
CollisionLi1stener.onCollisionEnter2D.AddListener(delegace (GameObject g1, GameObject g2) {
Debug.LogFormat ( "{0}开始碰撞{1}",g1.name , g2.name);
});
CollisionLi1stener.onCollisionStay2D.AddListener(delegace (GameObject g1, GameObject g2) {
Debug.LogFormat ( "{0}碰撞中{1}",g1.name , g2.name);
});
CollisionLi1stener.onCollisionExit2D.AddListener(delegace (GameObject g1, GameObject g2) {
Debug.LogFormat ( "{0}结束碰撞{1}",g1.name , g2.name);
});
}
碰撞方向
Unity2D并没有提供方法来判断方向,但是提供了碰撞发生的坐标点,需要我们自己来计算碰撞方向。
void OnCollisionStav2D(Collision2D coll){
foreach (ContactPoint2D contact in coll.contacts)
{
//绘制线
Debug.DrawLine ( contact.point, transform.position, Color.red);
var direction = transform.InverseTransformPoint (contact.point);
if(direction.x > 0f){
print( "右碰撞");
}
if(direction.x < 0f){
print("左碰撞");}
if(direction.y > 0f){
print ("上碰撞");
}
if(direction.y < 0f){
print ("下碰撞");
}
}
}
Effector
unity可以给Collider 2D组件添加的额外效果
- Platform Effector 2D: 单向板地面,能从下往上跳,却掉不下来
- Surface Effector 2D: 传输带一样带摩擦移动
- Point Effector 2D: 类似炸弹,爆炸后可以把周围东西炸开
- Buoyancy Effector 2D: 模拟浮力
- Area Effector 2D: 区域力
不依赖物理引擎
我们可以不依赖物理引擎,可以极大的优化效率,比如我们可以利用射线检测实现碰撞检测
射线检测

可以看出只用一根射线检测是不行的,在2D-Epic-Controller中就使用了10个射线检测来判断地面和前提碰撞
这种方法手感非常的完美,不过实现起来有些许麻烦
Physical.Overlap
我们可以直接使用下面几种:
- Physics.OverlapBox
- Physics.OverlapCapsule
- Physics.OverlapSphere
可以在此基础上使用Gizmos 辅助线框来实现在Scence中更好的视觉效果
如果是2D则使用Physics2D.开头的一系列函数
3D碰撞检测
碰撞检测穿透
只要是跟碰撞相关的基本都是离不开Rigidbody这个组件,当中的Collision detection参数可以选择碰撞检测方式

主要用于处理高速s运动的物体,会有时候直接穿过其他物体的时候
(上图每个箭头两端均指的是两个即将碰撞的物体的Collision Detection属性的值,箭头中间的属性值所指的是这两个物体时间碰撞所用的碰撞检测模式)
Discrete(离散型检测模式)就是普通的默认状态;
Continuous(连续检测)则是更加精细的碰撞检测,但是很耗资源;
Continuous和Continuous Dynamic的共同点在于,对待没有刚体和设置为Continuous Dynamic的物体都使用连续碰撞检测,对待刚体设置为Discrete的物体都使用离散碰撞检测。
不同点在于,Continuous Dynamic在检测另一个设置为Continuous的物体使用的仍然是连续碰撞检测模式,而Continuous检测另一个Continuous的物体时使用的却是离散碰撞检测。

此两类方法由于依赖于连续(线性)扫描,所以会忽略物体的角速度,当物体迅速旋转时,仍然会有穿墙的情况发生
之后又出了一个Continuous Speculative **(基于推测式)**这里官方的API解释是要比Continuous和Dynamic的方式这两种方式更加的节省性能,是扫描方式的进行连续碰撞检测。
使用连续碰撞检测(Continuous和Continuous Dynamic)前提:
刚体和非刚体(静态碰撞器): 刚体物体的碰撞器必须是Box,Sphere,Capsule,非刚体物体的碰撞器必须是Mesh。
不使用物理引擎
不使用刚体 Rigidbody的方式,采用发射子弹之前,先发射射线,记录碰撞点(判断是否会发生碰撞),然后在发射子弹。
边栏推荐
猜你喜欢

adb工具介绍

数据链路层及网络层协议要点

Random walk reasoning and learning in large-scale knowledge base

Semantic segmentation | learning record (5) FCN network structure officially implemented by pytoch

Apache multiple component vulnerability disclosure (cve-2022-32533/cve-2022-33980/cve-2021-37839)

Semantic segmentation | learning record (4) expansion convolution (void convolution)

burpsuite
![[target tracking] |atom](/img/33/529b483a0a848e0e4263ba24462d5c.png)
[target tracking] |atom

Why did MySQL query not go to the index? This article will give you a comprehensive analysis

很多小夥伴不太了解ORM框架的底層原理,這不,冰河帶你10分鐘手擼一個極簡版ORM框架(趕快收藏吧)
随机推荐
静态路由配置全面详解,静态路由快速入门指南
MQTT X Newsletter 2022-06 | v1.8.0 发布,新增 MQTT CLI 和 MQTT WebSocket 工具
咋吃都不胖的朋友,Nature告诉你原因:是基因突变了
神经网络与深度学习-5- 感知机-PyTorch
银行需要搭建智能客服模块的中台能力,驱动全场景智能客服务升级
数据链路层及网络层协议要点
关于TXE和TC标志位的小知识
Talk about the cloud deployment of local projects created by SAP IRPA studio
VIM use
Key points of data link layer and network layer protocol
谈谈 SAP 系统的权限管控和事务记录功能的实现
Why did MySQL query not go to the index? This article will give you a comprehensive analysis
Cross modal semantic association alignment retrieval - image text matching
Keras深度学习实战——基于Inception v3实现性别分类
Apache multiple component vulnerability disclosure (cve-2022-32533/cve-2022-33980/cve-2021-37839)
科普 | 什么是灵魂绑定代币SBT?有何价值?
Clickhouse principle analysis and application practice "reading notes (8)
力争做到国内赛事应办尽办,国家体育总局明确安全有序恢复线下体育赛事
直接加比较合适
Many friends don't know the underlying principle of ORM framework very well. No, glacier will take you 10 minutes to hand roll a minimalist ORM framework (collect it quickly)