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

Unity 2D角色控制故障:UI按钮无法控制移动跳跃

Unity 2D移动端角色UI控制修复方案

核心问题分析

你的代码无法正常工作的关键原因是按钮事件绑定错误:使用Button.onClick事件同时绑定了按下和抬起方法,而onClick是在按钮被按下并抬起后才触发的事件,导致每次点击按钮时,Down和Up方法会被同时执行,状态变量(比如isMovingLeft)刚被设为true就立刻被设为false,Update方法自然检测不到正确的输入状态。

修改方案与完整代码

修改要点

  1. 替换按钮事件绑定:改用onPointerDown和onPointerUp事件分别监听按钮的按下/抬起动作,这两个事件是Unity UI处理触摸/鼠标输入的标准事件,能准确触发对应状态变更。
  2. 调整跳跃触发逻辑:将跳跃触发直接放在按钮按下事件中,避免状态被覆盖的问题;保留松键停止移动的核心需求。

修改后的完整代码

using UnityEngine;
using UnityEngine.UI;

public class CharacterController : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float jumpForce = 5f;
    private bool isJumping = false;
    private SpriteRenderer spriteRenderer;
    private Animator animator;
    private Rigidbody2D rb;
    private bool isFalling;
    private bool isRunning;

    public Button moveLeftButton;
    public Button moveRightButton;
    public Button jumpButton;

    private bool isMovingLeft = false;
    private bool isMovingRight = false;

    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        spriteRenderer = GetComponent<SpriteRenderer>();
        animator = GetComponent<Animator>();

        // 绑定正确的按下/抬起事件
        moveLeftButton.onPointerDown.AddListener(OnMoveLeftButtonDown);
        moveLeftButton.onPointerUp.AddListener(OnMoveLeftButtonUp);
        moveRightButton.onPointerDown.AddListener(OnMoveRightButtonDown);
        moveRightButton.onPointerUp.AddListener(OnMoveRightButtonUp);
        jumpButton.onPointerDown.AddListener(OnJumpButtonDown);
    }

    public void OnMoveLeftButtonDown()
    {
        isMovingLeft = true;
    }

    public void OnMoveLeftButtonUp()
    {
        isMovingLeft = false;
    }

    public void OnMoveRightButtonDown()
    {
        isMovingRight = true;
    }

    public void OnMoveRightButtonUp()
    {
        isMovingRight = false;
    }

    public void OnJumpButtonDown()
    {
        if (!isJumping)
        {
            Jump();
        }
    }

    private void Update()
    {
        // 移动逻辑:按下按钮时移动,松开时停止
        if (isMovingLeft)
        {
            rb.velocity = new Vector2(-moveSpeed, rb.velocity.y);
            spriteRenderer.flipX = true;
            isRunning = true;
            animator.SetBool("IsRunning", isRunning);
        }
        else if (isMovingRight)
        {
            rb.velocity = new Vector2(moveSpeed, rb.velocity.y);
            spriteRenderer.flipX = false;
            isRunning = true;
            animator.SetBool("IsRunning", isRunning);
        }
        else
        {
            rb.velocity = new Vector2(0f, rb.velocity.y);
            isRunning = false;
            animator.SetBool("IsRunning", isRunning);
        }

        // 动画状态更新
        isFalling = rb.velocity.y < 0f && !isJumping;
        animator.SetBool("IsFalling", isFalling);
        animator.SetBool("IsJumping", isJumping);
    }

    private void Jump()
    {
        rb.AddForce(new Vector2(0f, jumpForce), ForceMode2D.Impulse);
        isJumping = true;
        animator.SetTrigger("Jump");
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isJumping = false;
            animator.SetBool("IsJumping", isJumping);
        }
    }
}

额外说明

  • 事件绑定改为onPointerDown和onPointerUp后,按钮按下时会触发Down方法设置移动状态为true,抬起时触发Up方法设置为false,确保Update能正确读取当前输入状态。
  • 跳跃逻辑直接在按钮按下时触发,避免了原代码中状态被瞬间覆盖的问题,同时保留了仅在地面时才能跳跃的限制。
  • 松键停止功能通过Up方法重置移动状态,Update中检测到状态为false时将角色水平速度设为0,实现预期效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 05:03:13