您曾經(jīng)想設(shè)計自己的游戲控制器嗎?
在這個簡短的項目中,我們將構(gòu)建一個簡單的自定義游戲控制器,以與Unity游戲引擎一起使用。該控制器將由Arduino Uno供電,盡管您也可以使用該項目的眾多替代產(chǎn)品之一。我們還將創(chuàng)建一個基本的游戲,在該游戲中,您將使用控制器來避免物體掉落和減慢時間。
對于此項目,您將需要
Arduino或類似的微控制器
1 x 10k歐姆電阻
1 x瞬時開關(guān)
1 x電位計
連接線
面包板
Unity游戲引擎
Unity Asset Store中的Uniduino插件(30美元)
完成項目代碼,以防萬一您不想編寫它(不包括Uniduino插件)
這些東西大多數(shù)都可以在Arduino入門套件中找到。如果沒有入門工具包,請查看我們的指南,為您選擇最合適的指南。
您可以根據(jù)需要使控制器變得復(fù)雜,盡管在此示例中,我們將設(shè)置一個電位計和一個按鈕–非常適合控制簡單的街機(jī)游戲。
組裝控制器
設(shè)置面包板和Arduino,如這是我們將用作游戲控制器的圖像,盡管您也可以使用與DIY midi控制器幾乎完全相同的設(shè)置!

準(zhǔn)備Arduino
一旦一切都連接好,請通過USB連接Arduino。在Arduino Software IDE中,轉(zhuǎn)到工具》板和工具》端口,以選擇要使用的微控制器和端口。 Arduino IDE隨附了我們所需的草圖,您可以在文件》示例》固件》 StandardFirmata 下找到它。單擊“上載”,您就可以準(zhǔn)備就緒。
如果您是Arduino的新手,并且腦袋有點融化,請查看我們的初學(xué)者指南,以幫助您與計算機(jī)進(jìn)行良好的交談。
設(shè)置您的Unity項目
InUnity,打開 Window》 Asset Store 可以從Unity編輯器中訪問Unity的Asset Store。在資產(chǎn)商店中搜索Uniduino插件。這個插件將允許您在Unity內(nèi)部的Arduino引腳之間收發(fā)數(shù)據(jù)。在撰寫本文時,該插件的價格為30美元??梢栽诓毁徺I插件的情況下進(jìn)行此項目,盡管它相當(dāng)復(fù)雜,并且您可能會發(fā)現(xiàn)插件更方便。
此視頻來自插件創(chuàng)建者的幫助,帶您完成了所有功能的測試過程以及首次設(shè)置。請注意,您可能還必須在Windows上重置Unity編輯器。
我們可以使用同一測試面板來測試我們的控制器。將引腳D2設(shè)置為INPUT和Digital。再往下,將引腳A5設(shè)置為ANALOG。電位計和按鈕現(xiàn)在應(yīng)該在屏幕上的引腳號旁邊顯示值。進(jìn)步!

現(xiàn)在可以做一些我們可以控制的事情了
所以我們有一個控制器,但是我們應(yīng)該控制什么呢?好吧,可能性無窮無盡,但今天,我們將創(chuàng)建一個非常簡單的躲避游戲,以測試我們的新控制系統(tǒng)。我們將很快地完成游戲設(shè)置,因此,如果您是Unity引擎的新手,您可能會發(fā)現(xiàn)《 Unity游戲編程初學(xué)者指南》很有用。
我們將構(gòu)建一個非常基本的游戲,其中您的目標(biāo)是向左和向右避開球體以避免掉落立方體,這將利用您新創(chuàng)建的自定義控制器。
創(chuàng)建一個新場景并將Uniduino預(yù)制件從資產(chǎn)》 Uniduino》中拖動預(yù)制件進(jìn)入您的階層,然后將Uniduino預(yù)制件拖入層次結(jié)構(gòu)。
在Unity層次結(jié)構(gòu)中,單擊 Create》 Sphere ,然后使用檢查器中的“變換”選項卡將其移至底部。游戲畫面。

現(xiàn)在該開始編碼了。
現(xiàn)在要向此聚會添加一些代碼。在“層次結(jié)構(gòu)”中選擇球體后,點擊其Inspector窗口底部的添加組件》新腳本。將其命名為 sphereMover ,然后從下拉菜單中選擇 C Sharp 。點擊創(chuàng)建并添加,腳本將被添加到GameObject中。雙擊它以打開腳本并輸入以下代碼:
using UnityEngine;
using System.Collections;
using Uniduino;
public class sphereMover : MonoBehaviour
{
//Headers aren‘t scrictly neccesary, but they make life easier back in the Inspector.
[Header(“Arduino Variables”)]
//we need to declare the Arduino as a variable
public Arduino arduino;
//we need to declare an integer for the pin number of our potentiometer,
//making these variables public means we can change them in the editor later
//if we change the layout of our arduino
public int potPinNumber;
//a float variable to hold the potentiometer value (0 - 1023)
public float potValue;
//we will later remap that potValue to the y position of our capsule and hold it in this variable
public float mappedPot;
//public int for our button pin
public int buttonPinNumber;
[Header(“Sphere Variables”)]
//variables to hold the values we noted earlier for the sides of our screen
public float leftEdge;
public float rightEdge;
// Use this for initialization
void Start ()
{//and initialize we shall, starting with the Arduino Variable.
//we are only using one arduino, so we can use Arduino.global to grab it.
arduino = Arduino.global;
arduino.Setup(ConfigurePins);
}
void ConfigurePins()
{
//configure the Arduino pin to be analog for our potentiometer
arduino.pinMode(potPinNumber, PinMode.ANALOG);
//Tell the Arduino to report any changes in the value of our potentiometer
arduino.reportAnalog(5, 1);
//configure our Button pin
arduino.pinMode(buttonPinNumber, PinMode.INPUT);
arduino.reportDigital((byte)(buttonPinNumber / 8), 1);
}
}
花點時間通讀代碼注釋。到目前為止,我們已經(jīng)為Arduino,其引腳和Sphere聲明了一些變量。我們還使用了
Start和ConfigurePins方法在運(yùn)行時初始化Arduino。保存腳本,然后返回Unity編輯器,看看有什么更改。

我們現(xiàn)在可以在Inspector窗口中看到我們的公共變量。讓我們看看我們在現(xiàn)階段可以輸入什么以幫助我們以后。我們早先知道我們在Arduino上使用的是什么引腳,我們可以輸入它們。我們還從實驗中更早地知道了我們希望球體能夠左右移動的距離,以使其不會從屏幕上掉落?,F(xiàn)在讓我們輸入這些值。

最初的生命跡象
是時候在Unity Editor中實際查看來自Arduino的值了。現(xiàn)在,我們可以在sphereMover腳本的Update函數(shù)中添加一行代碼,然后再次保存該腳本。
void Update ()
{
//We assign the value the arduino is reading from our potentionmeter to our potValue variable
potValue = arduino.analogRead(potPinNumber);
}
現(xiàn)在,我們的potValue變量每幀都會更新一次。 ,我們可以在Unity Inspector中實時看到它的價值。在進(jìn)行測試之前,現(xiàn)在是時候檢查Uniduino插件是否在正確的端口上進(jìn)行偵聽。在層次結(jié)構(gòu)中單擊Uniduino,然后在檢查器中檢查它的端口名稱。如果為空白,請為您的Arduino輸入正確的端口號。在這種情況下,它是COM4,盡管它可能與您有所不同。如果不確定,請檢查使用Arduino IDE。

在層次結(jié)構(gòu)中選擇球體,然后單擊屏幕頂部的“播放”按鈕。系統(tǒng)需要幾秒鐘的初始化時間,此后您應(yīng)該在移動電位器時開始在檢查器中看到Pot Value變量的變化。

現(xiàn)在我們正在交談!好吧,嚴(yán)格來說,Unity和Arduino在說話,但是誰在數(shù)呢?如果您到此為止并且在檢查器中看不到值的變化,請檢查設(shè)置步驟,并確保為Arduino選擇了正確的端口。
讓我們移動這個球體
現(xiàn)在我們已經(jīng)更新了potValue變量,我們想使用該值來移動我們的球體。當(dāng)電位計完全移到左側(cè)時,我們希望球體位于屏幕的左側(cè),反之亦然。 Unity中的對象位于Vector空間中的某個點,該點由其Transform.position的值確定。在下面的圖像中,球體在我們想要的最左邊的位置,您可以看到它的位置向量是9.5,-4,0。

我們想影響球體的X位置。不幸的是,直接使用電位器的值將不起作用,因為當(dāng)電位器一直向左移動時,其值為0,這會使我們的球體位于屏幕中間。在另一個極端,電位器的最高值1023將使立方體遠(yuǎn)離屏幕的右側(cè)。沒用。我們需要的是一些數(shù)學(xué)。
為什么Unity會為您做數(shù)學(xué)?
對于那些在那里的人,他們害怕地盯著一張無意義數(shù)字覆蓋的紙(盡管有一些很棒的網(wǎng)站可以幫助您學(xué)習(xí)數(shù)學(xué)),但不要害怕。我們需要一種使電位計值與球體的X位置相對應(yīng)的方法。幸運(yùn)的是,我們可以使用擴(kuò)展方法。
擴(kuò)展方法是為我們完成特定工作的腳本。在這種情況下,我們給它提供我們擁有的值,并返回它們之間的映射關(guān)系,以便在我們的 sphereMover 腳本中使用。在“項目”面板的頂部,單擊創(chuàng)建》 C#腳本,并將其命名為ExtensionMethods。在腳本中輸入以下代碼:
using UnityEngine;
using System.Collections;
public static class ExtensionMethods {
//our handy dandy Remapper function
public static float Remap (this float value, float from1, float to1, float from2, float to2)
{
return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
}
}
保存該腳本,然后回到您的sphereMover腳本。現(xiàn)在,我們可以在Update函數(shù)的ExtensionMethods腳本中使用此Remap函數(shù),將電位計值轉(zhuǎn)換為游戲中可用的值。在我們剛剛分配了potValue變量的位置,鍵入以下內(nèi)容:

提示顯示我們的Remap接受了兩組From和To值,并映射了他們在一起。我們可以在其中輸入值。
mappedPot = potValue.Remap(0, 1023, leftEdge, rightEdge);
保存您的腳本,回到Unity編輯器,然后單擊播放按鈕?,F(xiàn)在,您應(yīng)該看到,移動電位計時,“映射的電位器”變量會發(fā)生變化,以與我們?yōu)樽笥疫吘壌_定的值相對應(yīng)?;ㄒ稽c時間坐下來,感謝您的ExtensionMethods腳本。

注意:如果您注意到自己的值是相反的,那么當(dāng)電位計完全移到右邊時如果您的“ Mapped Pot”變量獲得負(fù)值,則可能是電位計設(shè)置錯誤。幸運(yùn)的是,您無需進(jìn)行任何重新布線即可解決此問題。重新映射它們時,只需切換值即可:

現(xiàn)在,我們終于有了可用的值。現(xiàn)在剩下要做的就是將這些值分配給我們球體的X位置:
//Assign the mapped pot value to the sphere’s x position
transform.position = new Vector3(mappedPot, transform.position.y, transform.position.z);
保存腳本,返回Unity編輯器并按播放。現(xiàn)在,您應(yīng)該可以使用電位計將Sphere左右移動!
將按鈕置于工作狀態(tài)
現(xiàn)在我們可以移動球形了,不是嗎?當(dāng)我們在狹窄的地方時,有什么辦法可以減慢速度嗎?我們將使用按鈕來減慢游戲時間。打開您的sphereMover腳本,然后將此代碼添加到您的Update函數(shù)中
//if Unity detects the button is being pressed, the time scale slows down
if (arduino.digitalRead(buttonPinNumber) == 1){
Time.timeScale = 0.4f;
}
else Time.timeScale = 1.0f;
現(xiàn)在,我們已經(jīng)有了游戲的機(jī)制,請?zhí)砑右恍┱系K!我們將使用球體的天敵,即立方體。在層次結(jié)構(gòu)中,單擊創(chuàng)建》 3d對象》多維數(shù)據(jù)集。在多維數(shù)據(jù)集的檢查器中,添加組件》物理》剛體。將剛體的“拖動”值設(shè)置為5。此外,在檢查器的“ Box Collider”組件下,選擇“ Is Trigger”。
在多維數(shù)據(jù)集上創(chuàng)建一個腳本,并將其命名為 collideWithSphere ,打開腳本并刪除Start和Update函數(shù),這將使我們能夠檢測到與Sphere的碰撞。這次不需要他們。輸入以下代碼:
using UnityEngine;
using System.Collections;
public class collideWithSphere : MonoBehaviour
{
void OnTriggerEnter(Collider other)
{
Destroy(other.gameObject);
}
}
OnTriggerEnter每當(dāng)觸發(fā)對撞機(jī)碰到另一個對撞機(jī)時都會發(fā)送一條消息。在這種情況下,我們要告訴它銷毀一切。保存腳本并返回到Unity編輯器。將多維數(shù)據(jù)集從層次結(jié)構(gòu)拖動到“項目”面板。您會注意到層次結(jié)構(gòu)中的多維數(shù)據(jù)集文本已變?yōu)樗{(lán)色。這是因為我們已經(jīng)創(chuàng)建了一個預(yù)制件并將其保存在我們的項目中?,F(xiàn)在從層次結(jié)構(gòu)中刪除多維數(shù)據(jù)集。
我們現(xiàn)在需要的是一個腳本,用于生成多維數(shù)據(jù)集。在層次結(jié)構(gòu)中,單擊創(chuàng)建》創(chuàng)建空白,然后將其重命名為“檢查器”中的“游戲管理器”,然后向其中添加一個名為gameManager的腳本。打開腳本并添加以下代碼:
using UnityEngine;
using System.Collections;
public class gameManager : MonoBehaviour {
//a variable to hold the prefab we want to spawn
public GameObject cube;
//we want some variables to decide how any cubes to spawn
//and how high above us we want them to spawn
public int numberToSpwan;
public float lowestSpawnheight;
public float highestSpawnheight;
// Use this for initialization
void Start ()
{
for (int i = 0; i 《 numberToSpwan; i++)
{
Instantiate(cube, new Vector3(Random.Range(-9, 9), Random.Range(lowestSpawnheight, highestSpawnheight), 0), Quaternion.identity);
}
}
// Update is called once per frame
void Update ()
{
}
}
保存腳本。返回編輯器,在層次結(jié)構(gòu)中選擇“游戲管理器”,然后將多維數(shù)據(jù)集預(yù)制體從項目面板拖到檢查器中的“多維數(shù)據(jù)集”變量。還要在此處填寫生成的值。您可以隨意擺弄它,以使其變硬或簡單。請注意,將最低的多維數(shù)據(jù)集生成足夠高以允許Uniduino初始化是值得的-在移動之前輸?shù)粲螒蚩赡軙钊司趩剩?/p>

完成的項目
現(xiàn)在,當(dāng)您按Play時,多維數(shù)據(jù)集將在您上方生成并掉落。您可以使用電位計來避免它們,并可以使用按鈕來減慢時間。
在此項目中,我們使用Arduino創(chuàng)建了自定義控制器,將Unity和Uniduino配置為與其通信,并創(chuàng)建了一個簡單的控件。游戲進(jìn)行測試。這里的概念幾乎可以應(yīng)用于任何項目,甚至還有專門針對自定義控制器的游戲卡紙。
借助Arduino和Unity,您幾乎可以從任何東西創(chuàng)建自定義控制器。您是否創(chuàng)建了控制飛船的高保真音響?一個控制平臺游戲的烤面包機(jī)?
責(zé)任編輯:wv
-
控制器
+關(guān)注
關(guān)注
114文章
17805瀏覽量
193703 -
Arduino
+關(guān)注
關(guān)注
190文章
6526瀏覽量
197026 -
Unity
+關(guān)注
關(guān)注
1文章
131瀏覽量
23308
發(fā)布評論請先 登錄
如何為 Vision Five 2 編譯自定義 Linux 內(nèi)核?
電能質(zhì)量監(jiān)測裝置可自定義監(jiān)測時段嗎?
電能質(zhì)量在線監(jiān)測裝置可自定義監(jiān)測時段嗎?
無圖形界面模式下自定義檢查工具的應(yīng)用
采用匯編指示符來使用自定義指令
強(qiáng)實時運(yùn)動控制內(nèi)核MotionRT750(九):內(nèi)置C語言的自定義機(jī)械手模型實現(xiàn)
LOTO示波器自定義解碼功能—CANFD解碼
KiCad 中的自定義規(guī)則(KiCon 演講)
HarmonyOS應(yīng)用自定義鍵盤解決方案
如何使用自定義設(shè)置回調(diào)函數(shù)?
如何在不使用USB控制器的情況下對CYPD2119-24LQXI自定義配置進(jìn)行編程?
NVMe控制器IP設(shè)計系列之接口轉(zhuǎn)換模塊
怎樣使用Arduino和Unity制作自定義游戲控制器
評論