利用NEO与Unity制作游戏(第2部分)"
往事随风760
发表于 2022-12-5 17:35:42
114
0
0
( \; k* {! D8 X+ [6 D4 E# Q
NEOLux提供了一些方便的方法,可以用于将你的游戏连接到官方的测试网或者是主网。) j+ z" g2 r- ~. C
" j$ A, @6 ?8 F$ L4 {
但在本教程中,我们会搭建自己的私有网络。这个过车是非常简单的,一旦你克服了最初的障碍(我会引导你),你会发现这比使用测试网络更加简单。例如,尽管填写用于测试的GAS或者Tokens的申请表格可能不是世界上最困难的任务,但我发现就这样一点点小摩擦,往往会扼杀我继续的热情和动力。
你也可以在本地运行你自己的私有网络,不过在本教程中,我们将设置自己的服务器。这会使得团队工作或者构建工作这类事情更加简单直接。我将使用DigitalOcean。因为根据我的经验,他们具有良好的性价比。
/ R* ~& Z$ e" D- y
免责声明:我不是一个后端/服务器开发者,我猜“中等”水平的人应该会喜欢使用命令行工具。对于那些知道自己在做什么的人来说,这些内容应该很容易。如果你了解Linux和Docker的话,可以直接从DockerHub安装NEOPrivateNet并使用DockerCompose运行NEOSCAN。对于其他那些或多或少是我这种水平的人来说,接下来的内容应该还是相当简单直接的。6 D$ S3 H3 H$ Z7 }9 ?8 u& k) I% {
; L/ ^: ~, Q7 a6 y
如果你还没有DigitalOcean账户的话,就去创建一个。然后使用以下选项创建一个Droplet。
) N7 W) r- w( o* Q& o
使用16.X或者18.X版本的Ubuntu
5 o! F8 f8 s2 s j! V+ l4 T
使用中配应该就足够了–你可以在配置中自行尝试,并在评论中告诉我你的试验的结果
* u. N' N+ s2 p8 y( A: }
SSH登入到你新建的Droplet并安装docker。如果你按照DigitalOcean提供的指南进行操作的话,这个过程将非常简单:https://www.digitalocean.com/com ... ker-on-ubuntu-18-04
注意:在执行最开始的一步,向系统添加官方Docker库的GPG键这步操作时,我遇到了点小问题。我只是简单地跑了两次命令,然后一切都很顺利。7 _& V; ~0 T7 [: Y" j6 s" ?3 s7 i2 G
然后安装docker组件。同样地,安装说明非常的简单。只需要确保你看的是针对Linux系统的说明就行。
安装私有网络和NEOSCAN2 Q' ^2 k3 s# c& u
运行和安装我们自己的私有网络,这是最为困难的一步,好在CityofZion的人帮我们很好的做到了这一点。你可以点击这个链接查看他们的全部说明指导。同样地,SSH登录到你的Droplet,基本上我们只需要输入几个命令就行:
首先,从hub上下载docker镜像:1 V9 U+ d3 x5 ~2 }& x) N/ J8 M
2 y: ]# Y& H# P) i
dockerpullcityofzion/neo-privatenet( ^5 W8 K7 \# G9 C
* K8 @% E+ j( V/ ~ L2 ~% @
…下载NEOSCAN…$ R8 O m( T# y3 g
9 c- W, u/ _! {) j6 d2 U
wgethttps://raw.githubusercontent.co ... /docker-compose.yml
…并运行privnet…1 j7 H5 C' n% j( |- x( z
6 ~- J3 K1 c; K! F; v4 E
docker-compose-fdocker-compose-neoscan.ymlup7 Y7 Z+ Y/ [2 v8 L
让它运行起来,然后转到http:your-droplet-ip-address:4000查看NEOSCAN的运行情况:. i1 f" }# M& O/ L. u' e
回到Unity
我不想在本教程中深入探讨自己的开发风格,不过我要做的一件事就是将UniRx插件导入Unity中。UniRx是对.NETReactiveExtensions的重新实现,它针对Unity做了优化处理,而且能很好地兼容iOSIL2CPP。不必过于复杂的实现,它可以简化一些管理NEO和UI的代码。8 _+ c% n9 g1 g! i- b7 ]
% s* d P. R& A0 C: {& [* z' P! }
在资产(Assets)–>脚本(Scripts)下创建另一个名为NEOManager的脚本,并复制+粘贴以下代码:' e' M+ E6 Q$ J% i; f
usingSystem.Collections;- s- Z4 v8 i0 u3 }
( s+ M# b {+ Y# w+ n3 f
usingUnityEngine;
usingSystem;
8 P: @" z# D+ l# `, f* B
usingUniRx;
usingNeo.Lux.Core;9 B% I; M; Q5 J3 J. H6 t& H
usingNeo.Lux.Cryptography;
usingUnityEngine.UI;) Q" r# w: Y- j4 ^. p
# U3 S6 ~+ E3 ?' E6 T3 O( {
publicclassNEOManager:MonoBehaviour
+ h" w9 m. H* `5 ]( Z
{
4 x7 R+ T$ w0 |( l
publicNeoAPIAPI;
. J+ @1 o0 R! T6 { b4 o
[SerializeField]privatestringRpcIP;9 }0 G! p' J; n, e& Q5 {
publicconststringAssetSymbol="GAS";
- y! X f& s, N3 i
[HideInInspector]
publicKeyPairReactivePropertyPlayerKeyPair=newKeyPairReactiveProperty();
) ~ C3 H6 R# t7 F* B+ K
[SerializeField]privateTextaddressText;5 T& @1 ]. P& Z
! J4 |/ Y; {8 Z! l+ `
[SerializeField]privateTextbalanceText;1 f4 P& v3 e1 M5 ?4 s6 ] O) A
5 \4 s$ r2 _$ |8 [
publicDecimalGASBalance;; R( u8 M" `6 H( G0 x8 m
privatevoidOnEnable()) T$ c" y0 V+ L$ A W
{/ b" n. W8 _# z, ~2 P" Z
PlayerKeyPair.Value=KeyPair.FromWIF("KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr");
" v$ ?* k1 A, s% P; n
#ifUNITY_EDITOR
. F, ?9 C# Q( f/ ~/ h/ W4 T6 r7 c
//this.API=newLocalRPCNode(30333,"http://localhost");) D7 ~' B/ n* A
this.API=newCustomRPC(30333,4000,"http://"+RpcIP);
#else( i6 [! |% e/ @) u4 t0 V: Q, ^
//this.API=NeoRPC.ForTestNet();
. l) M& H( o: M! s; z
this.API=newCustomRPC(30333,4000,"http://"+RpcIP);
#endif3 {: ^3 ?, w6 S P! h
this.PlayerKeyPair.DistinctUntilChanged().Where(kp=>kp!=null).Subscribe(keyPair=>/ v k4 b& g) l) G, ]/ q# L
4 q( a L6 T% X. M$ @5 g, U
{
this.addressText.text="Address:"+keyPair.address;9 ~/ r+ j' H$ ` c" t0 P7 v
$ W. a2 g4 J8 q8 W% L. q" P' } }
this.balanceText.text="Balance:Pleasewait,syncingbalance...";
StartCoroutine(SyncBalance());. r0 Z7 T" M U
}).AddTo(this);
! i9 V- s8 F! F B) _8 E: m
}+ P+ ~) W- @& j
9 Q: @/ |1 c8 `- _, H
privateIEnumeratorSyncBalance()2 L- n0 q; s: T+ Z5 l
0 j- x C( a% s/ i
{3 u9 E" _5 ~ }7 x
, v2 E) P) `6 U
yieldreturnnull; K2 }; {3 H) E7 m8 [" q8 B
varbalances=this.API.GetAssetBalancesOf(this.PlayerKeyPair.Value);; m( L( |" k) T k+ q- Q
3 I% u% W; J& X7 a3 H! l# Z
this.GASBalance=balances.ContainsKey(AssetSymbol)?balances[AssetSymbol]:0;
this.balanceText.text="Balance:"+GASBalance.Value.ToString()+""+AssetSymbol;
5 ~8 |/ u; Y4 R: R
}2 T+ s4 v2 s- N" Q9 {$ e
}
[Serializable]
publicclassKeyPairReactiveProperty:ReactiveProperty
0 r& r$ l: O6 l' b
{( l( `& e0 g0 ^9 U9 k* b
publicKeyPairReactiveProperty(){}
/ u$ ]1 j! _0 }0 J- E" [/ M
publicKeyPairReactiveProperty(KeyPairinitialValue):base(initialValue){}2 Z* O P2 N5 d6 V/ B* i
}6 I3 a: G3 V: u$ g
保存脚本然后返回主场景。创建一个空的游戏对象(GameObject),将其命名为NEO,然后创建一个该NEO对象的空的游戏子对象(childGameObject),并将其命名为NEOManager,并将NEOManager脚本添加到这个NEO对象中。在检查器(inspector)中的RpcIP字段旁边输入你的Droplet的IP地址。
" t( P. v. |, R! s; ?
接下来,我们将创建一些UI元素并将它们连接到检查器中,这样在连接到主网的时候,我们就可以看到余额的更新。1 _: t8 y% x8 r' I( z, ~
创建UI画布并向其中添加两个子文本元素,然后单击并将它们的引用拖动到NEOManager的“(AddressText)”和“(BalanceText)”字段。
3 h6 h9 B# h4 V' u0 e* n) m
单击播放(Play)按钮然后查看地址和余额的更新情况。
我们当前使用的是在安装私有网络时自动生成的测试账号。在下一部分中,我们会进行一些设置,以便我们的玩家可以输入他们自己的私钥然后开始与NEO区块链进行交互。
成为第一个吐槽的人