Unity制作游戲自定義按鍵詳解
一、效果圖

二、布局
1.場(chǎng)景布局
創(chuàng)建一個(gè)Panel 創(chuàng)建三個(gè)cube,Panel地板 兩個(gè)cube設(shè)置一個(gè)綠色材質(zhì),調(diào)整Scale大小讓其成為柱子形狀,一個(gè)cube改名為player設(shè)置一個(gè)紅色材質(zhì),當(dāng)作玩家(用來(lái)演示操作的),修改相機(jī)位置就可以了。

2.設(shè)置面板布局
2.1新建一個(gè)空節(jié)點(diǎn)名字改為SetKeyPanle,修改屬性

2.2在SetKeyPanle下新建一個(gè)image,修改名字為root,調(diào)整大小,如下圖

2.3 在root下 新建Text ,修改名為T(mén)itle當(dāng)作標(biāo)題

2.4在root下新建Scroll View組件修改屬性

2.5 選擇Scroll View—>Viewport—>Content對(duì)象,添加Grid Layout Group組件并修改屬性

2.6 在上一步的Content下創(chuàng)建一個(gè)按鈕改名Item,然后在這個(gè)Item下在創(chuàng)建兩個(gè)Text,修改Item的Button組件屬性

兩個(gè)Text自己修改一下位置就好了,注意兩個(gè)Text在父物體的孩子子級(jí)不要搞錯(cuò)了,第一個(gè)Text是前進(jìn),第二個(gè)是W

弄好后在吧item復(fù)制3個(gè),有了Content的Grid Layout Group組件新建的item就不用布局了,他自動(dòng)給你排列了

三、腳本思路
我們需要一個(gè)移動(dòng)腳本(Player)、按鍵數(shù)據(jù)腳本(KeyItem)和設(shè)置面板腳本(SetKeyPanle),KeyItem腳本主要用于存儲(chǔ)按鍵信息和觸發(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; //按下的按鍵名稱(chēng)
Button btn; //開(kāi)啟按鈕
[SerializeField] KeyCode keyCode;//初始化按鍵 需要在面板自己選擇
void Start()
{
//獲取組件
key = transform.GetChild(1).GetComponent<Text>();//這里我用了子物體的孩子子級(jí)來(lái)獲取
btn = GetComponent<Button>();//按鈕就獲取他自己本身
}
}
將這個(gè)腳本賦值給item對(duì)象,我們?cè)诿姘逯性O(shè)置他的初始化按鍵

3.1.2添加修改key值、修改按鈕顏色、更新失敗還原按鍵名稱(chēng) 方法
//修改key值
void SetKeyItemValue()
{
//當(dāng)前有修改的key值
if (SetKeyPanle.GetIntance().CurrentKeyItem!=null)
{
return;
}
//當(dāng)前keyitem為空時(shí),就讓它等于自己
SetKeyPanle.GetIntance().CurrentKeyItem = this; //這個(gè)要從SetKeyPanle腳本獲取,是下面要講的
//當(dāng)前狀態(tài)改為true 這樣就可以修改按鍵了
SetKeyPanle.GetIntance().IsSet = true; //可修改 //這個(gè)要從SetKeyPanle腳本獲取,是下面要講的
SetBtnColor(new Color32(202, 138, 138, 255));//修改按鈕顏色
key.text = "";//修改的時(shí)候text值為空
}
//修改按鈕顏色
public void SetBtnColor(Color32 color)
{
btn.image.color = color; //修改顏色
}
//更新失敗還原按鍵名稱(chēng)
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; //按下的按鍵名稱(chēng)
Button btn; //開(kāi)啟按鈕
[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()
{
//當(dāng)前有修改的key值
if (SetKeyPanle.GetIntance().CurrentKeyItem!=null)
{
return;
}
//當(dāng)前keyitem為空時(shí),就讓它等于自己
SetKeyPanle.GetIntance().CurrentKeyItem = this; //這個(gè)要從SetKeyPanle腳本獲取,是下面要講的
//當(dāng)前狀態(tài)改為true 這樣就可以修改按鍵了
SetKeyPanle.GetIntance().IsSet = true; //可修改 //這個(gè)要從SetKeyPanle腳本獲取,是下面要講的
SetBtnColor(new Color32(202, 138, 138, 255));//修改按鈕顏色
key.text = "";//修改的時(shí)候text值為空
}
//修改按鈕顏色
public void SetBtnColor(Color32 color)
{
btn.image.color = color; //修改顏色
}
//更新失敗還原按鍵名稱(chēng)
public void Restore()
{
key.text = keyCode.ToString();
}
}
上面有幾個(gè)報(bào)錯(cuò)的句子先不管,寫(xiě)完SetKeyPanle腳本的對(duì)應(yīng)方法就沒(méi)錯(cuò)了。
2.SetKeyPanle腳本
這個(gè)腳本稍微復(fù)雜,因?yàn)檫壿嬏幚矶荚谶@里。腳本中有詳細(xì)解釋
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
//序列化按鍵節(jié)點(diǎn)
[Serializable]
public class KeyItemNode
{
public string keyName;//按鍵功能名稱(chēng)
public KeyItem keyItem; //按鍵item
}
public class SetKeyPanle : MonoBehaviour
{
KeyItem currentkeyItem=null; //當(dāng)前要修改的Item
//封裝 用于判定當(dāng)前是否有修改的按鈕 沒(méi)有為空
public KeyItem CurrentKeyItem { get => currentkeyItem; set => currentkeyItem = value; }
[SerializeField] List<KeyItemNode> keyItemList; //這個(gè)需要到面板賦值
Dictionary<string, KeyItem> keyItemDic; //字典存放 鍵值參數(shù) (玩家移動(dòng)要用,玩家腳本后面寫(xiě))
public Dictionary<string, KeyItem> KeyItemDic { get => keyItemDic; set => keyItemDic = value; } //封裝可以進(jìn)行外部調(diào)用
[SerializeField] Transform root; //面板節(jié)點(diǎn) 用于控制開(kāi)啟關(guān)閉面板 是上面創(chuàng)建設(shè)置面板UI SetKeyPanle下的root
//單例 這樣就可以獲取這個(gè)腳本的方法進(jìn)行使用了
static SetKeyPanle intance;
public static SetKeyPanle GetIntance()
{
return intance;
}
void Awake()
{
intance = this; //將自己賦值給intance
}
void Start()
{
keyItemDic = new Dictionary<string, KeyItem>();//初始化字典
//將存儲(chǔ)的按鍵值 添加到字典中
for (int i = 0; i < keyItemList.Count; i++)
{
keyItemDic.Add(keyItemList[i].keyName, keyItemList[i].keyItem);
}
ClosePanel(); //關(guān)閉設(shè)置面板
}
bool isCurrentOpenState = true; //當(dāng)前設(shè)置面板開(kāi)啟的狀態(tài) true 代表開(kāi)啟狀態(tài)
public bool IsCurrentOpenState { get => isCurrentOpenState; set => isCurrentOpenState = value; } //封裝可以進(jìn)行外部調(diào)用
void Update()
{
//按下esc鍵開(kāi)啟關(guān)閉設(shè)置面板
if (Input.GetKeyDown(KeyCode.Escape))
{
//判斷面板的開(kāi)啟狀態(tài)
if (isCurrentOpenState)
{
OpenPanel(); //開(kāi)啟面板
}
else
{
//判斷當(dāng)前是修改狀態(tài),但是你沒(méi)有按下按鍵修改而是直接esc退出時(shí),恢復(fù)上一次按鍵
if (isSet)
{
//關(guān)閉后恢復(fù)當(dāng)前修改鍵值
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;//獲取當(dāng)前事件
if (e != null && e.isKey && e.keyCode != KeyCode.None)
{
KeyCode currentKey = e.keyCode;
//當(dāng)前按鍵等于 ESC 時(shí) 恢復(fù)上一次按鍵
if (currentKey==KeyCode.Escape)
{
CurrentKeyItem.Restore();
return;
}
//判斷是否按鍵沖突
if (IsRepeat(currentKey))
{
Debug.Log("按鍵重復(fù)?。?);
CurrentKeyItem.Restore(); //還原按鍵名稱(chēng)
}
else
CurrentKeyItem.KeyCode = currentKey; //不重復(fù) 修改按鍵
CurrentKeyItem.SetBtnColor(new Color32(173, 173, 173, 255)); //還原顏色
IsSet = false;//不是修改狀態(tài)
CurrentKeyItem = null; //當(dāng)前沒(méi)有選擇按鍵item
}
}
}
//是否重復(fù) true 有重復(fù)
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 開(kāi)啟關(guān)閉面板
public void OpenPanel()
{
root.gameObject.SetActive(true);
}
public void ClosePanel()
{
root.gameObject.SetActive(false);
}
#endregion
}
將這個(gè)腳本拖到SetKeyPanle的UI上 設(shè)置keyItemList值和root對(duì)象。如下圖 :

3.player移動(dòng)腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
public class player : MonoBehaviour
{
public Text txt; //這個(gè)text是用來(lái)顯示你按下的按鍵名稱(chēng)的,你可以隨便創(chuàng)建在任何位置,只要賦值給他就好
public float speed = 10f; //定義一個(gè)速度
void Start()
{
}
void Update()
{
//沒(méi)有開(kāi)啟設(shè)置面板時(shí) 可移動(dòng)
if (SetKeyPanle.GetIntance().IsCurrentOpenState)
{
//前進(jìn)
if (Input.GetKey(SetKeyPanle.GetIntance().KeyItemDic["前進(jìn)"].KeyCode))
{
transform.Translate(Vector3.forward * Time.deltaTime * speed);
txt.text = "按下:" + SetKeyPanle.GetIntance().KeyItemDic["前進(jìn)"].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();
}
}
}
}
將這個(gè)腳本拖給player (場(chǎng)景中紅色cube)賦值

好的這樣我們的自定義按鍵功能就完成了,趕緊試試吧~~
以上就是Unity制作游戲自定義按鍵詳解的詳細(xì)內(nèi)容,更多關(guān)于Unity的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#中FormsAuthentication用法實(shí)例
這篇文章主要介紹了C#中FormsAuthentication用法實(shí)例,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-02-02
C#開(kāi)發(fā)的人臉左右相似度計(jì)算軟件源碼分析
這篇文章主要介紹了C#開(kāi)發(fā)的人臉左右相似度計(jì)算軟件,較為詳細(xì)的分析了相似度計(jì)算的相關(guān)原理與具體實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-04-04
c#異步操作async?await狀態(tài)機(jī)的總結(jié)(推薦)
這篇文章主要介紹了c#異步操作async?await狀態(tài)機(jī)的總結(jié),關(guān)于async和await每個(gè)人都有自己的理解,甚至關(guān)于異步和同步亦或者關(guān)于異步和多線程每個(gè)人也都有自己的理解,本文通過(guò)實(shí)例代碼詳細(xì)講解,需要的朋友可以參考下2023-02-02
C#基于TCP協(xié)議的服務(wù)器端和客戶(hù)端通信編程的基礎(chǔ)教程
這篇文章主要介紹了C#基于TCP協(xié)議的服務(wù)器端和客戶(hù)端通信編程的基礎(chǔ)教程,文中講解了C#中TCP編程主要相關(guān)的TcpListener類(lèi)與TcpClient類(lèi)用法,需要的朋友可以參考下2016-04-04
WPF+Canvas實(shí)現(xiàn)平滑筆跡的示例代碼
這篇文章主要介紹了如何利用WPF+Canvas實(shí)現(xiàn)平滑筆跡效果,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,需要的可以參考一下2022-09-09

