unity射线检测碰撞物的原理 如何让角色仅仅一次的跳跃呢?——角色跳跃

unity射线检测碰撞物的原理 如何让角色仅仅一次的跳跃呢?——角色跳跃

文章目录

这里我以角色跳跃为例,实现角色是否在地面判断的3种方法,及优缺点

分析

通常我们不希望角色可以进行无限次的跳跃

比如如何让角色仅仅一次的跳跃呢?

我们的思路是对这个角色进行一次检测,当角色接触到了平台或者地面时,我们才允许角色跳跃

当角色是在空中时,角色不允许跳跃,直到落地为止

检测地面

我们如何去检测一个物体是否在地面上呢?

1. 使用Raycast 1.1 介绍

我们可以去使用Raycast方法(射线检测),让他发射一条向下的射线,如果这条射线能检测到任何添加了Collider组件的平台,那就意味着我们的角色接触地面了

Physics2D.Raycast(xxx, xx, xx);

方法第一个参数为射线发射点

第二个参数 为射线的方向

第三个参数为射线的检测距离

检测距离我们不能写成无限长,检测的最大距离,应该是人物的中心点,到我们人物的【底部】再多出一点点的距离(一点点的距离我用0.1来表示),射线是从我们图片当中的中心点发出的

我们可以通过【sp.bounds.extents.y】直接获取这个整张图片一半高度

1.3 场景窗口可视化

为了能够在场景窗口种,可视化这条射线,我们可以通过Debug.DrawRay方法,参数传递的是射线的发射点和射线反向

1.4 完整实例代码

private void CheckGround()
{
	RaycastHit2D hitInfo = Physics2D.Raycast(transform.position, -transform.up, sp.bounds.extents.y + 0.1f);
	Debug.DrawRay(transform.position,-transform.up * (sp.bounds.extents.y + 0.1f), Color.red);
	if(hitInfo.collider != null)//我们检测到了平台
	{
		isGround = true;
	}else{
		isGround = false;
	}
}

1.4 存在问题 1.4.1 问题1

当Raycast进行检测时,游戏一开始第一个检测到的是它的本身,并不是平台,是含有collider组件的游戏对象,而且角色的这个collider组件又无法去除,导致检测一直是true

解决

在Start方法种,通过Physics2D.queriesStartInCokkiders=false,来忽略一开始射线检测的游戏内部collider组件

private void Start(){
	Physics2D.queriesStartInCokkiders=false;
}

1.4.2 问题2

如上图,当我们的平台靠的足够近时,并且小于角色的宽度时,我们的角色必然是可以站在这两个平台之间不会掉下去的,因为我们胖嘛,我们并不会掉下去,但是当我们想要再次进行跳跃的时候硬件设备,由于Raycast射线的检测unity射线检测碰撞物的原理,在我们的射线路径中,检测判定为空,我们并没有检测到任何的collider组件音乐音效,这也反映出了Raycast在进行检测时,带来的一些缺点和不足

2. 使用Overlapcircle 2.1 介绍

在检测平台跳跃时,我们通常并不会使用Raycst方法来检测人物是否着地,而是需要去给他一个【大小范围】的来检测。这次我们需要使用【Physics2D.OverlapCircle】方法,这个方法通过一个circle(圆形)区域去进行检测,如果检测到任何的collider的碰撞器组件对象,会返回collider2d类型的变量

Physics2D.OverlapCircle(xxx, xx, xx);

第一个参数是这个圆形的中心点位置

第二个参数是这个圆形的半径距离

第三个参数是这个圆形能够检测的【指定层】

2.2 场景窗口可视化

为了能够可视化的去看到,究竟我们这个圆形的检测范围是多大,OnDrawGizmos在方法的内部可视化一个子物体位置坐标为中心

OnDrawGizmos在方法内部可视化一个以子物体位置坐标为中心,检测长度为半径的圆形,这样我们就可以有通过Inspector窗口直接对这个圆形检测范围进行非常直观的调整

2.3 完整实例代码

private void CheckGround()
{
	Collider2D collider = Physics2D.OverlapCircle(checkPoint.position, checkRadius, layerMask);
	if(collider!=null)//我们检测到了平台
		isGround true;
	}else{
		isGround false;
	}
}
private void OnDrawGizmos()
{
	Gizmos.DrawWireSphere(checkPoint.position, checkRadius);
	Gizmos.color = Color.red;
}

2.4 存在问题

如上图,比如我们站在平台的边缘,如果我们的圆形的半径不足够大的话,我们依然没有办法去进行判断,但是如果我们的半径足够大,满足我们人物的宽度时,会出现我们的角色没有真正到达地面,也判定为可以再次起跳

3. 使用OverlapBox 3.1 介绍

对于上面的问题,我们就引入了【Physics2D.OverlapBox】方法

Physics2D.OverlapBox(xxx, xxx, xx, xx);

检测的形状只是从圆形变为了box方形,

第二个参数就不是圆的半径了,而是一个Vector2结构类型的变量,表示这个检测方形的长和宽,

第三个参数表示的是角度,我设置为0即可

3.2 场景窗口可视化

因为检测形状发生了改变,如果你想在场景窗口种可视化,我们需要在OnDrawGizmos方法中,将【Sphere圆球】变成【Cube立方体】

3.3 完整实例代码

private void CheckGround()
{
	Collider2D collider = Physics2D.OverlapBox(checkPoint.position, checkBoxSize, 0, layerMask);
	if(collider!=null)//我们检测到了平台
		isGround true;
	}else{
		isGround false;
	}
}
private void OnDrawGizmos()
{
	Gizmos.DrawWireCube(checkPoint.position, checkBoxSize);
	Gizmos.color = Color.red;
}

3.4 注意事项

我们最好保证检测方形的大小不要太大,如果检测的方形很大的话,我们会导致如果我们连续按下空格键(及跳跃键),很可能在第二次跳跃时检测人物还在地面上。同时进行了两次跳跃,导致一些不必要的问题,比如跳跃过高等

扩展

【unity技巧】实现马里奥一样更具物理感的长按长跳与短跳

【Unity游戏开发教程】零基础带你从小白到超神19——射线检测

参考

BeaverJoe【视频】:更具物理感的长跳与短跳和Raycast缺点

完毕

好了,我是向宇,

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是开始自习unity。最近创建了一个新栏目【你问我答】,主要是想收集一下大家的问题unity射线检测碰撞物的原理,有时候一个问题可能几句话说不清楚,我就会以发布文章的形式来回答。 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

我知道阁下是一位白嫖高手,但假如我说下面有个打赏按钮,那阁下又该如何应对呢?

(量力而行,力虽微,心暖人,你的支持是我创作的最大动力)

文章来源:https://blog.csdn.net/qq_36303853/article/details/131030870