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(没按键盘的话),导致角色根本没法持续移动。
修复步骤
- 修改
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(); }
确认触摸按钮事件绑定:
- 左右箭头按钮的
On Pointer Down分别绑定到TouchControls的LeftArrow和RightArrow方法 - 按钮的
On Pointer Up和On Pointer Exit都绑定到UnpressedArrow方法,确保松开/移出按钮时角色停止移动
- 左右箭头按钮的
可选验证操作:
- 在
PlayerMovement的Move函数中添加Debug.Log("当前horizontal值:" + horizontal);,运行后点击触摸按钮,查看控制台输出确认事件是否触发 - 在
TouchControls的Start方法中添加Debug.Log(thePlayer);,确认是否成功获取到PlayerMovement组件
- 在
内容的提问来源于stack exchange,提问作者ace brown
相关产品推荐
相关产品推荐

