利用NEO與Unity製作遊戲(第3部分)
歡迎來到使用Unity遊戲引擎製作的NEO區塊鏈遊戲的’A-Z’多系列講解教程的第3部分。在第2部分中,我們設定了自己的私有網路並將其連線到我們的Unity場景中。 在第3部分中,我們會進行一些設定,以便我們的玩家可以輸入他們自己的私鑰然後開始與NEO區塊鏈進行互動。
我們將保證每個系列內容的簡潔清晰,從而對整體的工作流程做出全面地演示說明。某些內容我們會做出快速的討論,有任何不清楚的地方,隨時歡迎你發表評論,我很樂意為你解答。
免責申明
至此,我們將開始新增更多自定義的邏輯並與NEO區塊鏈進行互動。 對於任何熟悉這個領域的人來說,這些是不言自明的,但是這個應用程式僅用於教學目的。一款遊戲在很多方面來說就像一個錢包,作為使用者和開發者,在最終將應用連線到主網或者將應用程式交付給使用者時,都必須非常的謹慎。在這個領域中,大多數面向使用者的專案都經過了徹底的測試和稽核,以便發現程式碼漏洞和惡意程式碼。我建議你多花時間與社群合作然後做這些工作。本教程只介紹一些基本知識,為簡單起見,我們會直接將私鑰等內容儲存在本地儲存中,這是不安全的。不要在生產環境中這麼做。
錢包管理
下一部分會更多地涉及到Unity特定的工作流的內容,所以我會給你提供一個預置和指令碼檔案,你可以直接匯入到你的專案中,這樣可以節省一些時間。你可以直接在這裡下載。這個指令碼會管理你的NEO錢包的例項,如果你還沒有這個例項的話,它會幫你新建一個。我提供這個指令碼的原因是為了證明擁有良好入門體驗的重要性。許多的加密貨幣專案(以及一些遊戲)都會要求使用者進行大量的學習從而學會如何使用這個應用程式。長遠上來說,我們需要更好地瞭解如何引入新使用者,同時在這麼做的時候儘可能地減少摩擦。使用者已經投入時間下載遊戲了,當開始要求佔用他們更多時間的時候,如果能在開始玩遊戲的時候,有著越少的必要的點選操作和學習要求,他們就越不可能立馬刪除遊戲。不要讓使用者去思考。
理想情況下,我是希望能完全移除第一個介面,只需將使用者直接放入遊戲中即可。但持有資產的問題是很明顯的,你必須非常清楚何時以及如何處理這些資產。當用戶忘記或者丟失他們的金鑰時,你無法直接進入後臺幫助使用者重置和檢索他們的資料。一個好的中間解決方案是遊戲的開始部分不用涉及到任何錢包內容,只有使用者想要更好地嘗試你的錢包功能時,才會提示使用者輸入這些錢包資訊。希望你們能自行嘗試探索自己的解決方案。
傳送通證
在後面的教程中,我們將更深入地研究智慧合約,但是現在我們只想快速與NEO區塊鏈進行互動。當玩家得分超過某個閾值時,我們會給他們代幣作為獎勵。GAS在某種程度上是NEO區塊鏈中的實際代幣,所以我們會使用它來作為獎勵。
在建立一個真正的遊戲時,你將不得不與攻擊作鬥爭,而鬥爭的同時又要保持遊戲的趣味性和經濟的流動性並不是一件容易的事情。出於演示的目的,我們在這裡會進行簡化。在真正的線上遊戲中,你需要多種反作弊機制,但最終在遊戲中,我們知道我們永遠都無法避免所有的攻擊。某個地方的某個人會下定決心去破壞你的遊戲。否則的話你會遺漏一個關鍵的程式碼漏洞。我們試圖通過防止最為常見的攻擊和睡眠不足來找到平衡,我們經常以這樣一種方式分割經濟,以便其他玩家的遊戲體驗不會在這個過程中受到損害。
建立一個名為NEORewardManager的遊戲物件GameObject,將它作為其他NEO管理器的子物件。建立一個名為NEORewardManager的指令碼並複製貼上以下程式碼:
using System;
using System.Collections;
using UniRx;
using UnityEngine;
public class NEORewardManager : MonoBehaviour
{
[SerializeField] private NEOManager neoManager;
[SerializeField] private CompleteProject.PlayerHealth playerHealth;
[SerializeField] private int rewardThreshold = 50;
private bool isGameOver;
private void Update()
{
if(playerHealth.currentHealth <= 0 && !isGameOver)
{
StartCoroutine(OnGameOver());
isGameOver = true;
}
else if(playerHealth.currentHealth > 0 && isGameOver)
{
isGameOver = false;
}
}
private IEnumerator OnGameOver()
{
yield return new WaitForSeconds(1);
Time.timeScale = 0;
if(CompleteProject.ScoreManager.score >= rewardThreshold)
{
StartCoroutine(TrySendGAS(1));
}
else
{
Time.timeScale = 1;
}
}
private IEnumerator TrySendGAS(int amount)
{
yield return null;
try
{
var tx = neoManager.API.SendAsset(neoManager.MasterKeyPair, neoManager.PlayerKeyPair.Value.address, NEOManager.AssetSymbol, (decimal)amount);
if (tx == null)
{
Debug.LogError("Null Transaction returned");
Time.timeScale = 1;
}
else
{
Debug.Log("TX received, checking sync...");
Observable.FromCoroutine(SyncBalance).Subscribe().AddTo(this);
}
}
catch (NullReferenceException exception)
{
Debug.LogError("There was a problem...");
Time.timeScale = 1;
}
catch (Exception exception)
{
Debug.LogError("There was a problem...");
Time.timeScale = 1;
}
}
private IEnumerator SyncBalance()
{
yield return null;
try
{
//var balances = neoManager.API.GetAssetBalancesOf(neoManager.PlayerKeyPair.Value);
//neoManager.GASBalance.Value = balances.ContainsKey(NEOManager.AssetSymbol) ? balances[NEOManager.AssetSymbol] : 0;
//if (Mathf.Approximately((float)NEOManager.GASBalance.Value, GameDataSystem.Coins.Value))
//{
// Debug.Log("GAS transferred successfully");
//}
//else
//{
// Debug.LogWarning("Something's not right." +
// //"\nCoins: " + GameDataSystem.Coins.Value +
// "\nGAS: " + NEOManager.GASBalance.Value);
//}
Debug.Log("Balance synced!");
Time.timeScale = 1;
}
catch (NullReferenceException exception)
{
Debug.LogWarning("Something's not right." +
//"\nCoins: " + GameDataSystem.Coins.Value +
"\nGAS: " + neoManager.GASBalance.Value);
Time.timeScale = 1;
}
}
}
系統會等待遊戲結束狀態,遊戲結束後如果玩家得分超過某個特定的閾值,系統就會從主賬戶中轉賬GAS到本地玩家賬戶中。 通過拖放場景中的引用來連線NEOManager和PlayerHealth。 你還可以將獎勵閾值設定為你想要的任何值; 玩玩看看。 在隨後的回放中,你可以看到數量的更新,這可以反映出GAS已經轉賬正常了。恭喜,我們現在已經可以與NEO區塊鏈進行一些基本的互動了,耶。
在接下來的教程中,我們將更深入地探討智慧合約,並探索系統能夠提供的其他功能。