PointerEnter、PointerExit、PointerDown、PointerUp——鼠标点击物体,则开始旋转,鼠标离开或者松开物体,则停止旋转

〇、需求来源

  • 需求:鼠标点击手轮,则开始旋转(左键顺时针转,右键逆时针转),鼠标离开手轮或者鼠标松开手轮,则停止旋转。

  • 实现思路:

    • (1)这是一个手动轮,鼠标悬停在该物体上的时候,按下鼠标左键,它顺时针旋转,如果按下鼠标右键,它逆时针旋转。在轮子旋转的时候,即便鼠标没弹起,失去焦点,它也会停止旋转。
    • (2)也就是说:
      鼠标左键长按它------>顺时针转
      鼠标右键长按它------>逆时针转
      一旦松开鼠标,则手轮停止旋转。
      另外,即便没松开鼠标,如果鼠标离开手轮,手轮也停止旋转。
    • (3)一句话总结:鼠标点击手轮,则开始旋转,鼠标离开手轮或者鼠标松开手轮,则停止旋转。
  • 入口和出口事件:

    • (1)旋转入口:手轮被点击
    • (2)停止旋转的条件(出口):退出悬停 or 松开物体

一、对比这两组Pointer事件

事件类型 中文释义 核心逻辑
PointerDown 按下物体 逻辑起点:鼠标在物体碰撞体范围内按下。此时该物体会"捕获"指针,后续动作将与此物体绑定。
PointerUp 松开物体 逻辑终点 :此前按下的按键被松开。注意: 无论此时鼠标是否还在物体上方,事件都会发送给最初按下的那个物体。
PointerEnter 进入物体 视觉反馈:鼠标光标移动到物体碰撞体上方。
PointerExit 离开物体 视觉反馈:鼠标光标离开物体碰撞体范围。

二、PointerUp事件说明

它并不是单纯的【鼠标弹起】或者【鼠标松开】。

这个事件要发生,必须是前面发生过PointerDown事件,也就是说它俩是配对的。

鼠标在其它区域被按下,然后再移动到这个物体上弹起,也不会发生PointerUp事件。

三、PointerDown发生的时候,如何获取是左键还是右键

csharp 复制代码
//鼠标点击物体:左键 | 右键
leftWheel.OnEventTriggerAddListener(EventTriggerType.PointerDown, (data) =>
{
    if(data.button == PointerEventData.InputButton.Left)         //左键点了手轮物体
    {
        Debug.Log("【鼠标左键】点了【左边手轮】");
    }
    else if(data.button == PointerEventData.InputButton.Right)   //右键点了手轮物体
    {
        Debug.Log("【鼠标右键】点了【左边手轮】");
    }
});
csharp 复制代码
/// <summary>
/// 给一个GameObject添加一个EventTrigger的事件侦听,绑定一个Action方法,Action捕获PointerEventData
/// </summary>
/// <param name="obj"></param>
/// <param name="eventType"></param>
/// <param name="fn"></param>
public static void OnEventTriggerAddListener(this GameObject obj, EventTriggerType eventType, Action<PointerEventData> fn)
{
    Action<PointerEventData> unityAction = (data) => {fn(data); };

    //EventTrigger组件判空
    EventTrigger trigger = obj.GetComponent<EventTrigger>();
    if (!trigger)
    {
        trigger = obj.AddComponent<EventTrigger>();
    }

    //碰撞体判空     
    if (!obj.GetComponent<Collider>())
    {
        obj.AddComponent<MeshCollider>();
        Debug.LogWarning($"{obj}自动添加MeshCollider组件");
    }

    //添加侦听
    EventTrigger.Entry entry = new EventTrigger.Entry();
    entry.eventID = eventType;
    entry.callback.AddListener(data => unityAction.Invoke((PointerEventData)data));
    trigger.triggers.Add(entry);
}

四、测试脚本

csharp 复制代码
	/// <summary>
	/// 左手轮
	/// </summary>
	[SerializeField]
	[Header("左手轮")]
	public GameObject leftWheel;
	
    /// <summary>
    /// 鼠标是否悬停在左手轮上
    /// </summary>
    private bool isHoverLeft = false;

在Start里面绑定代码

csharp 复制代码
void Start()
{
    #region=====================脚本绑定=======================begin
    //光标【进入】【左边手轮】------光标悬停
    leftWheel.OnEventTriggerAddListener(EventTriggerType.PointerEnter, () =>
    {
        isHoverLeft = true;
        Debug.Log("【左边手轮】得着焦点");
    });

    //光标【退出】【左边手轮】------光标退出悬停
    leftWheel.OnEventTriggerAddListener(EventTriggerType.PointerExit, () =>
    {
        isHoverLeft = false;
        Debug.Log("【左边手轮】失去焦点");
    });

    //鼠标点击物体:左键 | 右键
    leftWheel.OnEventTriggerAddListener(EventTriggerType.PointerDown, (data) =>
    {
        if(data.button == PointerEventData.InputButton.Left)         //左键点了手轮物体
        {
            Debug.Log("【鼠标左键】点了【左边手轮】");
        }
        else if(data.button == PointerEventData.InputButton.Right)   //右键点了手轮物体
        {
            Debug.Log("【鼠标右键】点了【左边手轮】");
        }
    });

    //鼠标松开物体:鼠标弹起
    leftWheel.OnEventTriggerAddListener(EventTriggerType.PointerUp, (data) =>
    {           
        if (isHoverLeft) 
        {
            if (data.button == PointerEventData.InputButton.Left)         //左键点了手轮
            {
                Debug.Log("【鼠标左键】从【左边手轮】上弹起");
            }
            else if (data.button == PointerEventData.InputButton.Right)   //右键点了手轮
            {
                Debug.Log("【鼠标右键】从【左边手轮】上弹起");
            }
        }
        else
        {
            if (data.button == PointerEventData.InputButton.Left)         //左键点了手轮
            {
                Debug.Log("【鼠标左键】在【其它地方】弹起");
            }
            else if (data.button == PointerEventData.InputButton.Right)   //右键点了手轮
            {
                Debug.Log("【鼠标右键】在【其它地方】弹起");
            }
        }            
    });

    #endregion =================脚本绑定=======================end
}

测试结果:

相关推荐
mxwin1 天前
Unity Shader 半透明物体为什么不能写入深度缓冲?
unity·游戏引擎·shader
晚枫歌F1 天前
三层时间轮的实现
网络·unity·游戏引擎
咸鱼永不翻身1 天前
Lua脚本事件检查工具
unity·lua·工具
leo__5202 天前
单载波中继系统资源分配算法MATLAB仿真程序
算法·matlab·unity
努力长头发的程序猿2 天前
Unity使用ScriptableObject序列化资源
unity·游戏引擎
mxwin2 天前
Unity Shader 手写基于 PBR 的 URP Lit Shader 核心光照计算
unity·游戏引擎·shader
小贺儿开发2 天前
Unity3D 智能云端数字标牌系统
unity·阿里云·人机交互·视频·oss·广告·互动
魔士于安2 天前
Unity windows 同步 异步 打开文件文件夹工具
游戏·unity·游戏引擎·贴图·模型
魔士于安2 天前
unity lowpoly 风格 城市 建筑 道路 交通标志
游戏·unity·游戏引擎·贴图·模型
mxwin2 天前
Unity GPU Shader 性能优化指南
unity·游戏引擎·shader