Unity制作游戲自定義按鍵詳解
一、效果圖
二、布局
1.場景布局
創(chuàng)建一個Panel 創(chuàng)建三個cube,Panel地板 兩個cube設(shè)置一個綠色材質(zhì),調(diào)整Scale大小讓其成為柱子形狀,一個cube改名為player設(shè)置一個紅色材質(zhì),當作玩家(用來演示操作的),修改相機位置就可以了。
2.設(shè)置面板布局
2.1新建一個空節(jié)點名字改為SetKeyPanle,修改屬性
2.2在SetKeyPanle下新建一個image,修改名字為root,調(diào)整大小,如下圖
2.3 在root下 新建Text ,修改名為Title當作標題
2.4在root下新建Scroll View組件修改屬性
2.5 選擇Scroll View—>Viewport—>Content對象,添加Grid Layout Group組件并修改屬性
2.6 在上一步的Content下創(chuàng)建一個按鈕改名Item,然后在這個Item下在創(chuàng)建兩個Text,修改Item的Button組件屬性
兩個Text自己修改一下位置就好了,注意兩個Text在父物體的孩子子級不要搞錯了,第一個Text是前進,第二個是W
弄好后在吧item復制3個,有了Content的Grid Layout Group組件新建的item就不用布局了,他自動給你排列了
三、腳本思路
我們需要一個移動腳本(Player)、按鍵數(shù)據(jù)腳本(KeyItem)和設(shè)置面板腳本(SetKeyPanle),KeyItem腳本主要用于存儲按鍵信息和觸發(fā)修改 具體修改功能在SetKeyPanle腳本中
1.KeyItem腳本
3.1.1 獲取組件 和 設(shè)置初始化按鍵
using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using UnityEngine; using System; public class KeyItem : MonoBehaviour { Text key; //按下的按鍵名稱 Button btn; //開啟按鈕 [SerializeField] KeyCode keyCode;//初始化按鍵 需要在面板自己選擇 void Start() { //獲取組件 key = transform.GetChild(1).GetComponent<Text>();//這里我用了子物體的孩子子級來獲取 btn = GetComponent<Button>();//按鈕就獲取他自己本身 } }
將這個腳本賦值給item對象,我們在面板中設(shè)置他的初始化按鍵
3.1.2添加修改key值、修改按鈕顏色、更新失敗還原按鍵名稱 方法
//修改key值 void SetKeyItemValue() { //當前有修改的key值 if (SetKeyPanle.GetIntance().CurrentKeyItem!=null) { return; } //當前keyitem為空時,就讓它等于自己 SetKeyPanle.GetIntance().CurrentKeyItem = this; //這個要從SetKeyPanle腳本獲取,是下面要講的 //當前狀態(tài)改為true 這樣就可以修改按鍵了 SetKeyPanle.GetIntance().IsSet = true; //可修改 //這個要從SetKeyPanle腳本獲取,是下面要講的 SetBtnColor(new Color32(202, 138, 138, 255));//修改按鈕顏色 key.text = "";//修改的時候text值為空 } //修改按鈕顏色 public void SetBtnColor(Color32 color) { btn.image.color = color; //修改顏色 } //更新失敗還原按鍵名稱 public void Restore() { key.text = keyCode.ToString(); }
3.1.3最終代碼
using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using UnityEngine; using System; public class KeyItem : MonoBehaviour { Text key; //按下的按鍵名稱 Button btn; //開啟按鈕 [SerializeField] KeyCode keyCode; public KeyCode KeyCode { get { return keyCode; } set { keyCode = value; //修改按鍵值 key.text = keyCode.ToString(); //修改按鍵面板要顯示的Text值 } } void Start() { key = transform.GetChild(1).GetComponent<Text>(); btn = GetComponent<Button>(); btn.onClick.AddListener(SetKeyItemValue); } //修改key值 void SetKeyItemValue() { //當前有修改的key值 if (SetKeyPanle.GetIntance().CurrentKeyItem!=null) { return; } //當前keyitem為空時,就讓它等于自己 SetKeyPanle.GetIntance().CurrentKeyItem = this; //這個要從SetKeyPanle腳本獲取,是下面要講的 //當前狀態(tài)改為true 這樣就可以修改按鍵了 SetKeyPanle.GetIntance().IsSet = true; //可修改 //這個要從SetKeyPanle腳本獲取,是下面要講的 SetBtnColor(new Color32(202, 138, 138, 255));//修改按鈕顏色 key.text = "";//修改的時候text值為空 } //修改按鈕顏色 public void SetBtnColor(Color32 color) { btn.image.color = color; //修改顏色 } //更新失敗還原按鍵名稱 public void Restore() { key.text = keyCode.ToString(); } }
上面有幾個報錯的句子先不管,寫完SetKeyPanle腳本的對應方法就沒錯了。
2.SetKeyPanle腳本
這個腳本稍微復雜,因為邏輯處理都在這里。腳本中有詳細解釋
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; //序列化按鍵節(jié)點 [Serializable] public class KeyItemNode { public string keyName;//按鍵功能名稱 public KeyItem keyItem; //按鍵item } public class SetKeyPanle : MonoBehaviour { KeyItem currentkeyItem=null; //當前要修改的Item //封裝 用于判定當前是否有修改的按鈕 沒有為空 public KeyItem CurrentKeyItem { get => currentkeyItem; set => currentkeyItem = value; } [SerializeField] List<KeyItemNode> keyItemList; //這個需要到面板賦值 Dictionary<string, KeyItem> keyItemDic; //字典存放 鍵值參數(shù) (玩家移動要用,玩家腳本后面寫) public Dictionary<string, KeyItem> KeyItemDic { get => keyItemDic; set => keyItemDic = value; } //封裝可以進行外部調(diào)用 [SerializeField] Transform root; //面板節(jié)點 用于控制開啟關(guān)閉面板 是上面創(chuàng)建設(shè)置面板UI SetKeyPanle下的root //單例 這樣就可以獲取這個腳本的方法進行使用了 static SetKeyPanle intance; public static SetKeyPanle GetIntance() { return intance; } void Awake() { intance = this; //將自己賦值給intance } void Start() { keyItemDic = new Dictionary<string, KeyItem>();//初始化字典 //將存儲的按鍵值 添加到字典中 for (int i = 0; i < keyItemList.Count; i++) { keyItemDic.Add(keyItemList[i].keyName, keyItemList[i].keyItem); } ClosePanel(); //關(guān)閉設(shè)置面板 } bool isCurrentOpenState = true; //當前設(shè)置面板開啟的狀態(tài) true 代表開啟狀態(tài) public bool IsCurrentOpenState { get => isCurrentOpenState; set => isCurrentOpenState = value; } //封裝可以進行外部調(diào)用 void Update() { //按下esc鍵開啟關(guān)閉設(shè)置面板 if (Input.GetKeyDown(KeyCode.Escape)) { //判斷面板的開啟狀態(tài) if (isCurrentOpenState) { OpenPanel(); //開啟面板 } else { //判斷當前是修改狀態(tài),但是你沒有按下按鍵修改而是直接esc退出時,恢復上一次按鍵 if (isSet) { //關(guān)閉后恢復當前修改鍵值 CurrentKeyItem.Restore(); } ClosePanel();//關(guān)閉面板 } isCurrentOpenState = !isCurrentOpenState; } } #region 按鍵修改 bool isSet = false; //是否可以修改 public bool IsSet { get => isSet; set => isSet = value; } void OnGUI() { //可以修改 if (isSet) { Event e = Event.current;//獲取當前事件 if (e != null && e.isKey && e.keyCode != KeyCode.None) { KeyCode currentKey = e.keyCode; //當前按鍵等于 ESC 時 恢復上一次按鍵 if (currentKey==KeyCode.Escape) { CurrentKeyItem.Restore(); return; } //判斷是否按鍵沖突 if (IsRepeat(currentKey)) { Debug.Log("按鍵重復?。?); CurrentKeyItem.Restore(); //還原按鍵名稱 } else CurrentKeyItem.KeyCode = currentKey; //不重復 修改按鍵 CurrentKeyItem.SetBtnColor(new Color32(173, 173, 173, 255)); //還原顏色 IsSet = false;//不是修改狀態(tài) CurrentKeyItem = null; //當前沒有選擇按鍵item } } } //是否重復 true 有重復 bool IsRepeat(KeyCode keyCode) { //循環(huán)查找是否有相同的按鍵 for (int i = 0; i < keyItemList.Count; i++) { if (keyItemList[i].keyItem.KeyCode== keyCode) { return true; } } return false; } #endregion #region 開啟關(guān)閉面板 public void OpenPanel() { root.gameObject.SetActive(true); } public void ClosePanel() { root.gameObject.SetActive(false); } #endregion }
將這個腳本拖到SetKeyPanle的UI上 設(shè)置keyItemList值和root對象。如下圖 :
3.player移動腳本
using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using UnityEngine; public class player : MonoBehaviour { public Text txt; //這個text是用來顯示你按下的按鍵名稱的,你可以隨便創(chuàng)建在任何位置,只要賦值給他就好 public float speed = 10f; //定義一個速度 void Start() { } void Update() { //沒有開啟設(shè)置面板時 可移動 if (SetKeyPanle.GetIntance().IsCurrentOpenState) { //前進 if (Input.GetKey(SetKeyPanle.GetIntance().KeyItemDic["前進"].KeyCode)) { transform.Translate(Vector3.forward * Time.deltaTime * speed); txt.text = "按下:" + SetKeyPanle.GetIntance().KeyItemDic["前進"].KeyCode.ToString(); } //后退 if (Input.GetKey(SetKeyPanle.GetIntance().KeyItemDic["后退"].KeyCode)) { transform.Translate(Vector3.back * Time.deltaTime * speed); txt.text = "按下:" + SetKeyPanle.GetIntance().KeyItemDic["后退"].KeyCode.ToString(); } //向左 if (Input.GetKey(SetKeyPanle.GetIntance().KeyItemDic["向左"].KeyCode)) { transform.Translate(Vector3.left * Time.deltaTime * speed); txt.text = "按下:" + SetKeyPanle.GetIntance().KeyItemDic["向左"].KeyCode.ToString(); } //向右 if (Input.GetKey(SetKeyPanle.GetIntance().KeyItemDic["向右"].KeyCode)) { transform.Translate(Vector3.right * Time.deltaTime * speed); txt.text = "按下:" + SetKeyPanle.GetIntance().KeyItemDic["向右"].KeyCode.ToString(); } } } }
將這個腳本拖給player (場景中紅色cube)賦值
好的這樣我們的自定義按鍵功能就完成了,趕緊試試吧~~
以上就是Unity制作游戲自定義按鍵詳解的詳細內(nèi)容,更多關(guān)于Unity的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
c#異步操作async?await狀態(tài)機的總結(jié)(推薦)
這篇文章主要介紹了c#異步操作async?await狀態(tài)機的總結(jié),關(guān)于async和await每個人都有自己的理解,甚至關(guān)于異步和同步亦或者關(guān)于異步和多線程每個人也都有自己的理解,本文通過實例代碼詳細講解,需要的朋友可以參考下2023-02-02C#基于TCP協(xié)議的服務器端和客戶端通信編程的基礎(chǔ)教程
這篇文章主要介紹了C#基于TCP協(xié)議的服務器端和客戶端通信編程的基礎(chǔ)教程,文中講解了C#中TCP編程主要相關(guān)的TcpListener類與TcpClient類用法,需要的朋友可以參考下2016-04-04