You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity角色跳跃碰墙被吸附粘墙问题的解决方法

Unity角色跳跃碰墙粘滞问题解决方法

你的粘墙问题完全是脚本逻辑错误导致的,不需要改引擎项目设置,按下面两步改完就能解决:

  • 落地判断逻辑错误:现有代码里OnCollisionStay()没有做碰撞面方向判断,只要角色碰到任何碰撞体(墙面、天花板、陡坡)都会被判定为“站在地上”,碰墙时游戏会误以为你踩在地面,持续响应朝墙方向的移动指令,自然会贴在墙上。
  • 移动方式违反物理系统规则:你用transform.Translate直接修改角色坐标,这个方法会完全绕过Unity的物理计算,直接把角色模型往碰撞体里面“塞”,物理引擎检测到穿模后会持续把角色推回碰撞表面,就会出现粘墙、滑墙落不下来的问题。

第一步:修正落地检测逻辑

删掉原来无参数的OnCollisionStay()方法,替换成带碰撞信息检测的版本,只有接触点在角色正下方时才判定为落地,同时补充离开碰撞体的状态重置逻辑:

void OnCollisionStay(Collision collision)
{
    // 遍历当前碰撞的所有接触点
    foreach (ContactPoint contact in collision.contacts)
    {
        // 用点积判断接触面方向:法线朝上=接触面在脚下,0.7f的阈值允许最大45度的斜坡
        if (Vector3.Dot(contact.normal, Vector3.up) > 0.7f)
        {
            isGrounded = true;
            break;
        }
    }
}

void OnCollisionExit(Collision collision)
{
    // 离开碰撞体立刻重置落地状态
    isGrounded = false;
}

第二步:把移动逻辑改成刚体驱动

用Rigidbody做角色控制器时,绝对不能用transform.Translate直接改坐标,所有移动、跳跃都要通过操作刚体的速度/施加力实现,避免和物理系统冲突。同时把输入检测从FixedUpdate移到Update,固定时间步的FixedUpdate会漏抓按键输入。
直接替换成下面的完整脚本即可,注释已经标清修改点:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RigidbodyPlayerController : MonoBehaviour
{
    public Rigidbody playerRidgidBody;
    public float movementSpeed = 3f;
    public float jumpForce;
    public bool isGrounded;
    private float horizontalInput; 
    private float verticalInput;
    private bool jumpPressed;

    void Awake()
    {
        playerRidgidBody.freezeRotation = true;
        playerRidgidBody.useGravity = true;
    }

    void Update()
    {
        // 所有输入检测放在Update中,避免丢失按键响应
        verticalInput = Input.GetAxis("Vertical");
        horizontalInput = Input.GetAxis("Horizontal");
        // 跳跃用GetButtonDown,仅在按下瞬间触发,不会出现长按连跳
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            jumpPressed = true;
        }
    }

    void OnCollisionStay(Collision collision)
    {
        foreach (ContactPoint contact in collision.contacts)
        {
            if (Vector3.Dot(contact.normal, Vector3.up) > 0.7f)
            {
                isGrounded = true;
                break;
            }
        }
    }

    void OnCollisionExit(Collision collision)
    {
        isGrounded = false;
    }

    void FixedUpdate()
    {
        // 跳跃逻辑
        if (jumpPressed)
        {
            // 跳跃前清零竖直方向速度,避免下落状态下跳跃高度异常
            playerRidgidBody.velocity = new Vector3(playerRidgidBody.velocity.x, 0, playerRidgidBody.velocity.z);
            playerRidgidBody.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
            jumpPressed = false;
            isGrounded = false;
        }
        
        // 移动逻辑:保留刚体原有的竖直速度(重力/跳跃生效),仅修改水平方向速度
        Vector3 moveDir = transform.forward * verticalInput + transform.right * horizontalInput;
        playerRidgidBody.velocity = new Vector3(moveDir.x * movementSpeed, playerRidgidBody.velocity.y, moveDir.z * movementSpeed);
    }
}

可选优化项(新手可以先改完上面两步再调)

  • 选中角色的Rigidbody组件,把Collision Detection从Discrete改成Continuous,高速跳跃碰墙时不会出现穿模、卡墙问题。
  • 如果还是有轻微滑墙感,可以新建一个摩擦力为0的Physic Material,拖到角色的碰撞体材质槽里,墙面不会因为摩擦力把角色挂住。

内容的提问来源于stack exchange,提问作者Peter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 21:39:28