0
\$\begingroup\$

I have a Unity mobile project where I am trying to use right/left movement using two UI buttons situated accordingly. The issue is that it only moves the player to the right/to the left one time, not continually when the player is holding the button down.

I'd like the player to be able to hold down a certain button and have the character move constantly in that direction until the button is released. I've tried making the void into a Coroutine, but nothing working works.

Here is my code. (rightCallable and leftCallable are attached to the buttons).

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
    
public class playerController : MonoBehaviour
{
    public GameObject player;
    public float speed = 1000f;
    public GameObject left;

    //this is so the player may also use the A and D keys if they want, and it works fine.
    public void Update()
    {
        var movement = Input.GetAxis("Horizontal");
        transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * speed;
    }

    //Below is what isn't working
    public void rightCallable ()
    {
        StartCoroutine("moveRight");
    }
    
    public void leftCallable ()
    {
        StartCoroutine("moveLeft");    
    }
    
    IEnumerator moveRight()
    {
        var movement = 1f;
        transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * speed;
        yield return null;
    }
    IEnumerator moveLeft ()
    {
        var movement = -1f;
        transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * speed;
        yield return null;
     }
 }
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Replace your code with something like this:

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

public class PlayerController : MonoBehaviour
{
    public GameObject player;
    public float speed = 1000f;
    public GameObject left;

    bool _isLeftHeld;
    bool _isRightHeld;

    public void Update()
    {
        var movement = Input.GetAxis("Horizontal");

        // Ignore cases where neither/both left and right are held at once.
        if (_isRightHeld ^ _isLeftHeld) {
            // Override the movement input from the keyboard/joypad.
            if (_isRightHeld) movement = 1f;
            else movement = -1f;
        }

        // Act on the movement input in just one place, following the DRY principle.
        transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * speed;
    }         

    public void HoldRight(bool held)
    {
        _isRightHeld = held;
    }

    public void HoldLeft(bool held)
    {
        _isLeftHeld = held;
    }
}

Then add an EventTrigger component to each on-screen button.

Add two event types to this component: Pointer Down (to detect a press), and Pointer Up (to detect a release). Optionally, you can also detect Pointer Exit and treat that like a release.

When pressed, call your HoldRight or HoldLeft function respectively, and tick the checkbox to send the argument true ("The button is held").

When released, call your HoldRight or HoldLeft function respectively, and leave the checkbox unticked to send the argument false ("The button is not held").

It'll look something a bit like this:

Inspector setup

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .