?開發程序的時候經常會出現更改操作方式的情況,這種時候就需要將操作模式以事件的方式注冊到管理輸入事件的類中,方便可以隨時切換和調用
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(){}