Unity 进阶 之 简单模仿鼠标交互(场景:手机屏幕当做触摸板Touch Pad,移动鼠标,鼠标确定等操作)

目录

Unity 进阶 之 简单模仿鼠标交互(场景:手机屏幕当做触摸板Touch Pad,移动鼠标,鼠标确定等操作)

一、简单介绍

二、实现原理

三、注意事项

四、效果预览

五、实现步骤

六、关键代码


一、简单介绍

Unity中的一些知识点整理。

本节简单介绍在Unity开发中的,因为项目的开发需要,需要把手机屏幕当做触控板,模拟鼠标移动和点击交互等,所以这里简单的整理一些,或许场景不同,你可能需要进行屏幕适配,这里仅供参考学习使用,如果你有新的方式也可以留言,多谢。

二、实现原理

1、这里使用 Input.GetMouseButtonDown(0) 、Input.GetMouseButton(0) 、Input.GetMouseButtonUp(0) 相关事件来获取位置相关信息进行处理,用来当做UI射线交互的位置

2、获取当前的 UI 的 EventSystem,然后进行对应改写,关键代码如下

m_eventSystem = EventSystem.current; // 获取当前的 EventSystem
m_pointerEvent = new PointerEventData(m_eventSystem);
m_pointerEvent.button = PointerEventData.InputButton.Left;

m_pointerEvent.position = mFunPointerPos != null ? mFunPointerPos.Invoke() : new Vector2(Screen.width * 1 / 2, Screen.height / 2); // 这里就是模拟鼠标位置

List<RaycastResult> raycastResults = new List<RaycastResult>();
m_eventSystem.RaycastAll(m_pointerEvent, raycastResults);

三、注意事项

1、使用场景不同,可能需要做适当的屏幕适配

2、因为使用模拟鼠标交互,EventSystem 上默认的 Standalone Input Module 最好移除或者禁用,不然可能影响模拟的鼠标交互操作

3、可能有些情况模拟的鼠标会被遮住,你可以进行对应处理,可以调整UI层级,可以换种方式显示模拟鼠标,可以添加材质调整渲染队列,等

四、效果预览

五、实现步骤

1、打开 Unity ,新建空工程

2、布置场景,一个是模拟的鼠标点,一些事交互控件

3、创建脚本,编写对应的逻辑代码,实现对应功能,IMouseGesturePointerCallback 回调接口,MousePointerMoveWrapper 鼠标位置,ScreenRayRaycasterUIWrapper 获取改写EventSystem当前的UI交互等等

4、 把脚本挂载到场景中,并对应把模拟的鼠标赋值,如图

5、这里Button 设置如下,并挂载一个脚本,用来点击交互,计数使用,方便效果演示

6、EventSystem 上默认的 Standalone Input Module 最好移除或者禁用,不然可能影响模拟的鼠标交互操作

7、运行场景,点击屏幕,移动,就可看到对应鼠标移动,并能简单交互  ,效果如上

六、关键代码

1、TestMousePointerInteraction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;namespace XANUtil { public class TestMousePointerInteraction : MonoBehaviour,IMouseGesturePointerCallback{public RectTransform PointerImageRectTrans;private MousePointerMoveWrapper mMousePointerMoveWrapper = new MousePointerMoveWrapper();private ScreenRayRaycasterUIWrapper mScreenRayRaycasterUIWrapper = new ScreenRayRaycasterUIWrapper();void Start(){Init();}void Update(){if (mMousePointerMoveWrapper != null){mMousePointerMoveWrapper.Update();}if (mScreenRayRaycasterUIWrapper != null){mScreenRayRaycasterUIWrapper.Update();}}void Init(){if (mMousePointerMoveWrapper != null){// 把鼠标的位置传 Ray 发射位置mMousePointerMoveWrapper.Init(this);}if (mScreenRayRaycasterUIWrapper != null){// 把鼠标的位置传 Ray 发射位置mScreenRayRaycasterUIWrapper.Init(() => { return PointerImageRectTrans.anchoredPosition; });}}#region PointerImageRectTransvoid SetPointerImageRectTrans(Vector2 deltrPos){if (PointerImageRectTrans != null){Vector2 val = PointerImageRectTrans.anchoredPosition;val += ModifyPointerPos(deltrPos);PointerImageRectTrans.anchoredPosition = ClampValue(val);}}/// <summary>/// 根据需要做指针位置修正处理/// </summary>/// <param name="deltrPos"></param>/// <returns></returns>Vector2 ModifyPointerPos(Vector2 deltrPos){return deltrPos;}/// <summary>/// 显示指针位置/// </summary>/// <param name="val"></param>/// <returns></returns>Vector2 ClampValue(Vector2 val){val.x = val.x < 0 ? 0 : val.x;val.y = val.y < 0 ? 0 : val.y;val.x = val.x > Screen.width ? Screen.width : val.x;val.y = val.y > Screen.height ? Screen.height : val.y;return val;}#endregion#region Interface IMouseGesturePointerCallbackpublic void MousePointerMoveDeltraPos(Vector2 deltraPos){SetPointerImageRectTrans(deltraPos);}#endregion}
}

2、SimulationPointerButtonItem

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;namespace XANUtil { /// <summary>/// 简单的模拟指针选中的按钮脚本/// (可以不用这个,也可重写,仅做参考)/// </summary>public class SimulationPointerButtonItem : MonoBehaviour{private Button mBtn;private Text mBtnText;Action mOnClick;private int mCounter = 0;private void Awake(){Init(null);}public void Init(Action onClick){mBtn = this.GetComponent<Button>();mBtnText = this.GetComponentInChildren<Text>();mCounter = 0;mOnClick = onClick;mBtn.onClick.AddListener(OnClick);}public void OnClick(){mCounter++;mBtnText.text = mCounter.ToString();mOnClick?.Invoke();}}
}

3、ScreenRayRaycasterUIWrapper

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;namespace XANUtil { public class ScreenRayRaycasterUIWrapper {// Prevents loop over the same selectableSelectable m_excluded;Selectable m_currentSelectable = null;RaycastResult m_currentRaycastResult;IPointerClickHandler m_clickHandler;IDragHandler m_dragHandler;EventSystem m_eventSystem;PointerEventData m_pointerEvent;Func<Vector2> mFunPointerPos;private bool mIsClick = false;private bool mIsSwipe = false;private bool mIsDrag = false;private Vector2 oldPos;private Vector2 lastPos;private const float MOVE_LENGTH_LIMIT = 10;public void Init(Func<Vector2> funPointerPos){m_eventSystem = EventSystem.current;m_pointerEvent = new PointerEventData(m_eventSystem);m_pointerEvent.button = PointerEventData.InputButton.Left;mFunPointerPos = funPointerPos;}public void Update(){// 没有数据屏幕中心(即为 width * 3/4,height * 1/2)// Set pointer positionm_pointerEvent.position = mFunPointerPos != null ? mFunPointerPos.Invoke() : new Vector2(Screen.width * 1 / 2, Screen.height / 2);List<RaycastResult> raycastResults = new List<RaycastResult>();m_eventSystem.RaycastAll(m_pointerEvent, raycastResults);// Detect selectableif (raycastResults.Count > 0){foreach (var result in raycastResults){var newSelectable = result.gameObject.GetComponentInParent<Selectable>();if (newSelectable){if (newSelectable != m_excluded && newSelectable != m_currentSelectable){Select(newSelectable);m_currentRaycastResult = result;}break;}}}else{if (m_currentSelectable || m_excluded){Select(null, null);}}// Target is being activatingif (m_currentSelectable){if (m_clickHandler != null && Input.GetMouseButtonUp(0) && mIsSwipe == false){m_clickHandler.OnPointerClick(m_pointerEvent);Select(null, null);}else if (m_dragHandler != null && mIsClick /*&& mIsSwipe == false*/){mIsDrag = true;m_pointerEvent.pointerPressRaycast = m_currentRaycastResult;m_dragHandler.OnDrag(m_pointerEvent);}if (m_dragHandler == null){mIsClick = false;mIsSwipe = false;}if (m_clickHandler != null || m_dragHandler != null){if (Input.GetMouseButtonDown(0)){oldPos = Input.mousePosition;mIsClick = true;}else if (Input.GetMouseButtonUp(0)){mIsSwipe = false;mIsClick = false;mIsDrag = false;Select(null, null);}else{lastPos = Input.mousePosition;mIsSwipe = JudgeISSwipe(oldPos, lastPos);}}}else{mIsClick = false;mIsSwipe = false;Select(null, null);}if (Input.GetMouseButtonUp(0)){mIsSwipe = false;mIsClick = false;mIsDrag = false;Select(null, null);}}/// <summary>/// 判断是否是缓动/// </summary>/// <param name="oldPos"></param>/// <param name="lastPos"></param>/// <returns></returns>private bool JudgeISSwipe(Vector2 oldPos, Vector2 lastPos){return Vector3.Distance(oldPos, lastPos) > MOVE_LENGTH_LIMIT;}/// <summary>/// 选择操作/// </summary>/// <param name="s"></param>/// <param name="exclude"></param>void Select(Selectable s, Selectable exclude = null){if (mIsDrag == true){return;}m_excluded = exclude;if (m_currentSelectable)m_currentSelectable.OnPointerExit(m_pointerEvent);m_currentSelectable = s;if (m_currentSelectable){m_currentSelectable.OnPointerEnter(m_pointerEvent);m_clickHandler = m_currentSelectable.GetComponent<IPointerClickHandler>();m_dragHandler = m_currentSelectable.GetComponent<IDragHandler>();}else{m_clickHandler = null;m_dragHandler = null;}}}
}

4、MousePointerMoveWrapper

using System.Collections;
using System.Collections.Generic;
using UnityEngine;namespace XANUtil { public class MousePointerMoveWrapper{private Vector2 mOldPos;private Vector2 mLastPos;private IMouseGesturePointerCallback mIMouseGesturePointerCallback;public void Init(IMouseGesturePointerCallback callback) {mIMouseGesturePointerCallback = callback;}public void Update(){if (Input.GetMouseButtonDown(0)){mOldPos = Input.mousePosition;}else if (Input.GetMouseButton(0)){mLastPos = Input.mousePosition;Vector2 deltaPosition = (mLastPos - mOldPos);mIMouseGesturePointerCallback?.MousePointerMoveDeltraPos(deltaPosition);mOldPos = mLastPos;}}}
}

5、IMouseGesturePointerCallback

using System.Collections;
using System.Collections.Generic;
using UnityEngine;namespace XANUtil
{ public interface IMouseGesturePointerCallback {void MousePointerMoveDeltraPos(Vector2 deltraPos);}
}

Unity 进阶 之 简单模仿鼠标交互(场景:手机屏幕当做触摸板Touch Pad,移动鼠标,鼠标确定等操作)相关推荐

  1. win10笔记本电脑将触摸板关了但是没有鼠标时怎么重新打开触摸板

    第一种,如果是通过快捷键"Fn + F11"(不同的电脑会有区别,F11上有触摸板的图标)关闭了触摸板,那就重新按一下快捷键"Fn + F11"打开触摸板. 第 ...

  2. Synaptics 触摸板驱动“连接外部USB鼠标自动禁用”注册表补丁

    以下内容 保存为reg文件双击导入即可 Windows Registry Editor Version 5.00[HKEY_CURRENT_USER\Software\Synaptics\SynTPE ...

  3. 鼠标交互的使用与优化

    无论是PC端的鼠标交互还是移动端的触摸交互,我们暂且都泛称为鼠标交互.这是游戏引擎实现人机交互的基础.本文从LayaAir引擎鼠标交互的基础使用开始(包括2D与3D),到进阶级的使用,进行全面介绍,希 ...

  4. 向日葵远程控制软件:死磕鼠标交互,远程桌面操作精确

    向日葵远程控制软件创新鼠标交互,手机远程桌面也能精细画图 远程桌面早已不是技术人员才会用的"专利",越来越多的设计师.摄影师.财务等各种人群都意识到远程办公的好处,何况现在手机也能 ...

  5. java 键盘鼠标交互_人机交互多样性-7种不需要鼠标和键盘的设备

    java 键盘鼠标交互 One of the most wonderful and least appreciated things about computers is diversity of d ...

  6. mac 苹果鼠标 magic mouse2 当触摸代替点击当触摸板教程

    本文解决 mac 苹果鼠标 magic mouse2 触摸代替点击,鼠标当触摸板教程 买了magic mouse2之后,发现官方不推荐使用触摸代替点击,我感觉很不爽,这不就是一个触摸板嘛,于是各种搜软 ...

  7. win10专业版没有触摸板选项_win10鼠标光标不见了触摸板没反应的具体解决办法...

    电脑在长时间的使用下难免会出现一些问题,近日就有使用win10系统的用户表示自己的电脑出现了鼠标光标不见了触摸板没反应的情况,我们该怎么解决呢?下面本文就为大家分享了关于win10鼠标光标不见了触摸板 ...

  8. 设置鼠标连接时触摸板禁用、Win10系统电脑触摸板使用方法总结

    连接鼠标,禁用触摸板的设置: 连接鼠标时,容易不小心碰到触摸板,使光标移出或内容滑动,可以禁用触摸板:点击电脑左下角的"设置"->在搜索框内输入"触摸板" ...

  9. Mac上鼠标滚轮方向是和Win相反的,系统中设置后触摸板的方向又跟着变了

    Mac上鼠标滚轮方向是和Win相反的,系统中设置后触摸板的方向又跟着变了 想让MacBook触摸板和非原生的鼠标滚轮方向一致可以使用第三方应用Scroll Reverser 来解决. Scroll R ...

最新文章

  1. Java在使用时需要注意那些问题_java使用String.split方法时要注意的问题
  2. 全球及中国水彩调色板行业销售前景与投资商机研究报告2022版
  3. 这样的奇技淫巧不可取,切记切记
  4. java读取.properties文件乱码
  5. 动态生成java类_Java 运行时动态生成class
  6. 病历管理系统V 1.0源码分享
  7. 计算机五笔打字口诀,快速学五笔打字技巧口决及方法
  8. pcb天线和纯铜天线_PCB天线和FPC天线有怎样的特性
  9. 工作组计算机如何设置文件共享,怎么设置办公室几台电脑文件共享?
  10. P3376 【模板】网络最大流
  11. SpringBoot的@Value注解设置默认值
  12. Python:批量修改图片的后缀名
  13. Don't let the things you own end up owing you
  14. GNU Screen的使用方法
  15. POJ 1637 混合图的欧拉回路判定
  16. 未越狱iPhone访问限制密码忘了怎么办
  17. 加州大学伯克利分校计算机科学专业,加州大学伯克利分校研究生计算机专业排名及申请...
  18. layui 表格隐藏id列
  19. tcpdump 网络抓包工具常用命令(转)
  20. Arthas性能监控

热门文章

  1. RAID磁盘冗余阵列
  2. Grbl limit.c代码分析
  3. 2019上半年软件设计师 下午真题-简答题及免费答案(一)
  4. 人工智能照进三百六十行:百度大脑与劳动者们
  5. 电商网站的mongodb设计
  6. 浏览器页面跟随鼠标滑轮变大变小
  7. 多个视频文件合成画中画效果(Python版)
  8. php网站 域名授权 怎么破,使用php进行域名授权代码 - 小俊学习网
  9. C++/C语言申请动态空间的详解【new关键字、malloc关键字、delete和free关键字】
  10. Lesson 52 A pretty carpet 漂亮的地毯