0

I tried to modify my code for it to be able to move the character by using UI buttons as I am making a mobile game. Before, the code looked incredible and worked, but since I tried to add the stop when the player released the button, it no longer works. There are no errors, but the character doesn't want to jump and move. I tried using ChatGPT to solve this problem, but he ran out of ideas and cycled the same codes. Here is his last written code that causes a problem:

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 bool isJumpButtonPressed = false;

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

        moveLeftButton.onClick.AddListener(OnMoveLeftButtonDown);
        moveLeftButton.onClick.AddListener(OnMoveLeftButtonUp);
        moveRightButton.onClick.AddListener(OnMoveRightButtonDown);
        moveRightButton.onClick.AddListener(OnMoveRightButtonUp);
        jumpButton.onClick.AddListener(OnJumpButtonDown);
        jumpButton.onClick.AddListener(OnJumpButtonUp);
    }

    public void OnMoveLeftButtonDown()
    {
        isMovingLeft = true;
    }

    public void OnMoveLeftButtonUp()
    {
        isMovingLeft = false;
    }

    public void OnMoveRightButtonDown()
    {
        isMovingRight = true;
    }

    public void OnMoveRightButtonUp()
    {
        isMovingRight = false;
    }

    public void OnJumpButtonDown()
    {
        isJumpButtonPressed = true;
    }

    public void OnJumpButtonUp()
    {
        isJumpButtonPressed = false;
    }

    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);
        }

        if (isJumpButtonPressed && !isJumping)
        {
            Jump();
        }

        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);
        }
    }
}

I debugged this code using Debug.Log and discovered that the

    public void OnMoveLeftButtonDown()
    {
        isMovingLeft = true;
    }

    public void OnMoveLeftButtonUp()
    {
        isMovingLeft = false;
    }

    public void OnMoveRightButtonDown()
    {
        isMovingRight = true;
    }

    public void OnMoveRightButtonUp()
    {
        isMovingRight = false;
    }

    public void OnJumpButtonDown()
    {
        isJumpButtonPressed = true;
    }

    public void OnJumpButtonUp()
    {
        isJumpButtonPressed = false;
    }

Methods are working but not used in the Update method.

Are there any ideas to rewrite this code to work again and add a stop for a character when the player releases it? Thanks for any help!

NeoTech
  • 21
  • 5
  • are you sure the script is enabled? the script can be on a game object and disabled, it allows running of methods, but doesnt run all the updates etc. – BugFinder Jul 10 '23 at 18:33
  • Yes, I tested it just right now. It was enabled. Anyway, the movement worked before I tried to add movement with UI buttons. – NeoTech Jul 10 '23 at 18:42
  • ok, so no errors? or warnings?, what happens when you add debug statements to see what its doing? – BugFinder Jul 10 '23 at 18:45
  • I debugged the second box of code in this post. They were all working. But when I debugged the Update method, there was no response in the console. There are no errors or warnings, and everything seems to be ok. – NeoTech Jul 10 '23 at 18:48

1 Answers1

1

Issue

The issue you are facing is because you are registering on the same event twice in your Start function:

    private void Start()
    {
        //code
        moveLeftButton.onClick.AddListener(OnMoveLeftButtonDown);
        moveLeftButton.onClick.AddListener(OnMoveLeftButtonUp);
        //More code
    }

This will cause both methods to be triggered right as the button is pressed, causing then the reaction of always setting the isMovingLeft (for instance) to be false.

Solving

For the requested behaviour, I'd recommend you to not use the Button class from UI due to its limitation of reading its state as its main purpose is to fire 'onClick' events, whereas you're looking for something like IPointerUpHandler and IPointerDownHandler. To implement EventSystem interfaces is quite easy:

  1. Be sure to have an active GraphicsRaycaster component
  2. Be sure to have an active EventSystem GameObject (to create it, right-click on the Scene/Hierarchy then go to UI -> Event System and it shall be added properly)

Both can also be added by creating a Canvas on the scene, so if you have one, you'll probably be set (but worth to check).

Those interfaces shall then be implemented on an UI script of yours, this way you can manage custom UI such as joysticks

Breno W.
  • 46
  • 3
  • I solved this problem. I just created a separate script that uses the IPointerUpHandler and IPointerDownHandler—and referred to it in the CharacterController script in the Update method. Then I added this separate script to the Image, and now everything works perfectly. Thank you for being so helpful! – NeoTech Jul 11 '23 at 13:36
  • 1
    Glad to hear that you managed to solve it :) – Breno W. Jul 12 '23 at 14:33