需求描述
实现3d物体只有在指定平台上才能够跳跃,在空中不能跳跃
使用Raycast射线检测的方法,从player碰撞盒最底部发射一条长度为0.1f射线,如果这条射线与设定好的地面相撞,认为是可以跳跃
实现
1、将可以跳跃的平台同一设定为一层layer,比如Ground
2、获取player最低点的位置
//首先获取碰撞盒
SphereCollider sphereCollider;
void Start()
{
rb = GetComponent<Rigidbody>();
sphereCollider = GetComponent<SphereCollider>();
Vector3 origin = sphereCollider.bounds.center + new Vector3(0,-sphereCollider.bounds.extents.y+0.0f,0);
}
//
bounds是碰撞盒的界限属性,通过bounds.certer可以获取碰撞盒的中心坐标,extents可以获取bounds的范围,extents.y即是y轴上碰撞盒长度的一半,可以当作半径来用
对于球型物体来说,中心坐标在高度上减去半径就是球的最低点,可以作为射线的初始位置
3、进行射线检测
Unity中有很多种射线,这里使用Physics.Raycast方法:
public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask)
返回值是bool,五个参数分别是:
Vector3 origin:射线起始位置
Vector3 direction:射线方向
out RaycastHit hitInfo:获取hit,射线碰撞的信息
float maxDistance:射线长度
int layerMask:允许射线碰撞的layer范围
从初始点origin沿direction方向发出一条长度为maxDistance的射线,如果射线与layerMask中的layer碰撞,返回true,否则返回false。
碰撞信息会保存在hitInfo中,如果检测到碰撞,会保存碰撞点坐标等信息;如果没有检测到碰撞,则会给hitInfo一个固定值,其中碰撞点坐标为(0,0,0)。
代码实现:
bool isGround;
void Start()
{
rb = GetComponent<Rigidbody>();
sphereCollider = GetComponent<SphereCollider>();
}
private void Raycast()
{
RaycastHit hit;
Vector3 origin = sphereCollider.bounds.center + new Vector3(0,-sphereCollider.bounds.extents.y+0.0f,0);
isGround = Physics.Raycast(origin,Vector3.down,out hit,0.01f,1<<6);
print(hit.point);
Debug.DrawLine(origin, hit.point,Color.red);
}
这样就可以进行射线检测,当isGround为true时,表示在平台上,可以进行跳跃:
private void Jump()
{
if(isGround && Input.GetKeyDown(KeyCode.Space))
{
rb.velocity = new Vector3(rb.velocity.x,0,rb.velocity.z);
rb.AddForce(Vector3.up*300*jumpSpeed);
}
}
会出现无法跳跃的情况
在上面的方法中,选取的origin坐标是player碰撞盒的最低点
发出的射线在起始点origin出并不会做碰撞检测,导致射线会直接穿过与player接触的Ground平台的碰撞盒,所以发现player与平台完全接触时无法跳跃,而与平台快要接触的时候时可以跳跃的。
解决方法
可以将射线的起始位置向上移动0.1f,同时将射线的长度也加长0.1f:
private void Raycast()
{
RaycastHit hit;
Vector3 origin = sphereCollider.bounds.center + new Vector3(0,-sphereCollider.bounds.extents.y+0.1f,0);
isGround = Physics.Raycast(origin,Vector3.down,out hit,0.11f,1<<6);
print(hit.point);
Debug.DrawLine(origin, hit.point,Color.red);
}
这样就可以避免origin和碰撞盒重叠的问题
在2D平面上跳跃出现的奇怪现象
如果将Ground换成一个平面,比如:
让player在一个平面上跳跃,而且origin与平面的碰撞盒重叠时,会出现上面1、4象限可以跳跃,2、3象限不能跳跃的情况。
也就是说,射线下一半平面可以检测到碰撞,另一半平面不能检测到碰撞
目前还不知道什么原因
另外,在做2D场景的时候,即使origin与平面的碰撞盒重叠也能检测到碰撞,不需要对起始点origin进行处理。
总之,在3D场景下使用这种方法做跳跃检测还是要对origin坐标的位置做一下处理的