该文章是独立游戏开发者克里夫·考利写的区块链游戏开发技术文章。没有投资没有团队,他自己一个人成功开发了以太坊区块链第一款真正意义上的ARPG游戏——遗失的宝藏。目前游戏已稳定运营8个月,游戏玩家人数已经超过3700人,玩家道具周交易量在1万人民币左右,月营收在80000 ENJ(人民币50000元)左右。克里夫近期分享了自己从零开发搭建区块链游戏的技术路线。作为一名区块链游戏的粉丝,我见证了遗失的宝藏从无到有的过程。为克里夫喝彩之余,感慨为何国内没有游戏开发者能做出如此上等品质的区块链游戏。于是翻译这篇文章,分享到国内的游戏开发者社区,希望能给国内的游戏开发者一些启发。
技术上深入研究了我如何使用Enjin,.Net Core,PlayFab,Azure和Unity来构建第一个以太坊主网上的ARPG游戏
作者:克里夫·考利
1月6日 · 18 分钟阅读
它已有8个月了我发布的第一版本遗忘的文物(2019年5月13日的创始人和其他人2019年5月23日),它可以运行在Enjin主网。
遗失的宝藏是第一个加入Enjin 星火计划的平台。我错过了抢先体验计划,因为我正忙于其他工作,但我抓住了加入Enjin生态系统并开始在区块链领域冒险的机会。
在第一个发行版之后很快便出现了名为“ Stampede ” 的第一个活动,我用它来查看构建的系统在压力下的性能如何,以及是否需要进一步构建和维护。Stampede 活动于2019年6月13日左右结束。
我最初计划在第一次活动后关闭服务器,以便我可以花一些时间进行重组,计划和改进。但是,每个玩过游戏的人都非常喜欢这次活动,他们要求我保持服务器运行,以便他们继续玩游戏。
仅有极短的停机时间来进行更新,该游戏现已连续平稳运行8个月!
第二个活动`` 坠落的石板’'于2019年7月1日开始,测试了玩家之间通过Enjin区块链资产以完成目标。
作为奖励,玩家可以在激活并传递任意石板后,在一个秘密的宝藏室中找到更高等级的战利品。
我开始使用PlayFab为其后端服务,从而使我能够快速启动并运行诸如玩家帐户,库存管理和服务器端脚本之类的关键系统。
如果你刚开始,PlayFab是一项了不起的服务。他们为你处理了许多系统,并具有一些出色的功能,例如玩家管理,玩家库存,物品数据库,分析仪表板和排行榜。当我去使用某种简单易用的东西时,我经常感到惊讶,这也意味着我不需要自己为该功能编写任何代码。
我强烈推荐PlayFab,但是根据你想要达到的目标,你的里程可能会有所不同。
我遇到了需要工作的方式的问题,下面详细介绍了其中的一些挑战。
自从我第一次使用它们以来的8个月里,它们已经进行了一些重大的升级和更改,并且我遇到的某些问题可能已得到解决。
我于2019年3月29日公开宣布了Enjin集成,其中包含从登录到获取物品的完整用户路径。
区块链游戏失落的宝藏
尽管它很快显示出你可以使用Enjin的Unity SDK来完成此过程,但你绝对不希望通过使用SDK进行写操作来发布游戏。诸如创建,发送,铸造物品等之类的事情。
该SDK包含2个主要组件。用于管理平台的编辑GUI,以及用于查询和变异的API。GUI使创建,编辑,铸造和融化项目非常简单。
刚开始时,这是我的省钱之举,因为它使我可以直观地看到可用的内容和可以做的事情,而无需直接查询GraphQL(我尚不确定如何使用它)。
我可以在一处查看和编辑所有项目。
最终,你将需要将此过程移至自动化过程。虽然这是一个很棒的介绍,但是如果要创建许多项目,那么就不应该长期使用它。
最近,Enjin已更新了他们的Web控制台,已包括上述编辑工具,你现在也可以直接从他们的网站中进行相同的操作,这真是棒极了。
API代码是GraphQL调用的包装,并且包括用于在更新钱包余额之类的内容时连接到推送服务以进行更新的代码。
此API仅应与仅将权限限制为视图的身份一起使用,并且应删除所有具有修改能力的权限。你唯一需要的查看权限是viewBalances。
然后,你将登录详细信息输入到SDK中,并将其保存以供客户端使用。
请注意,这些详细信息以纯文本格式存储在游戏二进制文件中。如果这样做,你便可以授予下载游戏的任何人对该Enjin帐户的完全访问权限,因此请确保该帐户已被锁定。
你可以在游戏二进制文件中对这些细节进行加密,但实际上要比你意识到要逆转这些细节并从游戏中恢复它们要容易得多。
我个人不建议这样做,因为在开发过程中你可能会不小心添加管理员详细信息,而忘记删除它们并在构建中释放完全访问权限。
你还将要对Enjin进行更多查询,因为你的服务器仍然需要查询相同的信息来验证操作,然后客户端需要再次查询它们。如果Enjin为API调用实现配额,那么你稍后可能需要找到有创意的方法来减少客户端调用。
如果所有内容都在服务器上,则可以在其中添加缓存,然后将快照返回给客户端。如果你将该缓存存储在服务器上,并且Enjin或以太坊区块链发生故障(这在我上线的8个月中已发生两次),则你的玩家仍然可以使用他们的物品。
我不建议将Enjin Unity SDK(或任何其他客户端引擎SDK)用于重要的事情,例如为游戏创建,铸造等(即,如果你将物品发送给玩家以完成关卡)。你希望完全控制的服务器成为授权代理,并且是执行这些操作的唯一实体。
就我而言,我有两个球员清单。虚拟库存(不是区块链项目的任何项目,或属于排队等待发送的区块链项目的项目)和区块链库存。
服务器同时查询,合并,缓存并发送给客户端。有时会不时刷新缓存,但是客户端也会监视推送程序通道的更改,并在下一次更新期间将其告知服务器,如果更改,服务器也会为该用户刷新缓存。
Unity SDK的核心是调用Enjin的GraphQL服务。
我使用Enjin的Unity SDK作为学习资源。我对如何将事物组合和使用的早期了解大部分来自阅读Enjin的Unity SDK的源代码。
如果你正在等待其他SDK(例如Unreal SDK),建议你直接进入并直接从服务器调用GraphQL,因为这最终将是你要做的。
确保所有区块链突变操作仅在安全的服务器上进行。
你永远不希望你的客户端(本机Windows,Mac,Android,iOS,Web)直接执行GraphQL调用,因为它允许具有足够知识的任何人自己在客户端/游戏之外进行这些调用。
当我发布Stampede活动时,一旦他们成功退出地牢,我就会将其发送给玩家。
效果很好,我很快就发送了数千个项目。
直到以太坊网络变得拥挤为止。
我发现,在Enjin的任何与区块链相关的调用都将开始返回错误之前,你的帐户上可能有大约16笔待处理交易(等待被开采)。(即发送,铸造,创建等)
如果你没有跟踪要操纵的项目,那么现在就没有记录可依。
据了解,这段时间在《遗失的宝藏》中丢失的物品已经丢失在地牢的熔岩中。
每次交易也要花费燃料,你支付的燃料量会随着数据量的增加而增加。
那时,我使用标准发送在一次交易中将单个物品发送到目标钱包。我花了很多ETH,然后才发出物品
相反,我建议将“高级发送”用于所有发送目的。你可以一次交易将多个项目发送到多个地址。
之所以有限制,是因为事务本身的大小是有限制的,但是大致的指导是传输数组中的条目不超过100个(如果你发送FT,则项目的数量无关紧要,但是NFT只能是1每个条目)。
几乎每个对Enjin的GraphQL的变异调用都返回一个transactionId。存储此数据非常重要,因为你可以使用它来查询刚刚执行的操作的状态。(不仅将其存储在日志中,还将其与数据一起存储,以便以后可以使用它查询状态)
例如,如果你发出发送,则可以使用此 transactionId 来确定发送是否成功,仍在区块链上处于挂起状态或发送失败。
我在调查交易时使用的常见graphQL查询是:
query {
EnjinTransactions(
id: TRANSACTION_ID_HERE,
) {
id
transactionId
type
state
error
nonce
token {
id
name
}
retryState
}
}
该查询在一个调用中返回足够的信息,以确定错误的原因或错误的状态。
我的大多数服务器进程都使用上面的查询来确定状态。
例如,要确定某人是否成功完成了一项任务,我可以使用此查询来确定我是否已成功将发给玩家的QuestId要求的 transactionId 发送到游戏钱包。
我将在“ Enjin区块链发送队列 ”部分下介绍有关发送队列的更多信息。
你可以使用“高级发送”将你自己的项目发送给多个人。你还可以使用“高级发送”向其他人请求项目。我用它来实现你在“ 遗失的宝藏”中看到的任务。
在这里的示例中,我要在一次交易中从我自己向两个不同的钱包发送20,000 FT的TOKENID1和10,000 FT的TOKENID2。
mutation advancedSend {
CreateEnjinRequest(identity_id: SENDER_ID, type: ADVANCED_SEND, advanced_send_token_data: {
transfers: [
{from_id: SENDER_ID, to: "0xTARGETWALLETADDRESS1", token_id: "TOKENID1", value: "20000"},
{from_id: SENDER_ID, to: "0xTARGETWALLETADDRESS2", token_id: "TOKENID2", value: "10000"}
]})
{
id
encoded_data
}
}
你可以将更多项目添加到transfers数组中,以一次传输更多内容。只要确保你添加的数量不超过100。
要请求物品,只需使用你所请求的用户的identity_id。
用户的 identity_id 特定于你的平台,他们必须已链接其钱包和已批准的ENJ支出
在Kovan测试网上进行测试时,交易会很快发生。在大多数情况下,在主网上也是如此,但是有时会出现问题。
拥堵和燃料价格上涨是你应该计划的事情。
我遇到的常见问题是:
我最初发布时使用的是PlayFab支持的后端。我相当广泛地使用了项目目录和删除表功能。在传统游戏中,无限制的物品,系统运行非常出色。
但是,如果你要管理有限的供应项目,则可能会遇到一些与我一样的问题。
由于我的大部分物品都供应有限,因此我需要准确地确保我所提供的物品不会超过钱包里的实际数量。向玩家展示他们刚刚赢得了《屠戮者》而无法将其发送给他们,这是很糟糕的,因为我的存货已经耗尽。
PlayFab具有“ 限量版 ”功能,你可以针对每个项目启用该功能。这似乎正是我需要使用的内容,但是它们有100个项目的任意限制。(我相信现在可能已将其增加到1000,但是如果你有任何数量的物品超过该值,那么这个数字仍然不够用)
这是我遇到的第一个障碍,因此我不得不提出一个有创意的解决方案。为此,我跟踪了该项目的单独的自定义数据。此自定义数据跟踪总供应量和剩余供应量。
每次我向玩家提供一件物品时,我都会检查该值是否已降至25,如果已降低,则将其最高填充至100(如果剩余供应量足够)。它很简陋,但确实有效,让我可以继续使用他们的系统。
我个人更喜欢C#。我在高中时就开始了编码工作,学习了QBasic,后来又学习了Visual Basic,然后当我开始在视频游戏行业工作时转而使用C和C ++。我沿途学习了许多其他语言,包括用于网络的语言(php,javascript等)。
PlayFab使用Javascript进行服务器端脚本编写,虽然我知道如何用Javascript编写代码,但我更喜欢C#。从Unity到我的自定义工具,整个堆栈的其余全部都是C#。所以对我来说,这是一个缺点,但是我暂时可以接受。
PlayFab 已取得进展,可让你执行C#,我相信他们即将发布此版本(目前处于私人预览中)
第一个用Javascript编写的服务器端代码
PlayFab服务器脚本的局限性在于你的脚本执行时间不会超过10秒。如果存在,则终止。(根据我的经验,它大约在9.3秒后终止)。
尽管大多数用例永远都不会接近此限制,但是随着我添加越来越多的EnjinAPI调用,我在大约一个月内就达到了这个极限。
从PlayFab的服务器发出的Enjin的GraphQL调用有时需要花费一秒钟的时间才能执行,具体取决于我查询的数据量(例如,玩家钱包中的物品数量),或者是否在服务器上进行了新发布。混合了几个Enjin调用带有PlayFab电话和它迅速增加。
如果还有其他网络故障,那么一个Enjin呼叫可能会花费几秒钟或更长时间。
当我添加了更多的多元宇宙的项目多,支持来电Enjin,我发现写在功能PlayFab的服务器脚本只是部分执行。
我不知道运行了多少功能,发现增加执行时间的唯一方法是升级到企业层。
我已经从Free升级到Indie,然后又升级到Pro,以便在几周前获得某种程度的支持包,而我还没有准备仅为此一项功能升级到最高级别。
由于没有执行时间的限制,因此我不得不迅速找到解决方案。
我决定将所有服务器逻辑和其他代码从PlayFab服务器脚本(javascript)转换为C#代码,然后在Microsoft Azure上将其作为Web服务运行。
这使我可以完全控制脚本的运行时间,这意味着我仍然可以使用服务器上的PlayFab的服务。
我花了大约一周的时间来转换所有代码。我现在在自己的Azure Web服务上运行代码,并依赖PlayFab来处理所有用户帐户,项目,库存,页首横幅等。
在PlayFab平台上的整个过程中,我遇到了多个错误,其中包括一个严重的错误,该错误影响了我所使用的“限量供应”功能。我遇到的每个问题我都无法控制,只能坐下来等待PlayFab的支持团队做出回应。
免费和独立层仅提供论坛帮助。响应时间通常为24-36小时。
对于我遇到的一些更关键的问题,我最终升级到Pro,因为它提供了专门的支持。
不幸的是,专用支持几乎花了整个时间才在论坛上得到答复(可笑的是,我从他们的免费支持那里得到的答复比专用支持更快),并且专用支持人员(在解决我的问题之前)询问是否可以解决问题在解决解决方案之前。
似乎他们非常渴望解决问题,而不是解决问题
另外,我遇到了一个长期存在的问题,即一旦一个玩家帐户上存在超过2,000个项目日志事件,该帐户就不再加载。
我建议他们可以简单地添加分页支持来解决此问题。
这个问题从未得到解决,PlayFab支持人员认为这是一个“ 未来功能请求”,需要进行投票。
随着更多玩家的帐户中添加和删除了物品,更多的帐户不再加载。
支持问题和这个长期存在的问题对我来说是最后的稻草。
是时候使用我自己的自定义解决方案重新开始了。
多年来,我已经编写了许多后端服务,所以我知道我有能力承担重新创建大部分PlayFab服务的艰巨任务。
现在大约是2019年8月中旬,我开始着手消除对PlayFab的依赖。我一次重新创建了各种系统,并在他们很高兴能像PlayFab产品一样工作时将它们联机。
最后我继续使用Microsoft Azure,因为我在过去的几年中拥有最丰富的经验,他们原生支持我已经在使用的C#.Net Core堆栈。我创建搭载一台数据库天青的Sql和我利用自己的CDN,服务总线,Blob存储,并应用见解。
首先,我创建了自己的用户身份验证系统,该系统依赖于无密码电子邮件身份验证(类似于“忘记密码”机制的工作原理)。一旦该系统透明地处理了身份验证方,我便开始重新创建Item数据库。
一旦Item数据库运行正常,我就添加了玩家库存支持,玩家帐户管理,冒险跟踪,排行榜,商店和管理后端以及其他较小的服务。
在2019年9月17日,我还成功启动了新的后端并完全刷新了网站。
管理员后端预览
经过一些小的修复后,自从我不断开发和改进它以来,它一直运行非常出色。
一些开发人员只需设置对数据库的直接访问权限,运行SQL查询以读取和写入数据并管理其帐户,就足够了。
我更喜欢减少人为错误组件并创建任何人都可以使用的接口。
我创建了一个简单的“管理面板”来简化此操作,并为我提供一个用于管理和管理“ 遗忘物品”的控制面板。
我使用“管理”面板来创建游戏项目(包括Enjin项目),设置新事件,冒险和任务,而无需执行手工SQL命令并确保在输入数据时遵循特定规则。
如果系统检测到某个项目是区块链项目,但尚未创建,则可以直接在“管理”面板中创建它。
当我单击“ 创建区块链项目 ”按钮时,该项目将添加到队列中进行处理。它由服务器Web Job拾取,它将发出对Enjin的调用,以使用输入的值创建令牌,设置元数据并铸造所有实例。
我强烈建议你为自己的项目设置这样的自动化系统,因为它可以消除人为错误组件。
踩踏事件发生后,我意识到我需要一个队列来稍后处理我的交易。
队列的好处是你可以在发送物品之前检查几个先决条件。
在发送物品之前,我会检查以下内容:
当我以前在视频游戏行业工作时,我工作的每个公司都有自己的内部游戏引擎。
每个引擎都有自己的优缺点,通常受到公司员工知识和专长的限制。
如果你更换公司,那么你拥有的大部分游戏引擎知识现在都将无用,因为下一家公司的游戏引擎与你以前使用的非常不同。通常,整个行业都没有执行任何标准,每家公司都冒险走自己的路。
Unity无疑改变了这一点。它增加了急需的竞争和技巧,从而压低了诸如Unreal之类的游戏引擎的价格。我所服务的公司当时从未许可过其他引擎,因为引擎许可成本几乎消耗了游戏预算的三分之一。
我是专业的程序员,但我也喜欢艺术,音频和设计。Unity的易用性及其资产商店使我能够自己一个人迅速地从头开始创建遗失的宝藏。
这种易用性和功能是10年前闻所未闻的。
我从Unity商店策划了很多艺术资产,然后对其进行自定义以适合“ 遗失的宝藏”世界。这是独立开发人员执行此操作的常见过程,因为它可以极大地提高生产力。
我依靠Unity将“ 遗失的宝藏”的世界带入生活。如果你曾经编写过游戏引擎,那么你将知道Unity可以为你处理多少(提示:很多)。我设计关卡,为游戏创建代码,并在Unity编辑器中对其进行预览。
Unity承担了许多繁重的工作,因此我不必这样做,而是可以专注于游戏并为每个人创造有趣而有趣的体验!
下载适用于iOS或Android设备的Enjin钱包,并使用它扫描以下二维码码:
你将立即收到可遗失的宝藏使用的剑。
Windows和Mac均可使用“ 遗失的宝藏”
Forgotten Artifacts是一款具有Enjin区块链集成的动作角色扮演hack和slash dungeon crawler视频游戏。你发现的工件将被添加到Enjin区块链钱包中,供你收集和交易!
遗失的宝藏
Forgotten Artifacts是一款具有Enjin区块链集成的动作角色扮演hack和slash dungeon crawler视频游戏。你发现的工件将被添加到Enjin区块链钱包中,供你收集和交易!