来解决连续跳跃这个问题,只有在地面上才可以执行跳跃
为了实现这个物理检测,我们需要单独写一个代码,因为除了人物需要检测周围的物理环境以外,我们的敌人也需要检测周围的物理环境,敌人撞墙需要返回继续走,在这个项目中需要创建这个通用的功能,真的把它写成一个component,挂在人物和npc身上都可以执行
首先我们在Player当中创建一个新的c#脚本
命名为PhysicsCheck(物理检测)
等代码加载好之后,我们就把他添加到我们的Player身上
在Player中点击add component,直接搜索PhysicsCheck添加
双击打开代码
我们接下来要做一些物理的检查判断,先把代码内的一些内容删掉
先创建一个check函数
这个检查要持续不断的进行,所以要把check函数放到Update当中去执行
public class PhysicsCheck : MonoBehaviour
{private void Update(){Check();}public void Check(){}}
在Check当中
检测地面,如果在地面上就可以允许按跳跃,不在则不允许
我们需要创建一些变量,来表示我们当前的人物状态
我们创建一个布尔值的变量(就是一个true,false的变量)起名叫isGround,判断人物是否在地面上,保存代码,返回unity
我们可以在inspector窗口看到这个检查框
这就是一个布尔值,他有两种状态,true和false;true代表在地面上
我们接下来用什么方法来检测人物
我们人物有一个Capsule Collider2D的组件,也就是一个物理组件,他在接触到我们地面的碰撞体之后,就会停留在那里,因为两个物体产生了碰撞,所以我们可以通过碰撞体碰撞的方式来进行检测(我们的墙面也是碰撞体,我们碰到墙面和地面要区分开来)
所以我们要分别检测这些方向,左边右边下边,下边检测到就代表人物在地面,左边和右边检测到就代表人物在墙上,我们需要这些监测点
BoxCast方形方式检测
Capsule胶囊方式
Circle点的方式
Overlap的检测方法也有box,capsule,circle的方式
我们使用OverlapCircle的方式,(我们可以检查出这个碰撞体是否位于一个圆形的检测范围内,圆形由其他世界空间中的中心坐标及其半径定义,可选的layerMask可让测试仅仅检查特定层上的对象)
layerMask是一个筛选器,用于检查指定层上的对象,避免持续判断很多对象的那种,比如脚底可能踩到花,敌人等其他东西,更加具体的检测是不是踩到地面上,所以用到这个参数作为一个筛选器
以中心点周围指定的半径来检测我们是否碰撞到了我们想要的内容
回到代码当中
public void Check(){//检测地面Physics2D.OverlapCircle()/*里面有6个重载的内容* (坐标中心点:人物脚底中心点用来检查地面,即transform position*/}
我们返回到unity中查看,Player的transform position(在scene中点击w查看)
我们可以看到这个坐标,所以这个坐标就是transform当前的坐标
键盘w(坐标移动工具)
要把这个坐标移到脚底,这个坐标应该在我们人物的脚底,也就是我们切割人物时的锚点,我们一会设置一个坐标的偏移来更改他的位置
我们返回代码
所以我们一开始最简单的判断点就是transform.position
接下来就是我们检测的范围,我希望这个范围可以在unity中进行编辑,所以我们可以创建一个变量,起名为checkRaduis检测范围,这样我们就可以在unity中进行编辑,修改调整大小
接下来是我们刚才说过的变量layerMask,我们希望他碰撞到的是我们地面的layer,所以我们也有创建一个LayerMask类型的变量,起名为groundLayer,检测是否碰撞到地面
碰撞到isGround=true,反之=false
所以我们直接用isGround=,因为它碰撞检测指定图层在范围之内的话,返回的就是一个true或false的一个布尔值
public class PhysicsCheck : MonoBehaviour
{public float checkRaduis;//检测范围public LayerMask groundLayer;//地面碰撞筛选器public bool isGround;private void Update(){Check();}public void Check(){//检测地面isGround = Physics2D.OverlapCircle(transform.position, checkRaduis, groundLayer);}
保存代码返回unity,给这些变量来赋值
首先Player当中Ground Layer,下拉菜单,这里并没有什么我们能选择的内容,但是这个菜单我们可以记住他的样子
然后我们再来看inspector当中右上角的Layer和刚才那个是完全一致的
右上角就是我们的物理检测的碰撞图层
目前我们要检测的地面并没有碰撞图层
地面应该是我们Platform这一图层,他是有碰撞体的,所以我们要给Platform这一层添加一个Layer
地面应该是我们Platform这一图层,他是有碰撞体的,所以我们要给Platform这一层添加一个Layer
我们找到Platform在右上角点击Layer--add Layer
然后我们在里面进行添加
起名就叫Ground
然后再回到Platform当中,在右上角将Layer改为Ground
接下来我们返回到我们的Player上,我们刚才要碰撞的层,改为Ground
这样指定了我们只撞这一层,只检测和这一层有关的
我们检测的点是脚底中心点,还需要有一定的范围,范围不需要太大,比如0.2,我们先这样试一下,点击运行看效果
人物在地面上,IsGround为true
人物不在地面上,IsGround为false
所以我们就可以用这个数值来进行修改,限制我们的跳跃次数
那也就代表我要通过Player Controller里面访问一下我的physics check代码当中的IsGround是true或false
接下来学习两个代码直接怎样互相访问
我们先打开Playercontroller这个代码,
我们想要获得哪个组件,就创建这个组件对应的类型一个变量,然后用Getcomponent来获得这个组件就可以了
每一个代码都可以看做一个组件,我们要创建一个PhysicsCheck类型的变量
我们已经创建了PhysicsCheck作为一个类,所以我们可以创建这个类对应的变量
在awake当中获取变量,获得了组件之后,我们就可以获得它里面所有创建好的变量了,要记得一定是PhysicsCheck中的公开public变量
public class PlayerController : MonoBehaviour
{public Playerinputcontrol inputControl;//inputsystem,与控制有关的代码public Vector2 inputDirection;private Rigidbody2D rb;//创建刚体类型private PhysicsCheck physicsCheck;//物理检测类型的变量[Header("基本参数")]public float speed;public float jumpForce;private void Awake(){rb = GetComponent<Rigidbody2D>();//获得Rigidbody2D的组件physicsCheck = GetComponent<PhysicsCheck>();//获取PhysicsCheck组件inputControl = new Playerinputcontrol();inputControl.Gameplay.Jump.started += Jump;
在Playercontroller找到我们的跳跃,跳跃是一个单独的函数方法
在跳跃命令之前,我要加上一个限制,如果在PhysicsCheck物理检测当中isGround为true,可以执行我的跳跃命令,反之则不能
保存返回unity,运行一下
private void Jump(InputAction.CallbackContext context)//注册函数,固定模式Jump
{if(physicsCheck.isGround)//Debug.Log("Jump");rb.AddForce(transform.up * jumpForce, ForceMode2D.Impulse);
}
目前在空中不会一直跳跃,只有落在地上才能跳跃,这样我们就成功实现了限制人物跳跃
目前还存在问题,我们刚才的地面检测,单纯靠我们对这个函数方法的理解,真实的检测范围有多大还不清楚,图片的中心点也有一些偏差
我们要添加一个变量,来修改它脚底位移的差值
我们用第二种方法在scene中来绘制出我们脚底碰撞的检测范围
首先我们打开PhysicsCheck代码添加一个变量public Vector2 bottomOffset(脚底位移差值);
所有他的检测点,我就用当前坐标值加上我的脚底位移差值
目前报错提示三维向量和二维向量之间不能用加号的方式来相加
所以我们要在transform的前面给他进行一个强制转换,把它转换成Vector2,也就意味着,我只要你的xy就够了,现在我们就实现了一个位移差值的地方检测了
那么我们要怎样把这个位置绘制出来,接下来我们学习一个unity已经内置好的方法,OnDraw绘制
OnDrawGizmos:无论是否选择,一直绘制
OnDrawGizmosSelected:当物体被选中时,在窗口Gizmos当中进行绘制
我们选择第二种方法OnDrawGizmosSelected
private void OnDrawGizmosSelected(){}
保存代码,返回unity,我们可以看到Bottom Offset
一会我们修改x的值,让他稍微往左侧偏移一点点
Gizmos是在之前提到过的scene中右上角的内容
点击一下关闭,由蓝色变为灰色,我们关闭了场景当中的所有辅助线
点开可以看到,我们在这个基础上,在脚底来绘制一下范围,画一个圈,我们就能看到他实际的检测范围了
在代码PhysicsCheck中写一下
这些都是一些固定的写法
private void OnDrawGizmosSelected(){Gizmos.DrawWireSphere((Vector2)transform.position + bottomOffset, checkRaduis);/*绘制。虚线的球* 中心点transform.position+bottomOffset* 范围checkRaduis,*/}
保存回到unity
可以看到目前我们的人物脚底出现了一个白圈,就是我们的检测范围
接下来,由于我的坐标位置加上了我们的Button Offside,所以我挪动一下这个x值
圆圈跟着移动,因为我们绘制时,把位移差值也加进去了
把这个圆圈挪到人物脚底的中心位置,自己调试
我们把范围大小也改为0.08,这样人物就必须贴着地面才可以跳跃
方便我们调整变量参数,能够实际看见
方便查看
实现了简单跳跃
接下来还要解决一个问题,人物跳起来会贴着墙不动,原因就是我们的Rigidbody2D当中,我们有这个质量导致的,这个质量导致我们是有真实的物理材质,用力的撞在一个物体上的话,我们不会下滑
我们留意在Rigidbody2D当中,我们有一个参数变量叫做Material(物理材质),里面写了Physics Material 2D,同样在我们的Capsule Collider当中也有这个Material,也就是说当前的碰撞体,你也可以给他添加一个物理材质,那我就可以创建一个光滑的物理材质,让这个人物不会粘在物体身上,
我们可以在这里面新创建一个文件夹,在setting当中创建文件夹PhysicsMaterials物理材质,
然后我们点击加号--2D--PhysicsMaterial2D创建2D的物理材质,取名为normal
可以看到当前的摩擦力设置为0.4,我们只要把摩擦力改为0,这样他就可以滑动下来了
我们选择Player,在Capsule Collider 2D的Material选择normal这个材质
最后我们运行测试一下
不可以在空中跳跃,且跳跃时按住方向键人物不会贴墙
目前发现地面会挡住我们的Player,Platform和Player在同一图层middle,Player先建立被挡住,将Player改在前面,把Player图层的Order in Layer改大,改为5,这样就不会被遮挡了