利用NEO与Unity制作游戏(第2部分)"
往事随风760
发表于 2022-12-5 17:35:42
146
0
0
NEOLux提供了一些方便的方法,可以用于将你的游戏连接到官方的测试网或者是主网。
% X O. W& X1 _7 x; f7 E% p
但在本教程中,我们会搭建自己的私有网络。这个过车是非常简单的,一旦你克服了最初的障碍(我会引导你),你会发现这比使用测试网络更加简单。例如,尽管填写用于测试的GAS或者Tokens的申请表格可能不是世界上最困难的任务,但我发现就这样一点点小摩擦,往往会扼杀我继续的热情和动力。
% X) F8 p3 V: h1 d7 K0 m9 `# u( W" ]
你也可以在本地运行你自己的私有网络,不过在本教程中,我们将设置自己的服务器。这会使得团队工作或者构建工作这类事情更加简单直接。我将使用DigitalOcean。因为根据我的经验,他们具有良好的性价比。, |5 o8 s9 S7 j& I! r
免责声明:我不是一个后端/服务器开发者,我猜“中等”水平的人应该会喜欢使用命令行工具。对于那些知道自己在做什么的人来说,这些内容应该很容易。如果你了解Linux和Docker的话,可以直接从DockerHub安装NEOPrivateNet并使用DockerCompose运行NEOSCAN。对于其他那些或多或少是我这种水平的人来说,接下来的内容应该还是相当简单直接的。
如果你还没有DigitalOcean账户的话,就去创建一个。然后使用以下选项创建一个Droplet。
( c0 \9 p5 f2 v5 T8 _
使用16.X或者18.X版本的Ubuntu3 O6 b! U: \4 v% U9 i
8 X0 g7 {$ y$ W8 R
使用中配应该就足够了–你可以在配置中自行尝试,并在评论中告诉我你的试验的结果
, y( W: ]" f6 U" V
SSH登入到你新建的Droplet并安装docker。如果你按照DigitalOcean提供的指南进行操作的话,这个过程将非常简单:https://www.digitalocean.com/com ... ker-on-ubuntu-18-04) }1 d9 H+ s9 g7 {( ?. T
6 }. z& I, s/ d5 W; |
注意:在执行最开始的一步,向系统添加官方Docker库的GPG键这步操作时,我遇到了点小问题。我只是简单地跑了两次命令,然后一切都很顺利。
然后安装docker组件。同样地,安装说明非常的简单。只需要确保你看的是针对Linux系统的说明就行。. [# f. J b6 G) f% f, z7 E% c
6 q# ~9 j+ l v! F4 [6 p
安装私有网络和NEOSCAN
/ D0 |* H: a$ Q) {7 z
运行和安装我们自己的私有网络,这是最为困难的一步,好在CityofZion的人帮我们很好的做到了这一点。你可以点击这个链接查看他们的全部说明指导。同样地,SSH登录到你的Droplet,基本上我们只需要输入几个命令就行:
首先,从hub上下载docker镜像:
1 m/ u. d/ K1 J$ W
dockerpullcityofzion/neo-privatenet
…下载NEOSCAN…
wgethttps://raw.githubusercontent.co ... /docker-compose.yml& J) \! ]& B0 v8 `& c
7 r$ K& g' b8 I2 u$ Q8 d) p
…并运行privnet…
2 ^% G, V2 v% C8 l; S# F R0 Q$ J& Y
docker-compose-fdocker-compose-neoscan.ymlup
/ x. V4 k: j7 z ^
让它运行起来,然后转到http:your-droplet-ip-address:4000查看NEOSCAN的运行情况:" L$ I: P, G% ?1 ]
8 W' m |$ [( l6 ^
回到Unity
& [* e' ^- B4 F9 s
我不想在本教程中深入探讨自己的开发风格,不过我要做的一件事就是将UniRx插件导入Unity中。UniRx是对.NETReactiveExtensions的重新实现,它针对Unity做了优化处理,而且能很好地兼容iOSIL2CPP。不必过于复杂的实现,它可以简化一些管理NEO和UI的代码。7 x: W+ H! u* P s- a
) P0 F R) d- w5 q# i4 b
在资产(Assets)–>脚本(Scripts)下创建另一个名为NEOManager的脚本,并复制+粘贴以下代码:
/ x6 A1 ^8 @8 H" {
usingSystem.Collections;/ p# o+ L- Y/ |. ?7 {
usingUnityEngine;
% ` [( g5 e- e7 U$ } z
usingSystem;
usingUniRx;- m; D4 e/ w% F8 d
' X1 z* z7 @9 h9 h( W& N
usingNeo.Lux.Core;7 s! [4 \. A$ ~2 s8 o Q( X
usingNeo.Lux.Cryptography;0 m7 N: ~( L3 t. U# Z$ O- V
usingUnityEngine.UI;1 ^: O7 C. Y; z9 `, \
' u- ~4 p+ M. N: t5 |
publicclassNEOManager:MonoBehaviour
' L/ J4 U7 h6 ~$ w
{
publicNeoAPIAPI;
0 Y& S, ?2 g5 `) O/ z+ B% U
[SerializeField]privatestringRpcIP;
publicconststringAssetSymbol="GAS";$ d% @! x) k" Z0 y5 C' A6 [" ^) ~
[HideInInspector]0 O5 e8 A2 c \+ _0 ^- ?2 d
6 S; c* I6 w5 a7 D: q
publicKeyPairReactivePropertyPlayerKeyPair=newKeyPairReactiveProperty();
e/ M( V# w7 }) y
[SerializeField]privateTextaddressText;
[SerializeField]privateTextbalanceText;
publicDecimalGASBalance;
% f$ Y3 w; u* y5 x; r9 G. Q
privatevoidOnEnable()% w1 E8 `8 }& T9 ]$ ]* Z
{) S1 Z3 t* `. B( b. t/ v% s
' s* O! b ?9 b
PlayerKeyPair.Value=KeyPair.FromWIF("KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr");. P$ D( n/ u- j6 m9 M9 }' s: ?, o
& {3 K& \, Q# f* E3 k1 @
#ifUNITY_EDITOR
; R3 S6 Z' e& V
//this.API=newLocalRPCNode(30333,"http://localhost");6 U5 F% I" E/ I. R @
this.API=newCustomRPC(30333,4000,"http://"+RpcIP);
#else
//this.API=NeoRPC.ForTestNet();9 G" X* _* [& U: o, `/ P7 ?
* k9 T; T: N6 t0 R8 `* z; U0 Y/ T( P
this.API=newCustomRPC(30333,4000,"http://"+RpcIP);
3 \1 D( J& Q: s* \/ Z7 H% ~
#endif
3 p% I9 K1 @" F0 O
this.PlayerKeyPair.DistinctUntilChanged().Where(kp=>kp!=null).Subscribe(keyPair=>
, P0 V$ a, Q1 R1 h2 K6 O
{5 D9 u7 P9 q% v
this.addressText.text="Address:"+keyPair.address;: M7 }# o; j& u) o
: p W3 S/ f W" U$ ]: r& A* g/ }
this.balanceText.text="Balance:Pleasewait,syncingbalance...";+ H, F9 X- ~, A; o
/ P: r2 b- y/ I/ |! R2 }
StartCoroutine(SyncBalance());
+ j: c( d+ C1 C% k; F7 i. |' Z7 Z3 {
}).AddTo(this);+ b5 _4 X4 c5 q* B% `8 F$ g
}
privateIEnumeratorSyncBalance(). w! @5 E3 ^' |8 n- C p9 z
{
yieldreturnnull;
. K, z, d* u6 Z0 B) G; b
varbalances=this.API.GetAssetBalancesOf(this.PlayerKeyPair.Value);
this.GASBalance=balances.ContainsKey(AssetSymbol)?balances[AssetSymbol]:0;0 [7 Y* F" U! H
this.balanceText.text="Balance:"+GASBalance.Value.ToString()+""+AssetSymbol;
}0 G* V7 ]+ \0 V* |) K+ O, B
) u8 L |. G1 h V0 w4 w8 G
}
[Serializable]1 b- P, ?5 w) a
7 @' s- P4 S8 ?9 d) o7 s
publicclassKeyPairReactiveProperty:ReactiveProperty* w+ f' z0 z4 M% [. G5 D8 D$ j
{* `# U, }! |- ~+ @. K
5 a" q+ O: N; Q$ |1 r
publicKeyPairReactiveProperty(){}- Z0 g. ?! v! O+ O
publicKeyPairReactiveProperty(KeyPairinitialValue):base(initialValue){}2 R/ B$ f, a$ f+ L% e1 |& e
}
( L# h* Z8 A. C' l+ f# t' p
保存脚本然后返回主场景。创建一个空的游戏对象(GameObject),将其命名为NEO,然后创建一个该NEO对象的空的游戏子对象(childGameObject),并将其命名为NEOManager,并将NEOManager脚本添加到这个NEO对象中。在检查器(inspector)中的RpcIP字段旁边输入你的Droplet的IP地址。
2 g# C3 ^) a S$ D6 L- Y
接下来,我们将创建一些UI元素并将它们连接到检查器中,这样在连接到主网的时候,我们就可以看到余额的更新。) [/ h3 ?/ F8 G J
创建UI画布并向其中添加两个子文本元素,然后单击并将它们的引用拖动到NEOManager的“(AddressText)”和“(BalanceText)”字段。
4 q* Q# \1 Q3 Z* I
单击播放(Play)按钮然后查看地址和余额的更新情况。
我们当前使用的是在安装私有网络时自动生成的测试账号。在下一部分中,我们会进行一些设置,以便我们的玩家可以输入他们自己的私钥然后开始与NEO区块链进行交互。
成为第一个吐槽的人