利用NEO与Unity制作游戏(第2部分)"
往事随风760
发表于 2022-12-5 17:35:42
155
0
0
NEOLux提供了一些方便的方法,可以用于将你的游戏连接到官方的测试网或者是主网。& B% N7 N2 d! e, q8 u$ d r; ?" U
# a# _, ^7 v: C: y( ]2 e
但在本教程中,我们会搭建自己的私有网络。这个过车是非常简单的,一旦你克服了最初的障碍(我会引导你),你会发现这比使用测试网络更加简单。例如,尽管填写用于测试的GAS或者Tokens的申请表格可能不是世界上最困难的任务,但我发现就这样一点点小摩擦,往往会扼杀我继续的热情和动力。8 P4 V& H7 {% c0 e
+ f- x, m9 J( G
你也可以在本地运行你自己的私有网络,不过在本教程中,我们将设置自己的服务器。这会使得团队工作或者构建工作这类事情更加简单直接。我将使用DigitalOcean。因为根据我的经验,他们具有良好的性价比。
- h, L+ X2 l5 W4 ^- \
免责声明:我不是一个后端/服务器开发者,我猜“中等”水平的人应该会喜欢使用命令行工具。对于那些知道自己在做什么的人来说,这些内容应该很容易。如果你了解Linux和Docker的话,可以直接从DockerHub安装NEOPrivateNet并使用DockerCompose运行NEOSCAN。对于其他那些或多或少是我这种水平的人来说,接下来的内容应该还是相当简单直接的。5 a( c; V# J6 b- y& E& ~
如果你还没有DigitalOcean账户的话,就去创建一个。然后使用以下选项创建一个Droplet。; M' o: \5 X0 j4 S6 C' C( M' q- Y
+ {( ~! ]# {8 ?
使用16.X或者18.X版本的Ubuntu
使用中配应该就足够了–你可以在配置中自行尝试,并在评论中告诉我你的试验的结果% x( F4 O: l2 I8 z5 S: Q
* I' y: s$ }* y
SSH登入到你新建的Droplet并安装docker。如果你按照DigitalOcean提供的指南进行操作的话,这个过程将非常简单:https://www.digitalocean.com/com ... ker-on-ubuntu-18-04+ @" _0 g6 D; ^/ }4 l: h
2 Q0 Q. T% D: N; I: W. v Y# _
注意:在执行最开始的一步,向系统添加官方Docker库的GPG键这步操作时,我遇到了点小问题。我只是简单地跑了两次命令,然后一切都很顺利。
然后安装docker组件。同样地,安装说明非常的简单。只需要确保你看的是针对Linux系统的说明就行。- X2 Q8 B$ D' v& R% N) d6 X
安装私有网络和NEOSCAN
/ n. c- M/ }# U. P8 H6 \) }* ^
运行和安装我们自己的私有网络,这是最为困难的一步,好在CityofZion的人帮我们很好的做到了这一点。你可以点击这个链接查看他们的全部说明指导。同样地,SSH登录到你的Droplet,基本上我们只需要输入几个命令就行:. e3 P5 x& T9 W) h) x' V
首先,从hub上下载docker镜像:! b, q" J) j& b) t1 L) P, D
dockerpullcityofzion/neo-privatenet
…下载NEOSCAN…
wgethttps://raw.githubusercontent.co ... /docker-compose.yml" b: D) K% `3 n: I
…并运行privnet…
docker-compose-fdocker-compose-neoscan.ymlup% P, A8 B: O1 p9 z/ U0 E
让它运行起来,然后转到http:your-droplet-ip-address:4000查看NEOSCAN的运行情况:
回到Unity' l3 C; G9 G" Z" c
& @7 z, T- h- Z( Z
我不想在本教程中深入探讨自己的开发风格,不过我要做的一件事就是将UniRx插件导入Unity中。UniRx是对.NETReactiveExtensions的重新实现,它针对Unity做了优化处理,而且能很好地兼容iOSIL2CPP。不必过于复杂的实现,它可以简化一些管理NEO和UI的代码。
$ s" M0 \% l+ R
在资产(Assets)–>脚本(Scripts)下创建另一个名为NEOManager的脚本,并复制+粘贴以下代码:
4 u% E4 q; `$ e4 s9 `3 ~! K4 d( q
usingSystem.Collections;
usingUnityEngine;
usingSystem;
0 |8 D) ~4 G) ?% {9 I% T
usingUniRx;3 y8 h4 B4 I- X. D9 _. [; U
9 t$ y2 w8 p/ P* a. d; k1 e3 ]
usingNeo.Lux.Core;: S+ w/ Z& y! |$ Q: D- }. d% ~
1 b6 Q L3 e7 g' G
usingNeo.Lux.Cryptography;5 P, a6 H6 ]6 Y# i: `' y0 i2 {9 b
usingUnityEngine.UI;9 ]4 @( [: O6 }
publicclassNEOManager:MonoBehaviour" t1 k! q4 p V i' i3 e
: g4 v# h0 U2 y# F' |
{/ y6 q$ l* m2 a/ _2 V2 ]
- H% l$ n0 w6 D; y0 g
publicNeoAPIAPI;
7 A) F0 n* f* |, |! R
[SerializeField]privatestringRpcIP;. ^+ }/ w4 e6 w1 }1 Z* C0 J5 J5 X# g; i: k
- J1 P; m" k8 }
publicconststringAssetSymbol="GAS";9 a& s5 Q9 b2 b5 t
[HideInInspector]
publicKeyPairReactivePropertyPlayerKeyPair=newKeyPairReactiveProperty();. g: z2 v5 [, z$ z) W6 m0 v
( m& F' W+ r# K/ n. Y1 U: X
[SerializeField]privateTextaddressText;
3 F/ S \: y7 o/ ]
[SerializeField]privateTextbalanceText;
8 j/ { ^+ V1 @. t0 X
publicDecimalGASBalance;+ Q- {. F: V; y6 R% W
: L5 `0 k$ b9 V9 f& X0 D4 x
privatevoidOnEnable()
4 P% b( u4 F/ W
{8 `, b% \/ C0 L5 _7 s
PlayerKeyPair.Value=KeyPair.FromWIF("KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr");
#ifUNITY_EDITOR
//this.API=newLocalRPCNode(30333,"http://localhost");" v. N7 a; I0 u; `1 t- c
this.API=newCustomRPC(30333,4000,"http://"+RpcIP);
#else
//this.API=NeoRPC.ForTestNet();
this.API=newCustomRPC(30333,4000,"http://"+RpcIP);$ M* U6 N8 k# n( A9 i% C2 g
+ b$ u" t+ B8 u. B7 ~
#endif' [% ]9 S" P5 x9 ~
, G1 R! z5 ]- x1 ]$ Y7 e+ o; b
this.PlayerKeyPair.DistinctUntilChanged().Where(kp=>kp!=null).Subscribe(keyPair=>
{3 B. e# y! A) `4 j5 \8 S
. q% G! L! L: H( p- Z7 I
this.addressText.text="Address:"+keyPair.address;8 r! K$ \8 d. A4 L
this.balanceText.text="Balance:Pleasewait,syncingbalance...";' I0 @4 ]2 h0 F) y3 |
StartCoroutine(SyncBalance()); P; A' ^& I2 @ K" ^* N* n+ ]
- {" u5 j7 b0 K* E; C/ f7 [
}).AddTo(this);
4 A# T M! C: g0 C2 R
}
, q, T" n4 f0 f" n) k, o3 T
privateIEnumeratorSyncBalance()
6 r" `! L" m7 F& K
{- a5 Y' L x" \/ n( ~
yieldreturnnull;
varbalances=this.API.GetAssetBalancesOf(this.PlayerKeyPair.Value);( l7 T- r( B7 B! ^! ~5 a$ \( F
this.GASBalance=balances.ContainsKey(AssetSymbol)?balances[AssetSymbol]:0;
5 Z, i% z- `& y) ~: B7 w
this.balanceText.text="Balance:"+GASBalance.Value.ToString()+""+AssetSymbol;: m7 i! V7 |( O f7 ~
" V0 `7 O/ G1 e$ E6 _
}) x" s0 g- ^! S; Y+ I$ s; p+ x
}
# ?" [7 s3 d( L4 `" B1 R% n) ~
[Serializable]) y1 X0 C4 j2 e3 y4 f6 y# R5 T
publicclassKeyPairReactiveProperty:ReactiveProperty
{. G7 d1 m+ |0 @8 l; w
publicKeyPairReactiveProperty(){}* m! a6 q0 \& t* W2 K8 ^% h
publicKeyPairReactiveProperty(KeyPairinitialValue):base(initialValue){}' ^+ X" ^) f2 \+ ]+ A( U' y
}
T5 x: K4 U1 ^ Q: U$ ?( z" t
保存脚本然后返回主场景。创建一个空的游戏对象(GameObject),将其命名为NEO,然后创建一个该NEO对象的空的游戏子对象(childGameObject),并将其命名为NEOManager,并将NEOManager脚本添加到这个NEO对象中。在检查器(inspector)中的RpcIP字段旁边输入你的Droplet的IP地址。
7 @" a/ S6 o0 c4 ^! w6 B" g
接下来,我们将创建一些UI元素并将它们连接到检查器中,这样在连接到主网的时候,我们就可以看到余额的更新。
+ a. s* v% j) C6 G' a
创建UI画布并向其中添加两个子文本元素,然后单击并将它们的引用拖动到NEOManager的“(AddressText)”和“(BalanceText)”字段。" z, g# u' {" J* |+ i. `/ H) d3 a
单击播放(Play)按钮然后查看地址和余额的更新情况。
I% n* H m9 r! ~" o
我们当前使用的是在安装私有网络时自动生成的测试账号。在下一部分中,我们会进行一些设置,以便我们的玩家可以输入他们自己的私钥然后开始与NEO区块链进行交互。
成为第一个吐槽的人