如何在Windows平臺使用Unity開發(fā)Loom Network游戲DAPP

一、服務(wù)器我選用的是阿里云服務(wù)器,按量付費,方便隨時不想用的時候直接釋放掉就可以了

首先選擇配置,按實際情況來選


001.png

選擇Ubuntu 18.04 64位系統(tǒng)


002.png

創(chuàng)建密碼,填寫主機名
003.png

其他保留默認即可!
后面需要用到Xftp傳輸文件,以及Unity與Loom節(jié)點通信所以需要把服務(wù)器相關(guān)的端口開放
打開服務(wù)器實例里的管理,左邊列表的安全組進入,點擊配置規(guī)則,添加安全組規(guī)則


016.png

017.png

二、安裝服務(wù)器上需要用到的一些插件

我本地使用的是Win7筆記本來開發(fā),為了方便操作服務(wù)器,推薦安裝Xshell和Xftp軟件來連接服務(wù)器


004.png

使用Xshell比較方便的可以同時開多個窗口

輸入命令更新源

apt-get update
005.png

006.png

安裝nodejs

sudo apt-get install nodejs

安裝npm

sudo apt-get install npm

然后測試nodejs的版本和包管理器npm的版本node -v、npm -v


007.png

008.png

三、安裝Loom以及開發(fā)合約需要用到的相關(guān)插件

安裝Loom運行Dapp鏈:

curl https://raw.githubusercontent.com/loomnetwork/loom-sdk-documentation/master/scripts/get_loom.sh | sh
./loom init
./loom run
LoomNetwork.png

LoomNetwork官方開發(fā)文檔:https://loomx.io/developers/zh-CN/how-to-develop-locally.html#introduction

安裝truffle

npm install truffle -g
npm install solc -g

安裝完成會顯示truffle版本
初始化一個新項目

mkdir truffle-dappchain
cd truffle-dappchain
truffle init
018.png

019.png
cd contracts
touch SimpleStore.sol
vi SimpleStore.sol

編寫SimpleStore合約

pragma solidity ^0.5.0;

contract SimpleStore {
  uint value;

  event NewValueSet(uint _value);

  function set(uint _value) public {
    value = _value;
    emit NewValueSet(value);
  }

  function get() public view returns (uint) {
    return value;
  }
}

編寫完按esc :wq 保存退出
編譯合約

root@LoomNet:~/truffle-dappchain# truffle compile

Compiling your contracts...
===========================
> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/SimpleStore.sol
> Artifacts written to /root/truffle-dappchain/build/contracts
> Compiled successfully using:
   - solc: 0.5.8+commit.23d335f2.Emscripten.clang

root@LoomNet:~/truffle-dappchain# ls
build  contracts  migrations  test  truffle-config.js
root@LoomNet:~/truffle-dappchain# 

合約部署需要創(chuàng)建一個遷移文件,進入migrations文件夾

root@LoomNet:~/truffle-dappchain# cd migrations
root@LoomNet:~/truffle-dappchain/migrations# ls
1_initial_migration.js
root@LoomNet:~/truffle-dappchain/migrations# cp 1_initial_migration.js 2_simple_store.js
root@LoomNet:~/truffle-dappchain/migrations# ls
1_initial_migration.js  2_simple_store.js
root@LoomNet:~/truffle-dappchain/migrations# vi 2_simple_store.js
root@LoomNet:~/truffle-dappchain/migrations# 
var SimpleStore = artifacts.require("./SimpleStore.sol");
module.exports = function(deployer) {
  deployer.deploy(SimpleStore);
};

修改truffle-config.js里的網(wǎng)絡(luò)配置

const { readFileSync } = require('fs')
const path = require('path')
const { join } = require('path')
const LoomTruffleProvider = require('loom-truffle-provider')
module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 7545,
      network_id: "*",
    },
    local_loom: {
      provider: function() {
        const privateKey = readFileSync(path.join(__dirname, 'loom_private_key'), 'utf-8')
        const chainId = 'default'
        const writeUrl = 'http://127.0.0.1:46658/rpc'
        const readUrl = 'http://127.0.0.1:46658/query'
        const loomTruffleProvider = new LoomTruffleProvider(chainId, writeUrl, readUrl, privateKey)
        loomTruffleProvider.createExtraAccountsFromMnemonic("gravity top burden flip student usage spell purchase hundred improve check genre", 10)
        return loomTruffleProvider
        },
      network_id: '*'
    }
  }
}

安裝loom-truffle-provider

npm install loom-truffle-provider --save

創(chuàng)建一個名為'loom_private_key'的私鑰
由于我的loom鏈?zhǔn)窃诟?jié)點,私鑰需要放到truffle-dappchain的根目錄,所以我這樣執(zhí)行

root@LoomNet:~/truffle-dappchain# ../loom genkey -a loom_public_key -k loom_private_key
local address: 0x02b40aAaF26f97f3ea0CA550a4C24F8b5C8d1324
local address base64: ArQKqvJvl/PqDKVQpMJPi1yNEyQ=
root@LoomNet:~/truffle-dappchain# ls
build  chaindata  contracts  loom_private_key  loom_public_key  migrations  test  truffle-config.js
root@LoomNet:~/truffle-dappchain# 

接下來打開另一個Xshell窗口,啟動LoomDapp鏈

./loom run

在剛才的窗口將合約部署到Loom鏈上

truffle migrate --network local_loom

這個時候合約就開始部署了

root@LoomNet:~/truffle-dappchain# 
root@LoomNet:~/truffle-dappchain# 
root@LoomNet:~/truffle-dappchain# truffle migrate --network local_loom

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.



Starting migrations...
======================
> Network name:    'local_loom'
> Network id:      13654820909954
> Block gas limit: 0x0


1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
   > transaction hash:    0x434fee0b8efcdec81dbf30520bc7d476b038cd3e44441b1655f66a93fc6dd833
   > Blocks: 0            Seconds: 0
   > contract address:    0x04B755D415BF2D528AfC562866B3DD52c1717893
   > block number:        141
   > block timestamp:     1569744222
   > account:             0x02B40AAAF26F97f3Ea0CA550a4C24f8B5c8D1324
   > balance:             0
   > gas used:            0
   > gas price:           0 gwei
   > value sent:          0 ETH
   > total cost:          0 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:                   0 ETH


2_simple_store.js
=================

   Deploying 'SimpleStore'
   -----------------------
   > transaction hash:    0x072f26c332cc19b59c3c37c9f0cfe9ea55122169b2308161828271e17010e520
   > Blocks: 0            Seconds: 0
   > contract address:    0xda98B323AC5c6c4E5DE2C6B71fc908744f14E7d4
   > block number:        147
   > block timestamp:     1569744228
   > account:             0x02B40AAAF26F97f3Ea0CA550a4C24f8B5c8D1324
   > balance:             0
   > gas used:            0
   > gas price:           0 gwei
   > value sent:          0 ETH
   > total cost:          0 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:                   0 ETH


Summary
=======
> Total deployments:   2
> Final cost:          0 ETH


root@LoomNet:~/truffle-dappchain# 

部署成功會在build/contracts目錄里找到SimpleStore.json文件,里面就包含我們的合約abi

root@LoomNet:~/truffle-dappchain# cd build
root@LoomNet:~/truffle-dappchain/build# ls
contracts
root@LoomNet:~/truffle-dappchain/build# cd contracts
root@LoomNet:~/truffle-dappchain/build/contracts# ls
Migrations.json  SimpleStore.json
root@LoomNet:~/truffle-dappchain/build/contracts# vi SimpleStore.json
{
  "contractName": "SimpleStore",
  "abi": [
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "name": "_value",
          "type": "uint256"
        }
      ],
      "name": "NewValueSet",
      "type": "event"
    },
    {
      "constant": false,
      "inputs": [
        {
          "name": "_value",
          "type": "uint256"
        }
      ],
      "name": "set",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "get",
      "outputs": [
        {
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    }
  ],

我們只需要"abi":[]大括號的部分一會會用到,
記住我們部署的SimpleStore合約地址,等會在Unity工程當(dāng)中會用到,你的地址部署出來可能跟我的不一樣

contract address:    0xda98B323AC5c6c4E5DE2C6B71fc908744f14E7d4

接下來我們在test目錄創(chuàng)建一個測試合約腳本

root@LoomNet:~/truffle-dappchain# cd test
root@LoomNet:~/truffle-dappchain/test# ls
root@LoomNet:~/truffle-dappchain/test# touch SimpleStore.js
root@LoomNet:~/truffle-dappchain/test# ls
SimpleStore.js
root@LoomNet:~/truffle-dappchain/test# vi SimpleStore.js
root@LoomNet:~/truffle-dappchain/test# 

測試合約內(nèi)容

const SimpleStore = artifacts.require('SimpleStore')
contract('Test', (accounts) => {
  let [alice] = accounts
  let contractInstance
        beforeEach(async () => {
            contractInstance = await SimpleStore.new()
        });
        it('should be able to set a value', async () => {
                let value = 4
                const result = await contractInstance.set(value, {from: alice})
                assert.equal(result.receipt.status, true)
                assert.equal(result.logs[0].args._value.toString(), value.toString())
        })
        it('should be able to set and then get a value', async () => {
                let value = 5
                await contractInstance.set(value, {from: alice})
                const result = await contractInstance.get({from: alice})
                assert.equal(result.toString(), value.toString())
        })
})

使用命令測試合約

root@LoomNet:~/truffle-dappchain/test# cd ../
root@LoomNet:~/truffle-dappchain# truffle test --network local_loom
Using network 'local_loom'.


Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.



  Contract: Test
    ? should be able to set a value (3018ms)
    ? should be able to set and then get a value (3021ms)


  2 passing (12s)

root@LoomNet:~/truffle-dappchain# 

測試成功!

四、在Unity工程中調(diào)用Loom合約

這里是官方的Unity教程:
https://loomx.io/developers/zh-CN/unity-truffle-loom-sample.html

首先去github下載LoomSDK的Unity工程包:
https://github.com/zandk/CryptoRealmClient
SimpleStoreHandler腳本代碼:

using System;
using System.Threading.Tasks;
using UnityEngine;
using Loom.Unity3d;
using Loom.Unity3d.Samples;
using Loom.Nethereum.ABI.FunctionEncoding.Attributes;

public class LoomQuickStartSample : MonoBehaviour {

    // 部署合約之后返回的abi
    // 合約部署的地址
    public TextAsset simpleStoreABI;
    public TextAsset simpleStoreAddress;

    async Task<EvmContract> GetContract(byte[] privateKey, byte[] publicKey)
    {
        var writer = RPCClientFactory.Configure()
            .WithLogger(Debug.unityLogger)
            .WithHTTP("http://127.0.0.1:46658/rpc")//替換自己部署到云服務(wù)器上的LoomDapp鏈的服務(wù)器IP
            //.WithWebSocket("ws://127.0.0.1:46657/websocket")
            .Create();

        var reader = RPCClientFactory.Configure()
            .WithLogger(Debug.unityLogger)
            .WithHTTP("http://127.0.0.1:46658/query")//替換自己部署到云服務(wù)器上的LoomDapp鏈的服務(wù)器IP
            //.WithWebSocket("ws://127.0.0.1:9999/queryws")
            .Create();

        var client = new DAppChainClient(writer, reader)
        {
            Logger = Debug.unityLogger
        };
        // required middleware
        client.TxMiddleware = new TxMiddleware(new ITxMiddlewareHandler[]{
            new NonceTxMiddleware{
                PublicKey = publicKey,
                Client = client
            },
            new SignedTxMiddleware(privateKey)
        });
        //合約部署之后返回的abi
        string abi = simpleStoreABI.ToString();
        //string abi = "[{\"anonymous\": false,\"inputs\": [{\"indexed\": false,\"name\": \"_value\",\"type\": \"uint256\"}],\"name\": \"NewValueSet\",\"type\": \"event\"},{\"constant\": false,\"inputs\": [{\"name\": \"_value\",\"type\": \"uint256\"}],\"name\": \"set\",\"outputs\": [],\"payable\": false,\"stateMutability\": \"nonpayable\",\"type\": \"function\"},{\"constant\": true,\"inputs\": [],\"name\": \"get\",\"outputs\": [{\"name\": \"\",\"type\": \"uint256\"}],\"payable\": false,\"stateMutability\": \"view\",\"type\": \"function\"}]\r\n";
        //合約地址
        var contractAddr = Address.FromHexString(simpleStoreAddress.ToString());
        var callerAddr = Address.FromPublicKey(publicKey);
        return new EvmContract(client, contractAddr, callerAddr, abi);
    }

    /// <summary>
    /// 調(diào)用合約的set方法
    /// </summary>
    /// <param name="contract"></param>
    /// <returns></returns>
    async Task CallContract(EvmContract contract,int value)
    {
        await contract.CallAsync("set", value);
    }

    /// <summary>
    /// 調(diào)用合約的get方法
    /// </summary>
    /// <param name="contract"></param>
    /// <returns></returns>
    async Task StaticCallContract(EvmContract contract)
    {
        if (contract == null)
        {
            throw new Exception("Not signed in!");
        }

        var result = await contract.StaticCallSimpleTypeOutputAsync<int>("get");

        if (result!=null)
        {
            Debug.Log("Smart contract returned: " + result.ToString());
        }
        else
        {
            throw new Exception("Smart contract didn't return anything!");
        }
    }

    // Use this for initialization
    async void Start()
    {
        // The private key is used to sign transactions sent to the DAppChain.
        // Usually you'd generate one private key per player, or let them provide their own.
        // In this sample we just generate a new key every time.
        var privateKey = CryptoUtils.GeneratePrivateKey();
        var publicKey = CryptoUtils.PublicKeyFromPrivateKey(privateKey);

        var contract = await GetContract(privateKey, publicKey);
        /**
         由于合約方法執(zhí)行需要有一定的時間,
         所以這里調(diào)用set方法的時候不能直接就調(diào)用get方法,
         有可能返回的是之前保存的值,不是最新的
         為了看到正確結(jié)果,可以分兩次執(zhí)行
         */
        await CallContract(contract, 123);//調(diào)用合約set方法保存一個值
        //await StaticCallContract(contract);//調(diào)用合約get方法獲取合約中保存的值
    }
}

如果你在調(diào)用get方法之后得到了你之前設(shè)置的值,那就說明你通過Unity與LoomSDK通信成功了!
接下來我們就可以編寫更復(fù)雜的合約了,我會繼續(xù)更新Unity游戲方面的教程,敬請期待!
下面是我的個人公眾號,我是一名Unity游戲開發(fā)工程師,也擅長小游戲開發(fā),如果有感興趣的請關(guān)注我!

頭號玩家云社區(qū)

Loom Network官方發(fā)布了一個賞金贏取Loom代幣獎勵的活動,推薦大家參加!
活動詳情:賞金和獎勵 —— 參與網(wǎng)絡(luò),贏取 LOOM 代幣

Loom Network官方的免費學(xué)習(xí)智能合約游戲編寫 DApp:https://cryptozombies.io/zh,一步一步教你如何編寫Solidity智能合約!

如果有阿里云服務(wù)器的新用戶推薦大家使用阿里云的券來體驗:高性能云服務(wù)器2折起

阿里云服務(wù)器2折起

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 摘要: 一、新產(chǎn)品發(fā)布1、云防火墻 商業(yè)化 發(fā)布云防火墻是一款云環(huán)境下的防火墻產(chǎn)品,首創(chuàng)了基于業(yè)務(wù)可視的結(jié)果,實現(xiàn)...
    貓耳呀閱讀 783評論 0 1
  • 引言 此文集主要用來記錄我的“天眼查”爬蟲生涯,給這個時刻2018/7/20賦上歷史的Flag。 代碼部分還沒上,...
    OzanShareing閱讀 3,386評論 2 7
  • 上個月,筆者對國內(nèi)兩大云廠商(阿里云和騰訊云)的云服務(wù)器、云數(shù)據(jù)庫和云存儲三種產(chǎn)品做了性能評測,算是對兩家的部分計...
    EarlGrey閱讀 1,848評論 2 7
  • 最近在看《一個人的朝圣》這本書,想起前段時間某個社群里發(fā)起的話題題目“2016年你想做的一件冒險的事...
    山風(fēng)嵐希閱讀 280評論 0 0
  • 身邊的人,你內(nèi)心的戰(zhàn)斗力呢! 身邊總有一些神奇的人,再經(jīng)歷了漫長的事情后,已經(jīng)成為了某個方向的老司機了,確再也開不...
    朋友你好嗎qing閱讀 265評論 0 1

友情鏈接更多精彩內(nèi)容