一、简单介绍
UGUI,是Unity自带的 GUI 系统,有别于 NGUI;使用 UGUI 也能制作出比较酷炫的效果 。
本节简单介绍实现 UGUI 按钮的 长按功能,以及Double Click 的功能。
二、实现原理
1、继承原有的UGUI 的 Button,组件
2、在 Button 的上面实现长按和双击事件
三、注意事项
1、长按和双击事件实现和原有的单击事件方法类似(目前不能显示的面板中,估计还有注意什么,知道的朋友可以留言啊(可能是继承 Button 子类已经有 UnityEvent (还是奇怪)),后面脚本有完全重写的Button 中面板有 onClick, onLongPress, onDoubleClick 事件)
2、触发双击的时候,可能总是会触发一次单击事件,顺序是先触发单击事件,之后双击事件触发(尝试了一些方法暂时没有方法在取消双击前的单击,知道的朋友留言哈)
四、效果预览
五、实现步骤
1、打开Unity,新建空工程
2、在场景中,简单布局场景,方便测试
3、新建脚本 MuButton,继承 Button,代码实现长按和双击效果的逻辑,并添加一个测试脚本,测试 MyButton 效果
4、移除Button 上的Button组件,添加 MyButton
5、添加测试脚本 TestMyButton
6、运行场景,测试效果如上
六、关键代码
1、MyButton.cs
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
/// <summary>
/// 我的自定义Button,继承 Button
/// </summary>
public class MyButton : Button
// 构造函数
protected MyButton()
my_onDoubleClick = new ButtonClickedEvent();
my_onLongPress = new ButtonClickedEvent();
// 长按
public ButtonClickedEvent my_onLongPress;
public ButtonClickedEvent OnLongPress
get { return my_onLongPress; }
set { my_onLongPress = value; }
// 双击
public ButtonClickedEvent my_onDoubleClick;
public ButtonClickedEvent OnDoubleClick
get { return my_onDoubleClick; }
set { my_onDoubleClick = value; }
// 长按需要的变量参数
private bool my_isStartPress = false;
private float my_curPointDownTime = 0f;
private float my_longPressTime = 0.6f;
private bool my_longPressTrigger = false;
void Update()
CheckIsLongPress();
#region 长按
/// <summary>
/// 处理长按
/// </summary>
void CheckIsLongPress() {
if (my_isStartPress && !my_longPressTrigger)
if (Time.time > my_curPointDownTime + my_longPressTime)
my_longPressTrigger = true;
my_isStartPress = false;
if (my_onLongPress != null)
my_onLongPress.Invoke();
public override void OnPointerDown(PointerEventData eventData)
// 按下刷新當前時間
base.OnPointerDown(eventData);
my_curPointDownTime = Time.time;
my_isStartPress = true;
my_longPressTrigger = false;
public override void OnPointerUp(PointerEventData eventData)
// 指針擡起,結束開始長按
base.OnPointerUp(eventData);
my_isStartPress = false;
public override void OnPointerExit(PointerEventData eventData)
// 指針移出,結束開始長按,計時長按標志
base.OnPointerExit(eventData);
my_isStartPress = false;
#endregion
#region 双击(单击)
public override void OnPointerClick(PointerEventData eventData)
//(避免已經點擊進入長按后,擡起的情況)
if (!my_longPressTrigger)
// 正常單擊
if (eventData.clickCount == 2 )
if (my_onDoubleClick != null)
my_onDoubleClick.Invoke();
}// 雙擊
else if (eventData.clickCount == 1)
onClick.Invoke();
#endregion
2、TestMyButton.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestMyButton : MonoBehaviour
public MyButton myButton;
// Start is called before the first frame update
void Start()
myButton.onClick.AddListener(()=> {
Debug.Log(" myButton.onClick");
myButton.OnDoubleClick.AddListener(() => {
Debug.Log(" myButton.OnDoubleClick");
myButton.OnLongPress.AddListener(() => {
Debug.Log(" myButton.OnLongPress");
// Update is called once per frame
void Update()
(注意:使用方法原有的Button一样)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using UnityEngine.Serialization;
using UnityEngine;
namespace XANTools
/// <summary>
/// 自己重写的 Button 按钮
/// 1、单击
/// 2、双击
/// 3、长按
/// </summary>
public class MyButtonXAN : Selectable, IPointerClickHandler, ISubmitHandler
[Serializable]
/// <summary>
/// Function definition for a button click event.
/// </summary>
public class ButtonClickedEvent : UnityEvent { }
// Event delegates triggered on click.
[FormerlySerializedAs("onClick")]
[SerializeField]
private ButtonClickedEvent m_OnClick = new ButtonClickedEvent();
protected MyButtonXAN()
public ButtonClickedEvent onClick
get { return m_OnClick; }
set { m_OnClick = value; }
private void Press()
if (!IsActive() || !IsInteractable())
return;
UISystemProfilerApi.AddMarker("Button.onClick", this);
m_OnClick.Invoke();
[Serializable]
/// <summary>
/// Function definition for a button click event.
/// </summary>
public class ButtonLongPressEvent : UnityEvent { }
[FormerlySerializedAs("onLongPress")]
[SerializeField]
private ButtonLongPressEvent m_onLongPress = new ButtonLongPressEvent();
public ButtonLongPressEvent onLongPress
get { return m_onLongPress; }
set { m_onLongPress = value; }
[FormerlySerializedAs("OnDoubleClick")]
public ButtonClickedEvent m_onDoubleClick = new ButtonClickedEvent();
public ButtonClickedEvent OnDoubleClick
get { return m_onDoubleClick; }
set { m_onDoubleClick = value; }
private bool my_isStartPress = false;
private float my_curPointDownTime = 0f;
private float my_longPressTime = 0.6f;
private bool my_longPressTrigger = false;
void Update()
CheckIsLongPress();
void CheckIsLongPress()
if (my_isStartPress && !my_longPressTrigger)
if (Time.time > my_curPointDownTime + my_longPressTime)
my_longPressTrigger = true;
my_isStartPress = false;
if (m_onLongPress != null)
m_onLongPress.Invoke();
public virtual void OnPointerClick(PointerEventData eventData)
//(避免已經點擊進入長按后,擡起的情況)
if (!my_longPressTrigger)
// 正常單擊
if (eventData.clickCount == 2)
if (m_onDoubleClick != null)
m_onDoubleClick.Invoke();
}// 雙擊
else if (eventData.clickCount == 1)
onClick.Invoke();
public virtual void OnSubmit(BaseEventData eventData)
Press();
// if we get set disabled during the press
// don't run the coroutine.
if (!IsActive() || !IsInteractable())
return;
DoStateTransition(SelectionState.Pressed, false);
StartCoroutine(OnFinishSubmit());
private IEnumerator OnFinishSubmit()
var fadeTime = colors.fadeDuration;
var elapsedTime = 0f;
while (elapsedTime < fadeTime)
elapsedTime += Time.unscaledDeltaTime;
yield return null;
DoStateTransition(currentSelectionState, false);
public override void OnPointerDown(PointerEventData eventData)
// 按下刷新當前時間
base.OnPointerDown(eventData);
my_curPointDownTime = Time.time;
my_isStartPress = true;
my_longPressTrigger = false;
public override void OnPointerUp(PointerEventData eventData)
// 指針擡起,結束開始長按
base.OnPointerUp(eventData);
my_isStartPress = false;
public override void OnPointerExit(PointerEventData eventData)
// 指針移出,結束開始長按,計時長按標志
base.OnPointerExit(eventData);
my_isStartPress = false;
Unity UI案例(长按按钮和双击按钮)
Unity中要实现自己得Button需要编写继承自UnityEngine的Button类,然后再重写按钮按下,抬起,和离开的方法(OnPointerDown,OnPointerUp,OnPointerExit),记录时间差就行了,具体实现看代码:
一:长按按钮实现:
public class LongClickButton : Button {
以下内容是根据Unity 2020.1.01f版本进行编写的
UGUI源代码之Button—长按按钮1、目的2、参考3、代码阅读4、准备修改UGUI源代码5、自定义实现长按按钮6、最终效果7、项目工程源代码
长按按钮应该是很常见也很实用的一个功能了吧,今天我们就来实现这个功能
本文参考Unity官方的UGUI源代码
Github地址:https://github.com/Unity-Technologies/uGUI
3、代码阅读
查看Button源代码(部分):
public
public class View_ATKNormalPress : StateMachineBehaviour {
// OnStateEnter is called when a transition starts a
Unity实现按钮Button多功能(长按,双击)。
今天在做游戏的时候突发奇想,为什么Unity只有单击捏?例如:以前的iPhone的Home键双击就是任务栏,单击就是回到主界面。那么在Unity应该也能实现吧(好像没什么关联。。。),毕竟现在很多游戏都存在双击的功能。于是我去网络上查找并学习了下,把心得写在这,方便大家可以参考参考。
既然我们需要手动写一个按钮,那么就需要去监听GameObject的点击事件。这里我设置了几个Public变量,并且实现了几个鼠标事件的接口,具体的代码如下:
还在用Update计时器实现各种流程控制和状态判断吗?今次介绍一下使用UnityEvents实现uGUI的长按状态检测。效果案例是我们常见的微信长按弹出菜单。
使用事件,首先需要添加引用。
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;在继承后面添加接口,用来获取UI状态。
public class ClickEventListener : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler
public static ClickEventListener Get(GameObject obj)
接下来便要实现双击功能,再次附上以前已写好的点击事件:using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSyste
虽然 UGUI 的 RectTransform 已经非常方便的可以帮助我们快速布局,但 UGUI 中还提供了很多可以帮助我们对 UI 控件进行自动布局的组件,他们可以帮助我们自动的设置 UI 控件的位置和大小等。 如果想做一些类似长按,双击,拖拽等功能是无法制作的,或者想让 Image 和 Text,RawImage 三大基础控件能够响应玩家输入也是无法制作的。 一般情况下布局元素的这些属性都是 0,但是特定的 UI 组件依附的对象布局属性会被改变,比如 Image 和 Text。