IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity 进阶 之 简单模仿鼠标交互(场景:手机屏幕当做触摸板Touch Pad,移动鼠标,鼠标确定等操作) -> 正文阅读

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

?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 PointerImageRectTrans

		void 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 IMouseGesturePointerCallback
		public 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 selectable
        Selectable 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 position
            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);

            // Detect selectable
            if (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 activating
            if (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);
	}
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-08-28 09:41:08  更:2021-08-28 09:41:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 8:08:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码