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

Unity屏幕触摸控制左右方向输入无响应问题排查求助

Unity触摸移动按钮无响应问题排查与解决

我是Unity新手,做屏幕触摸控制时,其他触摸按钮(跳跃、攻击)都正常工作,但控制角色移动的左右箭头输入完全无法被识别,试过在Move函数里调整speed参数也没解决问题。

相关脚本代码

PlayerMovement脚本

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

public class PlayerMovement : MonoBehaviour
{
    public ParticleSystem Dust;

    //Animation States
    const string IDLE_ANIMATION = "Idle_an";
    const string JUMP_ANIMATION = "Jump_an";
    const string RUN_ANIMATION = "Run_an";
    const string PICKAXE_ATTACK_ANIMATION = "Pickaxe_an";
    private float horizontal;
    public float speed = 5f;
    private float jumpingPower = 13f;
    private bool isFacingRight = true;
    private bool isJumpPressed;
    private bool isAttacking;
    private bool isAttackingPressed;

    public Transform attackHitBox;
    public float attackRange = 0.5f;
    public LayerMask enemyLayers;

    private float coyoteTime = 0.2f;
    private float coyoteTimeCounter;

    private float jumpBufferTime = 0.2f;
    private float jumpBufferCounter;

    public int damageToGive;
    
    [SerializeField] private Rigidbody2D rb;
    [SerializeField] private Transform groundCheck;
    [SerializeField] private LayerMask groundLayer;
    [SerializeField] private float attackDelay = 1f;
    Animator animator;
    private string currentState;
    void Start()
    {
        animator = GetComponent<Animator>();
    }

    // 让其他脚本可以访问Rigidbody
    public Rigidbody2D PlayerRigidbody
    {
        get { return rb; }
        set { rb = value; }
    }

    void Update()
    {
        Move(Input.GetAxisRaw("Horizontal")); 
        // 以下为原有的coyote time、jump buffer等逻辑
        if(isGrounded())
        {
            coyoteTimeCounter = coyoteTime;
        }else
        {
            coyoteTimeCounter -= Time.deltaTime;
        }
        
        if(Input.GetButtonDown("Jump"))
        {
            jumpBufferCounter = jumpBufferTime;
        }else
        {
            jumpBufferCounter -= Time.deltaTime;
        }

        if(jumpBufferCounter > 0f && coyoteTimeCounter > 0f)
        {
            isJumpPressed = true;
            rb.velocity = new Vector2(rb.velocity.x, jumpingPower);
            jumpBufferCounter = 0f;
        }

        if(Input.GetButtonUp("Jump") && rb.velocity.y > 0f)
        {
            rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * 0.5f);
            coyoteTimeCounter = 0f;
        }
          
        Flip();
    }

    public void Jump()
    {
        if(isGrounded())
        {
             isJumpPressed = true;
             rb.velocity = new Vector2(rb.velocity.x, jumpingPower);
        }
    }

    public void Move(float moveInput)
    {
         horizontal = moveInput; 
    }

    private void FixedUpdate()
    {
        rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);

        if(isGrounded() && !isAttacking){
            if(horizontal != 0f)
            {
                ChangeAnimationState(RUN_ANIMATION);
                CreateDust();
            }
            else if(horizontal == 0)
            {   
                ChangeAnimationState(IDLE_ANIMATION);
            }
        }

        if(isJumpPressed == true && !isGrounded() && !isAttacking){
            ChangeAnimationState(JUMP_ANIMATION);
        }

        if(isAttackingPressed)
        {
            isAttackingPressed = false;
            if(!isAttacking)
            {
                isAttacking = true;
                Attack();
            }
            Invoke("AttackComplete", attackDelay);
        }
    }

    public void PickAxe()
    {
        isAttackingPressed = true;
    }

    void Attack()
    {
        ChangeAnimationState(PICKAXE_ATTACK_ANIMATION);
        Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(attackHitBox.position, attackRange, enemyLayers);
        foreach(Collider2D enemy in hitEnemies)
        {
            Debug.Log("we hit" + enemy.name);
            enemy.GetComponent<EnemyHealthManager>().giveDamage(damageToGive);
        }
    }

    void OnDrawGizmosSelected()
    {
        if (attackHitBox == null)
            return;
        Gizmos.DrawWireSphere(attackHitBox.position, attackRange);
    }

    void AttackComplete()
    {
        isAttacking = false;
        if (isGrounded())
        {
            if (horizontal != 0f)
            {
                ChangeAnimationState(RUN_ANIMATION);
                CreateDust();
            }
            else
            {
                ChangeAnimationState(IDLE_ANIMATION);
            }
        }
        else
        {
            ChangeAnimationState(JUMP_ANIMATION);
        }
    }

    private bool isGrounded()
    {   
        return Physics2D.OverlapCircle(groundCheck.position, 0.1f, groundLayer);
    }

    private void Flip()
    {   
        if(isFacingRight && horizontal < 0f || !isFacingRight && horizontal > 0f)
        {
            isFacingRight = !isFacingRight;
            Vector3 localScale = transform.localScale;
            localScale.x *= -1f;
            transform.localScale = localScale;
        }
    }

    void ChangeAnimationState(string newState)
    {
        if (currentState == newState) return;
        animator.Play(newState);
        currentState = newState;
    }

    void CreateDust()
    {
        Dust.Play();
    }
}

TouchControls脚本

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

public class TouchControls : MonoBehaviour
{
    private PlayerMovement thePlayer;
    void Start()
    {
        thePlayer = FindObjectOfType<PlayerMovement>();
    }

    public void LeftArrow()
    {
        thePlayer.Move(-1);
    }

    public void RightArrow()
    {
        thePlayer.Move(1);
    }

    public void UnpressedArrow()
    {
        thePlayer.Move(0);
    }

    public void PickAxe_Attack()
    {
        thePlayer.PickAxe();
    }

    public void JumpButton()
    {
        thePlayer.Jump();
    }
}

问题原因与修复

核心问题

PlayerMovement的Update方法里,每帧都会调用Move(Input.GetAxisRaw("Horizontal")),这会直接覆盖触摸按钮设置的horizontal值。比如你点右箭头把horizontal设为1,但下一帧Update又把它改成键盘输入的0(没按键盘的话),导致角色根本没法持续移动。

修复步骤

  1. 修改PlayerMovement的Update方法,调整键盘输入逻辑,避免干扰触摸控制:
void Update()
{
    // 只在有键盘水平输入时才更新,不覆盖触摸设置的值
    float keyboardInput = Input.GetAxisRaw("Horizontal");
    if(keyboardInput != 0)
    {
        Move(keyboardInput);
    }

    // 以下保留原有的coyote time、jump buffer等逻辑,无需改动
    if(isGrounded())
    {
        coyoteTimeCounter = coyoteTime;
    }else
    {
        coyoteTimeCounter -= Time.deltaTime;
    }
    
    if(Input.GetButtonDown("Jump"))
    {
        jumpBufferCounter = jumpBufferTime;
    }else
    {
        jumpBufferCounter -= Time.deltaTime;
    }

    if(jumpBufferCounter > 0f && coyoteTimeCounter > 0f)
    {
        isJumpPressed = true;
        rb.velocity = new Vector2(rb.velocity.x, jumpingPower);
        jumpBufferCounter = 0f;
    }

    if(Input.GetButtonUp("Jump") && rb.velocity.y > 0f)
    {
        rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * 0.5f);
        coyoteTimeCounter = 0f;
    }
          
    Flip();
}
  1. 确认触摸按钮事件绑定:

    • 左右箭头按钮的On Pointer Down分别绑定到TouchControls的LeftArrow和RightArrow方法
    • 按钮的On Pointer Up和On Pointer Exit都绑定到UnpressedArrow方法,确保松开/移出按钮时角色停止移动
  2. 可选验证操作:

    • 在PlayerMovement的Move函数中添加Debug.Log("当前horizontal值:" + horizontal);,运行后点击触摸按钮,查看控制台输出确认事件是否触发
    • 在TouchControls的Start方法中添加Debug.Log(thePlayer);,确认是否成功获取到PlayerMovement组件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 14:58:07