Neste guia, mostraremos como criar uma mecânica "burn-to-redeem" em um jogo Unity; onde os usuários queimam um NFT para reivindicar um NFT diferente!
No final, você aprenderá como:
Criar uma coleção NFT com lógica personalizada em Solidity usando ContractKit;
Implantar seu contrato na blockchain;
Permitir que os jogadores reivindiquem NFTs de dentro de um jogo Unity.
Vamos começar!
Pré-requisitos
Este é o quarto passo de uma série de várias partes sobre construção de jogos Web3 com o nosso Unity SDK.
Recomendamos a leitura dos guias anteriores antes de continuar:
Criando um contrato inteligente "Burn-To-Mint"
Escreveremos um contrato inteligente em Solidity usando ContractKit, que possui a seguinte lógica:
O contrato é uma coleção de NFTs ERC1155 que podem ser reivindicados.
Os usuários só podem reivindicar um NFT se possuírem um NFT de chave de acesso ( de nossa guia anterior).
A NFT de chave de acesso é gravada conforme o usuário afirma!
Criando o contrato inteligente
Para começar, usaremos a CLI para criar um novo projeto de contrato inteligente executando o seguinte comando:
npx thirdweb@latest create contract
Isso dará início a uma CLI interativa, onde você pode responder a uma série de perguntas para iniciar seu projeto. Configure seu projeto da mesma maneira:
Altere o diretório para o projeto recém-criado e abra-o no seu editor de texto. Dê uma olhada no arquivo contracts/Contract.sol
agora. Revisemos rapidamente o que criamos até agora com a CLI antes de continuarmos:
Estamos importando o contrato inteligente [ERC1155LazyMint](https://portal.thirdweb.com/contractkit/base-contracts/erc-1155/erc1155lazymint?ref=thirdweb)
à partir do ContractKit. Isso vem com recursos que nos permitem carregar metadados NFT e ter outras carteiras que os reivindicam.
Nós herdamos o contrato ERC1155LazyMint
de dentro de nosso contrato; o que significa que podemos acessar todas as funcionalidades do contrato base dentro deste:
contract Contract is ERC1155LazyMint
- Nós usamos o
constructor
para especificar coisas como oname
do nosso contrato inteligente. Essa lógica é executada quando implantamos ele na blockchain.
Excelente! Agora estamos preparados com a fundação da nossa coleção ERC1155 NFT.
Vamos adicionar nossa lógica personalizada a seguir.
Restringindo as cunhagens para apenas os portadores das chaves de acesso
Queremos apenas que os usuários que possuem um NFT de Chave de Acesso possam cunhar a partir deste contrato.
O contrato ERC1155LazyMint
que estamos herdando vem com uma função chamada verifyClaim
, que podemos substituir.
Esta função verifyClaim
é executada antes de uma carteira tentar reivindicar um NFT do nosso contrato. Se a função verifyClaim
falhar, o usuário não tem permissão para reivindicar um NFT.
Você pode ver a função no contrato base, que, por padrão, permite qualquer endereço da carteira reivindicar um NFT (desde que a função esteja vazia):
Dentro do nosso contrato inteligente, veremos o override
desta função:
function verifyClaim(
address _claimer,
uint256 _tokenId,
uint256 _quantity
) public view override {
// Aqui, nós checamos se o requisitante tem a chave de acesso
}
Em seguida, precisamos de uma maneira de verificar o saldo do endereço do _claimer
para garantir que eles possuam uma NFT de chave de acesso enquanto tentam reivindicar.
Vamos primeiro criar uma variável para armazenar nossa coleção NFT de chave de acesso dentro deste contrato e depois usá-la para verificar o saldo do solicitante.
Podemos implementar essa lógica em um processo de três etapas:
Crie uma variável para o nosso contrato inteligente de NFTs com chave de acesso.
No
constructor
, defina a variável acima para o endereço do contrato da nossa chave de acesso.Na função
verifyClaim
, use a funçãobalanceOf
no contrato da chave de acesso.
Nosso contrato inteligente agora se parece com isso:
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "@thirdweb-dev/contracts/base/ERC1155LazyMint.sol";
contract Contract is ERC1155LazyMint {
// Define uma variável para armazenar a chave de acesso ao contrato //inteligente
ERC1155LazyMint public accessKeysCollection;
constructor(
string memory _name,
string memory _symbol,
address _royaltyRecipient,
uint128 _royaltyBps,
// Passa para dentro oendereço da coleção de chave de acesso
address _accessKeysCollection
) ERC1155LazyMint(_name, _symbol, _royaltyRecipient, _royaltyBps) {
// Define a chave de acesso do contrato inteligente na variável criada
// (ERC1155LazyMint não é “exatamente” do tipo da edição //pré-implantada,
// mas tem a mesma função “balanceOf” que precisamos.
accessKeysCollection = ERC1155LazyMint(_accessKeysCollection);
}
function verifyClaim(
address _claimer,
uint256 _tokenId,
uint256 _quantity
) public view override {
// Avalia se o solicitante tem a chave de acesso
require(
accessKeysCollection.balanceOf(_claimer, 0) >= _quantity,
"Rejected: Claimer does not have access key"
);
}
}
Queimando o passe de acesso
Agora garantimos que o usuário possui uma NFT de chave de acesso antes de reivindicar, vamos queimar a chave de acesso quando o usuário receber seu NFT.
Podemos fazer isso substituindo a função _transferTokensOnClaim
do contrato base. Como o nome sugere, isso é chamado depois da função verifyClaim
ser executada, a fim de realmente cunhar o token para o endereço do solicitante.
Podemos ver isso no código fonte da função claim
no contrato base ERC1155LazyMint também. (Observe a ordem das funções que ocorrem dentro dela):
verifyClaim
_transferTokensOnClaim
Portanto, em nosso contrato inteligente, vamos substituir essa função para incluir nossa lógica burn
(lógica de queima):
function _transferTokensOnClaim(
address _receiver,
uint256 _tokenId,
uint256 _quantity
) internal override {
// Primeiro, queima a chave de acesso da carteira do usuário
accessKeysCollection.burn(
_receiver, // Queima do recebedor
0, // Token ID
_quantity// Quantidade de queima é a quantidade que estão exigindo
);
// Use o restante da lógica da função de reivindicação herdada
super._transferTokensOnClaim(_receiver, _tokenId, _quantity);
}
É isso para a nossa lógica de contrato inteligente! Vamos continuar para implantá-lo agora.
Implantando o contrato inteligente
Para implantar seu contrato, execute o seguinte comando:
npx thirdweb@latest deploy
Abra o URL no seu navegador e preencha os campos do construtor da seguinte maneira:
_name
: nome da sua coleção NFT;_symbol
: ticker para os tokens no contrato;_royaltyRecipient
: endereço da carteira para receber taxas de royalties em vendas secundárias;_royaltyBps
: quantos royalties você deseja receber. Por exemplo,500 = taxa de 5%._accessKeysCollection
: o endereço do contrato inteligente das suas chaves de acesso (veja abaixo):
Quando estiver pronto, implante seu contrato inteligente na mesma rede que suas chaves de acesso e aprove a transação Contract Deployment
:
Fazendo upload de metadados NFT
Depois de implantado, vá para a guia NFTs
e Single Upload
ou Batch Upload
, seus metadados NFT para os NFTs que representam seus personagens jogáveis no seu jogo.
Para o nosso jogo, os usuários podem cunhar um dos três veículos para dirigir, então aqui está como eu configurei os NFTs:
Tudo bem! Seu contrato inteligente está pronto!🥳 🎉 Vamos voltar ao Unity agora.
Reivindicando NFTs da Unity
Em nossa guia anterior, lemos a carteira do usuário para ver se eles possuíam um NFT de chave de acesso.
Agora, vamos permitir que os usuários que possuam uma NFT de chave de acesso cunhem um veículo NFT de sua escolha! No processo, eles queimarão sua NFT de chave de acesso.
Conectando carteiras de usuário
Siga o nosso guia "Add A Connect Wallet Button In Unity" para permitir que os usuários conectem sua carteira e verifiquem seu saldo para os NFTs das chaves de acesso primeiro.
Renderizando NFTs selecionáveis
Dentro do objeto do jogo ConnectedState
, crie um novo Empty Game Object
chamado NFTs
. Dentro do objeto do jogo NFTs
, crie um novo botão chamado Button0
.
Com algum estilo e ativos de demonstração, deve parecer algo assim até agora:
Agora, vamos criar uma nova função dentro do nosso script StartMenuManager
existente chamado RenderNFTs
; que renderizará nossos botões na interface do usuário SE o usuário tiver uma chave de acesso.
public void RenderNFTs()
{
// No ConnectedState GameObject, encontre o GameObject "NFTs"
GameObject nfts = ConnectedState.transform.Find("NFTs").gameObject;
// Define o NFTs GameObject como ativo
nfts.SetActive(true);
}
Reivindicando NFTs com um clique
Agora, o usuário poderá ver os botões caso possua um NFT de chave de acesso.
Queremos que cada botão reivindique o respectivo NFT quando clicado, então vamos adicionar outra função chamada SelectVehicleToMint
que aceita um parâmetro tokenId
:
public async void SelectVehicleToMint(string tokenId)
{
// Conecta o contrato inteligente aos ‘veículos’.
Contract vehicleContract =
sdk.GetContract("0xc1B3337f08a6eF19DFc8C46731a0B20b7D97E15F");
// Conecta-se ao contrato inteligente para acessar as chaves.
Contract accessKeyContract =
sdk.GetContract("0x69BC6d095517951Df17f70f38746Bc27CE1C8A62");
// Precisa conceder aprovação do contrato para queimar nossos primeiros nfts.
//Isso só é necessário se você estiver usando a lógica queimar para ganhar.
//isso NÃO é necessário para reivindicar um contrato pré-criado.
await accessKeyContract
.Write("setApprovalForAll",
new List<object> {
// The address of the vehicle contract
"0xc1B3337f08a6eF19DFc8C46731a0B20b7D97E15F",
// True to grant approval
true
});
// Reivindique 1 veículo de sua escolha.
await vehicleContract.ERC1155.Claim(tokenId, 1);
}
Para renderizar condicionalmente os botões quando o usuário conectar sua carteira, adicione a seguinte lógica ao final da função ConnectWallet
public async void ConnectWallet()
{
// ... lógica existente aqui
// Nova lógica:
if (balanceFloat > 0)
{
RenderNFTs();
}
}
Finalmente, vamos definir o manipulador OnClick
do objeto Button0
que fizemos para chamar o SelectVehicleToMint
com o ID do token do veículo vermelho:
Aqui está o que temos até agora:
https://blog.thirdweb.com/content/media/2022/11/2022-11-16-15-46-10.mp4
Agora, vamos duplicar nosso botão para que o usuário possa selecionar um dos três veículos:
Lembre-se de alterar o argumento da função OnClick
para o ID do token do veículo (1 para a van verde) e (2 para o carro azul):
Finalizando
É isso aí! 🎉
Implementamos com sucesso uma maneira de os usuários cunharem NFTs em nosso jogo Unity!
Como bônus, queimamos os NFTs da Chave de Acesso da etapa anterior do processo.
Tem perguntas? Entre no nosso Discord para falar diretamente com nossa equipe!
Este artigo foi escrito por Jarrod Watts e traduzido por Adriano P. de Araujo. O original em inglês pode ser encontrado aqui.
Oldest comments (2)
Olá brother, tudo bem com vcs? Espero que sim.
Estou procurando algum artigo q mostre como usar os atributos de um nft pra aplicar no personagem 3d dentro da unity... Estou criando um game free e uma coleção de nfts com variação do personagem. Obrigado e parabéns pelo ótimo trabalho.
Opa @moonkeeperdev !
Massa demais, então eu apenas traduzi o artigo, não manjo tanto dessa área rs,
Acho que vc conseguirá informações no nosso 👉 discord, com certeza alguém pode te ajudar lá ^^