Unity3D玩家Rigidbody开重力仍可飞,求修复及跳跃、墙跑功能实现方法
Unity 3D玩家飞行异常排查及跳跃、墙跑功能实现方案
玩家可飞行异常排查
- 检查Rigidbody组件的*重力缩放(Gravity Scale)*参数是否设置为0或者过小,即使勾选了重力开关,缩放为0也不会受重力影响
- 检查玩家身上的碰撞体是否勾选了
Is Trigger,触发型碰撞体不会产生物理碰撞,玩家会和地面无碰撞交互 - 检查当前场景中是否存在其他持续给玩家刚体施加向上力的脚本,避免多脚本逻辑冲突
- 检查地面碰撞体的Layer是否被排除在Raycast检测之外,你当前的接地检测没有指定Layer过滤,如果射线误检测到空中的非地面对象,会导致逻辑误判玩家处于接地状态,建议给地面单独设置Layer,给
Physics.Raycast增加Layer参数过滤检测对象 - 检查Rigidbody的*阻力(Drag)*参数是否设置过大,过大的垂直阻力会抵消重力效果,导致下落速度极慢看起来像飞行
- 检查玩家胶囊碰撞体是否和其他碰撞体产生了持续的挤压碰撞,导致刚体被持续向上弹开
跳跃功能实现
首先在代码中新增如下变量:
public float jumpForce = 7f; public float airMultiplier = 0.4f; // 空中移动阻力系数,避免空中移动和地面一样灵活
修改MyInput方法,新增跳跃输入检测逻辑:
void MyInput() { horizontalMovement = Input.GetAxisRaw("Horizontal"); verticalMovement = Input.GetAxisRaw("Vertical"); moveDirection = transform.forward * verticalMovement + transform.right * horizontalMovement; // 跳跃输入判定 if(Input.GetKeyDown(KeyCode.Space) && isGrounded) { // 重置垂直速度避免跳跃高度和下落速度挂钩 rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z); rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); } }
修改MovePlayer方法,区分地面和空中的移动力度:
void MovePlayer() { float currentSpeedMultiplier = isGrounded ? 1f : airMultiplier; rb.AddForce(moveDirection.normalized * moveSpeed * currentSpeedMultiplier, ForceMode.Acceleration); }
墙跑功能实现
首先做前置配置:给场景中所有可墙跑的墙面单独设置Wall层级。
在代码中新增如下变量:
public float wallRunForce = 8f; public float maxWallRunTime = 2f; public float wallCheckDistance = 0.7f; private float wallRunTimer; private bool isWallLeft; private bool isWallRight; private bool isWallRunning; public LayerMask wallLayer; // inspector中选择刚才创建的Wall层
修改Update方法,新增墙面检测和墙跑状态判定逻辑:
private void Update() { isGrounded = Physics.Raycast(transform.position, Vector3.down, playerHeight / 2 + 0.01f); // 左右墙面检测 isWallRight = Physics.Raycast(transform.position, transform.right, wallCheckDistance, wallLayer); isWallLeft = Physics.Raycast(transform.position, -transform.right, wallCheckDistance, wallLayer); // 墙跑生效判定:不在地面、挨着墙面、玩家按下前向移动键 if((isWallLeft || isWallRight) && !isGrounded && verticalMovement > 0) { if(wallRunTimer <= 0) wallRunTimer = maxWallRunTime; isWallRunning = true; wallRunTimer -= Time.deltaTime; // 墙跑期间禁用重力避免下落 rb.useGravity = false; rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z); } else { isWallRunning = false; rb.useGravity = true; // 墙跑计时器离开墙面后自动恢复 if(wallRunTimer < maxWallRunTime) wallRunTimer += Time.deltaTime * 0.5f; } print(isGrounded); MyInput(); }
修改FixedUpdate方法,新增墙跑驱动力逻辑:
private void FixedUpdate() { MovePlayer(); if(isWallRunning) { rb.AddForce(transform.forward * wallRunForce, ForceMode.Acceleration); // 可选:添加贴墙的力,避免玩家移动过程中脱离墙面 if(isWallRight) rb.AddForce(-transform.right * 2f, ForceMode.Acceleration); if(isWallLeft) rb.AddForce(transform.right * 2f, ForceMode.Acceleration); } }
如果需要增加墙跳功能,只需要在MyInput的跳跃判定逻辑中,增加墙跑状态下的分支,给玩家施加朝向墙面外侧+向上的冲量即可。
内容的提问来源于stack exchange,提问作者canadian.goose
相关产品推荐
相关产品推荐

