Unity开发框架:输入事件管理类

 开发程序的时候经常会出现更改操作方式的情况,这种时候就需要将操作模式以事件的方式注册到管理输入事件的类中,方便可以随时切换和调用

using System;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 记录鼠标事件的的结构体
/// </summary>
public struct InputMouseEvent
{/// <summary>/// 鼠标事件名称/// </summary>public string name;/// <summary>/// 鼠标左键按下事件/// </summary>public Action<bool> mouseDown;/// <summary>/// 鼠标左键抬起事件/// </summary>public Action<bool, Vector3> mouseUp;/// <summary>/// 鼠标左键拖拽事件/// </summary>public Action<bool,Vector3> mouseDrag;/// <summary>/// 鼠标右键按下事件/// </summary>public Action<bool> rightMouseDown;/// <summary>/// 鼠标右键抬起事件/// </summary>public Action<bool, Vector3> rightMouseUp;/// <summary>/// 鼠标右键抬起事件/// </summary>public Action<bool, Vector3> rightMouseDrag;/// <summary>/// 鼠标滚轮滚动事件/// </summary>public Action<bool,float> mouseScroll;/// <summary>/// 初始赋予事件名称的构造函数,赋予全部为空的事件,需要添加的事件在构造函数()后的{}大括号中添加/// </summary>/// <param name="name"></param>public InputMouseEvent(string name){this.name = name;mouseDown = b => { };mouseDrag = (b,v) => { };mouseUp = (b, v) => { };rightMouseDown = b => { };rightMouseUp = (b, v) => { };rightMouseDrag = (b, v) => { };mouseScroll = (b,flt) => { };}
}public class InputManager : MonoBehaviour
{private static InputManager main;public static InputManager Main{get{if (main == null){main = new GameObject("InputManager").AddComponent<InputManager>();main.Init();}return main;}}/// <summary>/// 保存的鼠标事件库,用来存放全部的鼠标事件,以字典的方式保存方便根据事件名称查找/// </summary>public Dictionary<string,InputMouseEvent> inputMouseEvent = new Dictionary<string, InputMouseEvent>();/// <summary>/// 保存的键盘点击事件库,用来存放全部的鼠标事件,以字典的方式保存方便根据事件名称查找/// </summary>public Dictionary<string, Dictionary<KeyCode, Action>> inputKeyDownEvent = new Dictionary<string, Dictionary<KeyCode, Action>>();/// <summary>/// 保存的键盘持续按下的事件库,用来存放全部的鼠标事件,以字典的方式保存方便根据事件名称查找/// </summary>public Dictionary<string, Dictionary<KeyCode, Action>> inputKeyEvent = new Dictionary<string, Dictionary<KeyCode, Action>>();/// <summary>/// 当前执行的鼠标事件/// </summary>InputMouseEvent runMouseEvent;/// <summary>/// 当前执行的键盘点击事件/// </summary>Dictionary<KeyCode, Action> runKeyDownEvent = new Dictionary<KeyCode, Action>();/// <summary>/// 当前执行的键盘持续按下事件/// </summary>Dictionary<KeyCode, Action> runKeyEvent = new Dictionary<KeyCode, Action>();bool dragMouse;bool dragRightMouse;Vector3 clickMousePos;Vector3 clickRightMousePos;List<string> mouseEventList = new List<string>();List<string> keyDownEventList = new List<string>();List<string> keyEventList = new List<string>();//先注册事件,然后调用这个方法传入想要执行的事件名,会自动覆盖上一个执行的事件public void ChangeInputEvent(string eventName){if (inputMouseEvent.ContainsKey(eventName)){mouseEventList.Add(eventName);}if (inputKeyDownEvent.ContainsKey(eventName)){keyDownEventList.Add(eventName);}if (inputKeyEvent.ContainsKey(eventName)){keyEventList.Add(eventName);}runMouseEvent = inputMouseEvent[mouseEventList[mouseEventList.Count - 1]];runKeyDownEvent = inputKeyDownEvent[keyDownEventList[keyDownEventList.Count - 1]];runKeyEvent = inputKeyEvent[keyEventList[keyEventList.Count - 1]];}//不想执行事件的时候,就调用这个方法解除执行,会自动执行上一个被覆盖的事件public void RemoveInputEvent(string eventName){mouseEventList.Remove(eventName);keyDownEventList.Remove(eventName);keyEventList.Remove(eventName);runMouseEvent = inputMouseEvent[mouseEventList[mouseEventList.Count - 1]];runKeyDownEvent = inputKeyDownEvent[keyDownEventList[keyDownEventList.Count - 1]];runKeyEvent = inputKeyEvent[keyEventList[keyEventList.Count - 1]];}void Init(){inputMouseEvent.Add("空", new InputMouseEvent("空"));inputKeyDownEvent.Add("空", new Dictionary<KeyCode, Action>());inputKeyEvent.Add("空", new Dictionary<KeyCode, Action>());ChangeInputEvent("空");}void Update(){//用来判断当前鼠标是否在UI上的神奇方法,目前先注释//bool pointEnter = BaseCanvas.Main.GetPointEnter();bool pointEnter = false;Ray ray = CameraController.Main.camera.ScreenPointToRay(Input.mousePosition);if (Input.GetMouseButtonDown(0)){clickMousePos = Input.mousePosition;if (!pointEnter) { dragMouse = true; }runMouseEvent.mouseDown(pointEnter);}if(Input.GetMouseButtonUp(0)){dragMouse = false;runMouseEvent.mouseUp(pointEnter, Input.mousePosition - clickMousePos);}if (dragMouse){//获取鼠标移动距离的时候可以使用pos.magnituderunMouseEvent.mouseDrag(pointEnter, Input.mousePosition - clickMousePos);}if (Input.GetMouseButtonDown(1)){clickRightMousePos = Input.mousePosition;if (!pointEnter) { dragRightMouse = true; }runMouseEvent.rightMouseDown(pointEnter);}if (Input.GetMouseButtonUp(1)){dragRightMouse = false;runMouseEvent.rightMouseUp(pointEnter, Input.mousePosition - clickRightMousePos);}if (dragRightMouse){//获取鼠标移动距离的时候可以使用pos.magnituderunMouseEvent.rightMouseDrag(pointEnter, Input.mousePosition - clickRightMousePos);}runMouseEvent.mouseScroll(pointEnter,Input.mouseScrollDelta.y);foreach (var item in runKeyDownEvent){if (Input.GetKeyDown(item.Key)){item.Value();}}foreach (var item in runKeyEvent){if (Input.GetKey(item.Key)){item.Value();}}}
}

下面是一个使用方法的案例:

    InputMouseEvent mouseEvent;Dictionary<KeyCode, Action> keyEvent = new Dictionary<KeyCode, Action>();void Init(){mouseEvent = new InputMouseEvent("编辑路径"){mouseDown = MouseDown,mouseUp = MouseUp,mouseDrag = MouseDrag,rightMouseDown = MouseDown,rightMouseUp = MouseUp,rightMouseDrag = MouseDrag,};keyEvent = new Dictionary<KeyCode, Action>{{ KeyCode.W , ClickW },{ KeyCode.S , ClickS },{ KeyCode.A , ClickA },{ KeyCode.D , ClickD },};InputManager.Main.inputMouseEvent.Add("编辑路径", mouseEvent);InputManager.Main.inputKeyEvent.Add("编辑路径", keyEvent);}void OnEnable(){InputManager.Main.ChangeInputEvent("编辑路径");}private void OnDisable(){InputManager.Main.RemoveInputEvent("编辑路径");}void MouseDown(bool pointEnter){}void MouseUp(bool pointEnter, Vector3 pos){}void MouseDrag(bool pointEnter,Vector3 pos){}void ClickW(){}void ClickS(){}void ClickA(){}void ClickD(){}

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

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

相关文章

【kind管理脚本-2】脚本使用说明文档 —— 便捷使用 kind 创建、删除、管理集群脚本

当然可以&#xff0c;以下是为你这份 Kind 管理脚本写的一份使用说明文档&#xff0c;可作为 README.md 或内部文档使用&#xff1a; &#x1f680; Kind 管理脚本说明文档 本脚本是一个便捷的工具&#xff0c;帮助你快速创建、管理和诊断基于 Kind (Kubernetes IN Docker) 的…

opencv常用边缘检测算子示例

opencv常用边缘检测算子示例 1. Canny算子2. Sobel算子3. Scharr算子4. Laplacian算子5. 对比 1. Canny算子 从不同视觉对象中提取有用的结构信息并大大减少要处理的数据量的一种技术&#xff0c;检测算法可以分为以下5个步骤&#xff1a; 噪声过滤&#xff08;高斯滤波&…

Token安全存储的几种方式

文章目录 1. EncryptedSharedPreferences示例代码 2. SQLCipher示例代码 3.使用 Android Keystore加密后存储示例代码1. 生成密钥对2. 使用 KeystoreManager 代码说明安全性建议加密后的几种存储方式1. 加密后采用 SharedPreferences存储2. 加密后采用SQLite数据库存储1. Token…

MySQL数据库表的约束类型和使用

表完整约束性 约束条件 说明 PRIMARY KEY (PK) 标识该字段为该表的主键&#xff0c;是可以唯一的标识记录&#xff0c;不可以为空 UNIQUENOT NULL (primary key) FOREIGN KEY (FK) 标识该字段为该表的外键&#xff0c;实现表与表之间的关联 (foreign key) NULL …

Java 线程详解 --线程概念、线程池、线程同步与安全机制

一、Java线程的概念 Java 线程的本质&#xff1a;每个线程对应一个操作系统线程&#xff0c;由操作系统调度。JVM 通过调用操作系统 API&#xff08;如 Linux 的 pthread&#xff09;创建线程。 关键点&#xff1a; • 用户态与内核态&#xff1a;线程调度依赖操作系统&#…

PCL 计算点云至平面距离(SIMD加速)

文章目录 一、简介二、实现代码三、实现效果一、简介 SIMD 是一种并行计算模型,其中“单指令”表示处理器在同一时刻执行相同的指令,而“多数据”则表示同一条指令操作多个数据元素(如数组中的多个元素或矩阵中的多个元素)。与传统的串行计算不同,SIMD 能够同时处理多个数…

Ubuntu 22.04 完美安装 ABAQUS 教程:从零到上手,解决兼容问题

教程概述与安装准备 本教程详细介绍了在 Ubuntu 22.04 系统上安装 ABAQUS 2023 及 ifort 2021 的步骤,并实现用户子程序的链接。教程同样适用于 ABAQUS 2021(需相应调整文件名和路径)以及 Ubuntu 18.04 至 22.04 系统,尽管未在所有版本上测试。需要注意的是,Intel 的 One…

Spark-TTS(Text-to-Speech):基于大语言模型的语音合成革新者!!!

Spark-TTS&#xff1a;基于大语言模型的语音合成革新者 &#x1f680; &#xff08;全称解析 核心特性 行业影响全解读&#xff09; 一、概念定义与技术定位 1. 英文全称 Spark-TTS: An Efficient LLM-Based Text-to-Speech Model • 关键词解析&#xff1a; • LLM-Based…

2025年十六届蓝桥杯Python B组原题及代码解析

相关试题可以在洛谷上测试用例&#xff1a; 2025 十六届 蓝桥杯 Python B组 试题 A&#xff1a;攻击次数 答案&#xff1a;103 print(103)代码&#xff1a; # 初始化敌人的血量 x 2025# 初始化回合数 turn 0# 模拟攻击过程 while x > 0:# 回合数加一turn 1# 第一个英…

Spring Boot项目中结合MyBatis实现MySQL的自动主从切换

原理解析 1. MySQL主从复制&#xff08;Master-Slave Replication&#xff09; 工作原理&#xff1a;MySQL主从复制通过二进制日志&#xff08;binary log&#xff09;来同步数据。主服务器记录所有更改操作到二进制日志中&#xff0c;从服务器读取这些日志并执行相应的SQL语…

【经验记录贴】使用配置文件提高项目的可维护性

mark一下。 整体修改前后如下&#xff1a; 课题&#xff1a; 在项目中有一个支持的文件类型的FILE_TYPE的定义&#xff0c; 这个是写死在主程序中&#xff0c;每次增加可以支持的文件类型的时候&#xff0c;都需要去修改主程序中这个FILGE_TYPE的定义。 主程序修改其实不太花时…

用DeepSeek AI高效制作专业PPT

在当今职场中,制作精美而有力的PPT是展示想法、汇报工作和赢得机会的关键技能。然而,许多人花费过多时间在格式调整和内容组织上,而非专注于核心信息的传达。DeepSeek AI作为新一代智能助手,能够帮助您将PPT制作效率提升300%,同时显著提高专业度。本文将详细介绍如何利用D…

【AI学习从零至壹】语⾔模型及词向量相关知识

语⾔模型及词向量相关知识 ⾃然语⾔处理简介⾃然语⾔理解&#xff08;NLU&#xff09;⾃然语⾔⽣成&#xff08;NLG&#xff09;发展趋势信息检索技术布尔检索与词袋模型基于相关性的检索 / TF-IDF举例&#xff1a; 语⾔模型 / Language Model神经⽹络语⾔模型Word2Vec训练⽅法…

15.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--如何拆分单体

单体应用&#xff08;Monolithic Application&#xff09;是指将所有功能模块集中在一个代码库中构建的应用程序。它通常是一个完整的、不可分割的整体&#xff0c;所有模块共享相同的运行环境和数据库。这种架构开发初期较为简单&#xff0c;部署也较为方便&#xff0c;但随着…

在ARM架构Mac上部署Python 3.12与Conda环境的全链路指南!!!

在ARM架构Mac上部署Python 3.12与Conda环境的全链路指南 &#x1f680; &#xff08;M1/M2芯片实测&#xff5c;含性能调优避坑手册&#xff09; &#x1f31f; 核心价值点 • 原生ARM支持&#xff1a;突破Rosetta转译的性能损耗 • 环境隔离&#xff1a;Conda虚拟环境管理多…

yml文件上传并映射到实体类

文章目录 功能背景功能需要前端开发组件选用组件嵌套和参数绑定上传逻辑示例 后端开发接收逻辑解析逻辑省流纯手动实现&#xff08;不建议&#xff09; 功能背景 开发一个配置文件解析功能&#xff0c;需要兼容老版本的配置文件。 功能需要 前端&#xff1a;两个配置文件分别…

ElasticSearch中常用的数据类型

一、映射 Elasticsearch中通过映射来指定字段的数据类型&#xff0c;映射方式有2种&#xff0c;静态映射和动态映射。 1.动态映射 使用动态映射时&#xff0c;无须指定字段的数据类型&#xff0c;Elasticshearch会自动根据字段内容来判断映射到哪个数据类型。 比如&#xff…

【神经网络结构的组成】深入理解 转置卷积与转置卷积核

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;《深度学习理论直觉三十讲》_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 …

CSS高度坍塌?如何解决?

一、什么是高度坍塌&#xff1f; 高度坍塌&#xff08;Collapsing Margins&#xff09;是指当父元素没有设置边框&#xff08;border&#xff09;、内边距&#xff08;padding&#xff09;、内容&#xff08;content&#xff09;或清除浮动时&#xff0c;其子元素的 margin 会…

Web前端开发——格式化文本与段落(上)

一、学习目标 网页内容的排版包括文本格式化、段落格式化和整个页面的格式化&#xff0c;这是设计个网页的基础。文本格式化标记分为字体标记、文字修饰标记。字体标记和文字修饰标记包括对于字体样式的一些特殊修改。段落格式化标记分为段落标记、换行记、水平分隔线标记等。…