按下 UI 按钮时连续运行代码 [英] Continuously run code while UI button pressed

查看:31
本文介绍了按下 UI 按钮时连续运行代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 Unity 中制作一个平台游戏,用三个按钮来移动球:

I am making a platform game in Unity, where the ball is moved with three buttons:

  • 向右移动
  • 左移
  • 跳跃

我现在已经拥有了所有可以使用的功能,但是要移动角色我需要不断发送一个按钮,而不是像我想要的那样按住它.我尝试了一些在教程中找到的方法,但由于我仍然是一个初学者,我没有设法使它们起作用.

I already have all the functions that work now, but to move the character i need to keep spamming a button, instead of holding it as i would want to. I have tried a few ways I found on tutorials but, as i am still a very beginner, i did not manage to make them work.

这是我的 Move2D 脚本代码附加到角色上:

This is the code of my Move2D script attatched to the character:

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

public class Move2D : MonoBehaviour
{
    public float moveSpeed = 5f;
    public bool isGrounded = false;

    [SerializeField] private Rigidbody2D rigidbody;

    private void Awake()
    {
        if (!rigidbody) rigidbody = GetComponent<Rigidbody2D>();
    }

    public void Jump()
    {
        if (isGrounded)
        {
            rigidbody.AddForce(new Vector3(0f, 5f), ForceMode2D.Impulse);
        }
    }

    public void Move(float value)
    {
        Vector3 movement = new Vector3(value, 0f, 0f);
        transform.position += movement * Time.deltaTime * moveSpeed;
    }
}

这是主要控制所有运动的第二个脚本:

And this is the second script that mainly controls all the movement:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class ContinuesButton : MonoBehaviour, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
{
    [SerializeField] private Button button;

    [SerializeField] private UnityEvent whilePressed;

    private readonly bool isHover;

    private void Awake()
    {
        if (!button) button = GetComponent<Button>();
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        StartCoroutine(WhilePressed());
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        StopAllCoroutines();
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        StopAllCoroutines();
    }

    private IEnumerator WhilePressed()
    {
        while (true)
        {
            whilePressed?.Invoke();
            yield return null;
        }
    }
}

任何信息或解释都非常感谢,因为这部分对我的游戏非常重要!:)

Any information or explanations is really appreciated as this part is very important for my game! :)

推荐答案

由于您的播放器有一个刚体,您可以通过刚体的速度而不是通过它的变换来移动播放器.
(这也使其更加一致,因为您的跳转实现使用了刚体)

Since your player has a rigidbody, you can move the player via the rigidbody's velocity rather than through it's transform.
(This makes it more consistent too, since your jump's implementation uses rigidbody)

速度由DirectionSpeed组成;由于速度是恒定的,您可以让按钮设置移动的方向.
并且由于您希望玩家按住按钮以移动,您可以设置移动的方向 OnPointerDown,并在 OnPointerUp 发生时重置它,如下所示:

Velocity is made out of Direction and Speed; Since speed is constant, You can make the button set the direction of the movement.
And since you would want the player to hold down the button in order to move, you can set the direction of the movement OnPointerDown, and reset it when OnPointerUp occurs, like so:

public class Move2D : MonoBehaviour {
    // ...

    [SerializeField]
    private float speed;

    private Rigidbody2D rigidBody;

    private Vector2 currentMoveDirection;

    private void Awake() {
        rigidBody = GetComponent<Rigidbody2D>();
        currentMoveDirection = Vector2.zero;
    }

    // ...

    private void FixedUpdate() {
        rigidBody.velocity = (currentMoveDirection + new Vector2(0f, rigidBody.velocity.y)).normalized * speed;
    }

    public void TriggerMoveLeft() {
        currentMoveDirection += Vector2.left;
    }

    public void StopMoveLeft() {
        currentMoveDirection -= Vector2.left;
    }

    public void TriggerMoveRight() {
        currentMoveDirection += Vector2.right;
    }

    public void StopMoveRight() {
        currentMoveDirection -= Vector2.right;
    }
}

PlayerMoveButton.cs

(或者你的ContinuesButton.cs)

public class PlayerMoveButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler {
    [SerializeField]
    private Button targetButton;

    [SerializeField, Tooltip("The targeted player's movement component")]
    private Move2D playerMovement;

    [SerializeField, Tooltip("True if this button moves the player to the left")]
    private bool movesLeft;

    // ...

    public void OnPointerDown(PointerEventData eventData) {
        if (movesLeft) {
            playerMovement.TriggerMoveLeft();
        } else {
            playerMovement.TriggerMoveRight();
        }
    }

    public void OnPointerUp(PointerEventData eventData) {
        if (movesLeft) {
            playerMovement.StopMoveLeft();
        } else {
            playerMovement.StopMoveRight();
        }
    }
}

示例:

LeftButton 现在被点击 (OnPointerDown),currentMoveDirection 设置为 Left (-1, 0).
松开按钮的那一刻 (OnPointerUp),currentMoveDirection 重置为正常 (0, 0)

LeftButton is now clicked (OnPointerDown), currentMoveDirection is set to Left (-1, 0).
The moment the button is let go (OnPointerUp), the currentMoveDirection is reset to normal (0, 0)

玩家通过currentMoveDirection * speed

编辑

并且为了保留 jump 运动,而不是简单地执行 currentMoveDirection * speed,您需要向其添加当前向上的方向,如下所示:

Edit

And in order to preserve the jump motion, rather than simply do currentMoveDirection * speed, you would need to add the current upwards direction to it, like so:

private void FixedUpdate() {
    rigidBody.velocity = (currentMoveDirection + new Vector2(0f, rigidBody.velocity.y)).normalized * speed;
}

这篇关于按下 UI 按钮时连续运行代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆