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

Unity平台跳跃游戏角色撞墙击退异常问题求助

Unity平台跳跃游戏撞墙击退功能问题记录

我正在制作一款Unity平台跳跃游戏(课程设计项目),原本希望实现角色撞墙后产生击退效果,但最初的代码不仅未实现该功能,还导致角色直接飞到地图顶部。修改Dichuyen脚本的FixedUpdate方法并添加OnCollisionEnter2D逻辑后,击退效果生效,但角色出现浮空问题。


初始问题代码

WallKnockback脚本

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

public class WallKnockback : MonoBehaviour
{
    public Dichuyen diChuyen;
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "Player")
        {
            diChuyen.KBCounter = diChuyen.KBTotalTime;
            if (collision.transform.position.x <= transform.position.x)
            {
                // 玩家撞到右侧墙体
                diChuyen.KnockFromRight = true;
            }
            if (collision.transform.position.x >= transform.position.x)
            {
                // 玩家撞到左侧墙体
                diChuyen.KnockFromRight = false;
            }
        }
    }
}

Dichuyen脚本

using System.Collections;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class Dichuyen : MonoBehaviour
{
    public float walkSpeed;
    public float moveInput;
    public bool isGrounded;
    public Rigidbody2D rb;
    public LayerMask groundMask;
    public PhysicsMaterial2D bounceMat, normalMat;
    public bool canJump = true;
    public float JumpValue = 0.0f;
    public float maxJumpValue = 10.0f;  // 添加跳跃上限变量
    public float KBForce;
    public float KBCounter;
    public float KBTotalTime;

    public bool KnockFromRight;

    void Update()
    {
        moveInput = Input.GetAxisRaw("Horizontal");

        if (JumpValue == 0.0f && isGrounded)
        {
            rb.velocity = new Vector2(moveInput * walkSpeed, rb.velocity.y);
        }
        isGrounded = Physics2D.OverlapBox(new Vector2(gameObject.transform.position.x, gameObject.transform.position.y - 0.5f), new Vector2(0.9f, 0.4f), 0f, groundMask);
        
        if (JumpValue > 0)
        {
            rb.sharedMaterial = bounceMat;
        }
        else
        {
            rb.sharedMaterial = normalMat;
        }

        if (Input.GetKey("space") && isGrounded && canJump)
        {
            JumpValue += 0.1f;
            if (JumpValue > maxJumpValue)  // 检查跳跃上限
            {
                JumpValue = maxJumpValue;
            }
        }

        if (Input.GetKeyDown("space") && isGrounded && canJump)
        {
            rb.velocity = new Vector2(0.0f, rb.velocity.y);
        }

        if (JumpValue >= 20f && isGrounded)  // 这个条件看起来没必要了
        {
            float tempx = moveInput * walkSpeed;
            float tempy = JumpValue;
            rb.velocity = new Vector2(tempx, tempy);
            Invoke("ResetJump", 0.2f);
        }

        if (Input.GetKeyUp("space"))
        {
            if (isGrounded)
            {
                rb.velocity = new Vector2(moveInput * walkSpeed, JumpValue);
                JumpValue = 0.0f;
            }
        }
    }

    void ResetJump()
    {
        canJump = false;
        JumpValue = 0;
    }
    
    void FixedUpdate()
    {
        if(KBCounter >= 0)
        {
            rb.velocity = new Vector2(moveInput * walkSpeed, JumpValue);
        }
        else
        {
            if(KnockFromRight == true)
            {
                rb.velocity = new Vector2(-KBForce, KBForce);
            }
            if(KnockFromRight == false)
            {
                rb.velocity = new Vector2(KBForce, KBForce);
            }
            KBCounter -= Time.deltaTime;
        }
    }
}

修改后的代码片段

void FixedUpdate()
{
    if(KBCounter <= 0)
    {
        rb.velocity = new Vector2(moveInput * walkSpeed, JumpValue);
    }
    else
    {
        if(KnockFromRight)
        {
            rb.velocity = new Vector2(-KBForce, rb.velocity.y);
        }
        else
        {
            rb.velocity = new Vector2(KBForce, rb.velocity.y);
        }
        KBCounter -= Time.deltaTime;
    }
}

private void OnCollisionEnter2D(Collision2D collision)
{
    if (collision.gameObject.CompareTag("Ground"))
    {
        foreach (ContactPoint2D contact in collision.contacts)
        {
            // 检查是否是侧面碰撞
            if (Mathf.Abs(contact.normal.x) > Mathf.Abs(contact.normal.y))
            {
                if (contact.normal.x > 0)
                {
                    KnockFromRight = true;
                }
                else
                {
                    KnockFromRight = false;
                }

                KBCounter = KBTotalTime;

                if (KnockFromRight)
                {
                    rb.velocity = new Vector2(-KBForce, rb.velocity.y);
                }
                else
                {
                    rb.velocity = new Vector2(KBForce, rb.velocity.y);
                }

                break;
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 10:14:51