有些游戏都会有这样一个需求,比如一个按钮点击可以进行攻击,长按又可以释放技能的需求。
我们做一个类似Button的组件,只需要挂载到相应的按钮上面,即可像Button一样注册长按事件。
1.我们新建一个脚本RepeatButton,继承接口IPointerDownHandler, IPointerUpHandler, IPointerExitHandler,获取相应的按下,抬起,结束等事件。
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
public class RepeatButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler
{
public Vector2 position;
public bool interactable = true;
public bool invokeOnce = false;//是否只调用一次
private bool hadInvoke = false;//是否已经调用过
public float interval = 0.1f;//按下后超过这个时间则认定为"长按"
private bool isPointerDown = false;
private float recordTime;
public UnityEvent onClickDown = new UnityEvent();//按下时调用
public UnityEvent onPress = new UnityEvent();//按住时调用
public UnityEvent onRelease = new UnityEvent();//松开时调用
void Start()
{
}
void OnDisable() {
isPointerDown = false;
}
void Update()
{
if ((invokeOnce && hadInvoke) || interactable == false) return;
if (isPointerDown)
{
if ((Time.time - recordTime) > interval)
{
onPress.Invoke();
hadInvoke = true;
}
}
}
public void OnPointerDown(PointerEventData eventData)
{
isPointerDown = true;
recordTime = Time.time;
position = eventData.position;
onClickDown.Invoke();
}
public void OnPointerUp(PointerEventData eventData)
{
isPointerDown = false;
hadInvoke = false;
position = eventData.position;
onRelease.Invoke();
}
public void OnPointerExit(PointerEventData eventData)
{
isPointerDown = false;
hadInvoke = false;
position = eventData.position;
//onRelease.Invoke();
}
public void RemoveAddListener()
{
onClickDown.RemoveAllListeners();
onPress.RemoveAllListeners();
onRelease.RemoveAllListeners();
}
}
2.然后我们在逻辑脚本上添加代码。
Button Btn;
bool isPress = false;
void Start () {
Btn.onClick.AddListener(ClickBtn);
Btn.GetComponent<RepeatButton>().onPress.AddListener(LongPress);
}
void OnDestroy()
{
Btn.onClick.RemoveListener(ClickBtn);
Btn.GetComponent<RepeatButton>().onPress.RemoveListener(LongPress);
}
/// <summary>
/// 点击
/// </summary>
private void ClickBtn()
{
if (isPress)
{
isPress = false;
return;
}
//TODO 点击逻辑
}
/// <summary>
/// 长按
/// </summary>
private void LongPress()
{
isPress = true;
//TODO 长按逻辑
}
我这里为什么没有注册长按抬起的事件?这是因为长按抬起之后会执行onClick点击事件,在抬起之后设置isPress=false并不能过滤到点击事件,所以我直接在点击事件里面判断isPress = true时就return了。