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.pswp.cn/news/901602.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901602.shtml
英文地址,請注明出處:http://en.pswp.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;這是設計個網頁的基礎。文本格式化標記分為字體標記、文字修飾標記。字體標記和文字修飾標記包括對于字體樣式的一些特殊修改。段落格式化標記分為段落標記、換行記、水平分隔線標記等。…