一. Unity实现虚拟摇杆及屏幕自适应功能

news2024/11/14 13:35:43

手游里面很多类型的游戏都需要用到遥感功能,例如王者荣耀,和平精英等,之前的摇杆功能都是用类似于Easy Touch的插件进行开发的,今天不借助任何插件来实现虚拟摇杆的功能。

在这里插入图片描述

一般虚拟摇杆的组成都是由轮盘和遥感的点组成,轮盘控制位移,限制在某个区域内,而点则是控制旋转,限制在轮盘内,因此需要用到的是Unity自带的UI事件,因此创建一个名为UIEventListener的类,去实现IPointerDownHandler,IPointerUpHandler,IDragHandler方法,通过事件监听回调来处理。

using UnityEngine;
using UnityEngine.EventSystems;

namespace CS
{
    [AddComponentMenu("UI/UIEventListener")]
    public class UIEventListener : MonoBehaviour,IPointerDownHandler,IPointerUpHandler,IDragHandler
    {
        public Action<PointerEventData> OnDownEvent;
        public Action<PointerEventData> OnUpEvent;
        public Action<PointerEventData> OnDargEvent;

        public static UIEventListener Get(GameObject go)
        {
            UIEventListener listener = null;
            if (go != null)
            {
                listener = go.GetComponent<UIEventListener>();
                if (listener == null)
                {
                    listener = go.AddComponent<UIEventListener>();
                }
            }
            return listener;
        }

        public void OnPointerDown(PointerEventData eventData)
        {
            OnDownEvent?.Invoke(eventData);
        }

        public void OnPointerUp(PointerEventData eventData)
        {
            OnUpEvent?.Invoke(eventData);
        }

        public void OnDrag(PointerEventData eventData)
        {
           OnDargEvent?.Invoke(eventData);
        }
    }

下面贴出完整代码,接下来对虚拟摇杆进行处理,监听这三个事件,其中mTouchMaxDir是虚拟摇杆的点距离轮盘中心的最大距离,也就是你遥感点能拉到多远,而由于在不同分辨率下,这个距离其实并非是固定的,因此就和我上一篇Unity实现经验条动态自适应一样,以实际画布的高比屏幕的高得到当前高的比值,然后乘以固定的最远拉伸距离,就能得到当前分辨率下的自适应拉伸距离。为了限制轮盘的位置,因此需要设置一张矩形的底图,将其aplha设置为0,表示轮盘可移动的范围。

在这里插入图片描述

在我们按下的时候,记录开始按下的位置,已经显示遥感点,将按下的位置赋值给轮盘,而抬起的时候,隐藏摇杆点,重置轮盘的位置,这个都很简单,然后我们在OnDrag拖拽事件中,首先我们得到遥感的方法,通过遥感的最终位置-开始位置 = 方向,由于我们遥感点是需要限定在轮盘内的,因此需要用距离来判断,因此通过方向的magnitude得到当前遥感点的距离,来判断是否超过我们之前设定的最大遥感距离,如果超出了就用 Vector2.ClampMagnitude(dir, mTouchMaxDir) API限制在这个mTouchMaxDir最大距离内,然后我们遥感点的位置就是我们开始位置+限制在最大距离的Dir ,如果没有超出就直接等于我们Drag传出的位置即可,这里的位置需要注意,都是postion,也就是世界坐标的位置,因为我们UIEvent事件中传出的eventData中的Position是世界坐标位置

    public class UI_MainCityPanel : View<UI_MainCityPanel, MainCityScene>
    {
        private Image mDirBgImg;
        private Image mDirPointImg;
         private Vector2 mStartPos = Vector2.zero;
        private Vector2 mDefaultPos = Vector2.zero;
        private float mTouchMaxDir;

         public override void IAwake()
        {
            base.IAwake();
            InitComponment();
            OnTouchEvent();
        }
         private void InitComponment()
        {
            mPowerImg = transform.Index<Image>("F_PowerImg");
            mDirBgImg= transform.Index<Image>("F_DirBg");
        }
          private void OnTouchEvent()
        {
            mTouchMaxDir = Screen.height * 1.0f / Consts.ScreenHeight * Consts.TouchPointMaxLen;
            mDirPointImg.SetActiveState(false);
            mUIEvtListener = UIEventListener.Get(gameObject);
            mUIEvtListener.OnDownEvent += (eventData =>
            {
                mStartPos = eventData.position;
                mDirPointImg.SetActiveState(true);
                mDirBgImg.transform.position = eventData.position;
            });
            mUIEvtListener.OnUpEvent += (eventData =>
            {
                mDirPointImg.transform.localPosition = mDefaultPos;
                mDirPointImg.SetActiveState(false);
                mDirBgImg.transform.localPosition = mDefaultPos;
            });
            mUIEvtListener.OnDargEvent += (eventData =>
            {
                Vector2 dir = eventData.position - mStartPos;
                float length = dir.magnitude;
                if (length > mTouchMaxDir)
                {
                    Vector2 clampDir = Vector2.ClampMagnitude(dir, mTouchMaxDir);
                    mDirPointImg.transform.position = mStartPos + clampDir;
                }
                else
                {
                    mDirPointImg.transform.position = eventData.position;
                }
            });
        }
}

下面看演示效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2118134.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二百六十二、Java——打开别人项目时缺少maven配置,无法运行文件

一、目的 在打开别人的项目时&#xff0c;发现Java文件类型显示出错&#xff0c;没有application&#xff0c;无法运行文件 二、报错原因 项目缺少maven配置 三、解决措施 File——Setting——Maven 修改Maven的配置&#xff0c;指向Maven路径 四、重启项目 文件恢复正常…

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(wa…

跨境外贸业务使用新加坡裸机云站群服务器优势

在全球化的今天&#xff0c;跨境外贸业务正变得越来越普遍。随着互联网技术的发展&#xff0c;越来越多的企业选择使用云计算服务来支持其国际业务。新加坡作为一个国际金融中心和亚洲的数据枢纽&#xff0c;提供了优质的网络基础设施&#xff0c;使其成为设置裸机云站群服务器…

【vue3|第28期】 Vue3 + Vue Router:探索路由重定向的使用与作用

日期&#xff1a;2024年9月8日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉在这里插入代码片得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对…

第18届世界杰出华人奖得主王傲山:承父业展关怀,体现“圆桌”精神

王傲山博士是“保二代”&#xff0c;由父亲言传身教及自孩提时代刻在骨子里的氛围&#xff0c;让他理所当然地传承父亲保险助人为乐的精神。在保险行业打滚两旬余&#xff0c;他成就多项傲人的成绩、取得个人成就的同时&#xff0c;以更高的指标作为团队精神&#xff0c;秉持追…

苹果手机qq原文件失效怎么恢复?4个方法,让失效变有效!

热门提问&#xff1a;在QQ上的文件忘记下载了&#xff0c;文件已经过期且无法打开&#xff0c;有什么方法可以恢复这些失效的文件呢&#xff1f; 小编这里有4个靠谱的方法&#xff0c;可以解决苹果手机QQ原文件失效怎么恢复的问题。只要大家掌握了这4个方法&#xff0c;让苹果…

【如何在鼠标右键添加Typora软件(使用脚本)】

下载Typora后&#xff0c;希望右键新建文件时候&#xff0c;可以新建md文件。 使用下面的注册脚本就可以实现&#xff1a; Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\.md] "Typora.md" "Content Type""text/markdown" "Per…

C语言---函数指针基础总结万字(4)

一、 函数 1.函数是一段可以重复执行的代码。 它可以接受不同的参数&#xff0c; 完成对应的操作。 下面的例子就是一个函数 int plus(int n) {return n; }上面的代码声明了一个函数plus()。 2.函数声明的语法有以下几点&#xff0c;需要注意。 返回值类型。 函数声明时&a…

Mac电脑IDEA2024安装后打不开问题解决

Mac电脑IDEA2024安装后打不开问题解决 由于电脑系统升级&#xff0c;导致我用的2019版本的IDEA一打开就卡&#xff0c;机缘巧合拥有了一个正版的IDEA账号&#xff0c;下载2024版本的IDEA&#xff0c;打开报错。 由于电脑系统升级&#xff0c;导致我用的2019版本的IDEA一打开就卡…

Day20_0.1基础学习MATLAB学习小技巧总结(20)——MATLAB绘图篇(3)

利用空闲时间把碎片化的MATLAB知识重新系统的学习一遍&#xff0c;为了在这个过程中加深印象&#xff0c;也为了能够有所足迹&#xff0c;我会把自己的学习总结发在专栏中&#xff0c;以便学习交流。 参考书目&#xff1a;《MATLAB基础教程 (第三版) (薛山)》 之前的章节都是…

项目实战系列三: 家居购项目 第五部分

&#x1f333;显示订单[订单管理] &#x1f333;暂时缺货 需求分析 1.如果某家居库存为0, 首页的"Add to Cart" 按钮显示为"暂时缺货" 2.后台也加上校验. 只有在 库存>0 时, 才能添加到购物车 代码实现 1.修改web/views/customer/index.jsp <c:if…

网络层 VIII(网络层设备——路由器)【★★★★★★】

一、冲突域与广播域 这里的“域”表示冲突或广播在其中发生并传播的区域。 1. 冲突域 冲突域是指连接到同一物理介质上的所有结点的集合&#xff0c;这些结点之间存在介质争用的现象&#xff08;能产生冲突的所有设备的集合&#xff09;。也就是说&#xff0c;若这些设备同时发…

ABeam德硕 | 海立集团BI项目正式启动,ABeam中国助力实现以数据之力驱动经营管理

9月2日&#xff0c;由德硕管理咨询&#xff08;上海&#xff09;有限公司作为实施合作伙伴的海立集团BI项目正式启动&#xff0c;海立集团党委书记、总经理缪骏、ABeam大中华区董事长兼总经理中野洋辅出席项目启动仪式。 ABeam大中华区董事长兼总经理中野洋辅 在致辞中表示&am…

【vue+el-table】表格操作列宽度跟随按钮个数自适应, 方法封装全局使用

效果图 以上图片分别代表不同用户权限下所能看到的按钮个数, 操作列宽度也会自适应宽度, 就不会一直处于最大宽度, 导致其他权限用户看到的页面出现大量留白问题. 目录 解决方法解决过程中可能出现的问题width赋值时为什么不放update()中btnDom为什么不能直接调用forEach为…

【网络原理】❤️Tcp 连接管理机制❤️ “三次握手” “四次挥手”的深度理解, 面试最热门的话题,没有之一, 保姆式教学 !!!

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

杰发科技Bootloader(3)—— 基于7801的APP切到Boot

为了方便在APP中跳转到Boot重新进行升级&#xff0c;有两种办法&#xff0c;7840同样可以使用。 1. 调用reset接口进行复位&#xff0c;复位后会先进Boot&#xff0c;再自动跳转到App。 NVIC_SystemReset(); 2. 直接使用跳转指令&#xff0c;参考Boot跳转到App代码&#xff0…

有哪些常用的企业统一门户?为何选择移动应用管理平台WorkPlus

企业统一门户是为了解决企业内部应用分散、管理繁琐的问题&#xff0c;提供集成化的应用平台&#xff0c;旨在提高员工的工作效率和便利性。而在众多的企业统一门户中&#xff0c;作为一款领先的移动应用管理平台&#xff0c;WorkPlus备受青睐。本文将介绍一些常用的企业统一门…

Sentinel 控制界面

一、下载 可视化jar 二、cmd 启动 jar java -Dserver.port8718 -Dcsp.sentinel.dashboard.server127.0.0.1:8718 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.2.jar 页面访问&#xff1a; http://localhost:8718/#/dashboard/

Elasticsearch Suggesters 自动补全长度设置

问题&#xff1a;在用户输入之后联想词返回长度默认为50&#xff0c;导致返回结果不完全 原因&#xff1a;completion 字段索引时允许存储的文本长度受 max_input_length 参数控制&#xff08;默认为 50 字符&#xff09;。可以在 mapping 中调整这个值 解决&#xff1a;“max…

【西电电装实习】焊接台组、焊接技巧

前言 工训中心 - 电装实习&#xff0c;进行实操的笔记 --- 一、焊台 二、焊枪大功率的握法&#xff08;反握法&#xff09; 三、余锡擦拭 四、pcb板与焊盘 五、焊接技巧 先加热焊盘&#xff0c;再上锡&#xff08;不能不加热焊盘&#xff0c;让锡往下漏&#xff09;上锡的时…