Create In-Game NFT Loot Boxes In Unity
In this guide, we'll show you how to use the Pack contract to allow users to open randomly selected NFTs as in-game assets. By the end, you'll:
- Deploy an Edition; a collection of NFTs representing your in-game items.
- Deploy the Pack contract; a collection of ERC1155 loot box NFTs.
- Bundle the in-game item NFTs into the packs/loot crates.
- Randomly select an NFT to be awarded to the user when they open a pack!
Here's a preview of what we'll be building:
You can use your own assets, or purchase these assets for $10 USD.
Let's get started!
Creating In-Game NFTs
First, we need to create the NFTs our players can receive when they open their loot boxes! Let's use the Edition contract to achieve this.
To begin, head to the Contracts page in your thirdweb Dashboard and hit "Deploy new contract":
You will be taken to our Explore page — where you can browse smart contracts built by the top protocols in web3 and deploy them in just a few clicks!
Note: You can also use the thirdweb CLI to set up a smart contract environment by running the below command from your terminal:
npx thirdweb create contract
This will take you through an easy-to-follow flow of steps for you to create your contract. Learn more about this in our CLI guide.
Otherwise, let's get back to Explore:
In here, select your smart contract of choice. For this guide, we're going to use the Edition contract to create our NFT collection:
Populate the metadata of your smart contract, like so:
When you're ready, click the Deploy Now
button to deploy your contract! We recommend using a test network before deploying to mainnet.
Nice! Our Edition contract is shipped to the blockchain! 🎉
Minting NFTs
Head to the NFTs
tab and click the + Mint
button to create your in-game items.
As you mint your NFTs, consider the rarity you want each item to have.
For example, I have created two NFTs in my collection:
- Red Gem: A common item, with
400
available supply. - Purple Gem: A rare item, with
100
available supply.
Assuming we bundle all the NFTs and release 1
NFT per pack, there will be an 80%
chance to open a red gem, and a 20%
chance to open a purple gem with 500
available loot boxes.
Now our NFTs are minted, it's time to bundle them into some pack NFTs!
Creating Loot Box NFTs
The Pack contract lets you bundle ERC20, ERC721, and ERC1155 tokens into new ERC1155 NFTs that act as randomized loot boxes.
The packs themselves are also ERC1155 NFTs, with an additional feature that allows you to "open" them. When they are opened, the user receives randomly selected token(s) from those bundled into the packs.
Deploy the Pack Contract
Head to the Pack page on the dashboard and click Deploy Now
.
Populate the metadata for your smart contract like so:
Click Deploy Now
, ensuring you select the same network as your Edition contract.
Bundling Items Into Packs
To mint our pack NFTs, we need to use the SDK to bundle our item NFTs into newly created pack NFTs!
To get started, clone our template repository by running the following command:
npx thirdweb@latest create --template pack-creation-script
This will set you up with a script and instructions on bundling your NFTs into packs! We'll quickly cover the key elements in this guide.
First, we configure our smart contract addresses, network and private key.
const EDITION_ADDRESS = "<your-edition-smart-contract-address>";
const PACK_ADDRESS = "<your-pack-smart-contract-address>";
const network: ChainOrRpc = "optimism-goerli";
const PRIVATE_KEY = process.env.PRIVATE_KEY!;
const lootBoxImageFileName = "lootbox.png";
We use these values to instantiate the SDK on behalf of our wallet, and then connect to the edition and pack smart contracts:
// Instantiate the SDK with our private key onto the network
const sdk = ThirdwebSDK.fromPrivateKey(PRIVATE_KEY, network);
const storage = new ThirdwebStorage();
// Connect to the edition and pack contracts
const edition = await sdk.getContract(EDITION_ADDRESS, "edition");
const pack = await sdk.getContract(PACK_ADDRESS, "pack");
Once connected, we grant the pack smart contract the approval
to bundle our NFTs from the edition contract:
// Set approval for the pack contract to transfer our edition NFTs (items)
await edition.setApprovalForAll(PACK_ADDRESS, true);
Then we call the create
function on our pack contract and specify how we want to bundle our tokens into packs:
await pack.create({
packMetadata: {
name: "Loot Box",
description: "Open this to reveal an in-game item!",
image: await storage.upload(
readFileSync(`${__dirname}/${lootBoxImageFileName}`)
),
attributes: {
artist: "@GabrielAguiarProd",
},
},
erc1155Rewards: [
// Bundle 400 Red Gem NFTs:
{
contractAddress: EDITION_ADDRESS,
tokenId: 0,
quantityPerReward: 1,
totalRewards: 400,
},
// Bundle 100 Red Gem NFTs:
{
contractAddress: EDITION_ADDRESS,
tokenId: 1,
quantityPerReward: 1,
totalRewards: 100,
},
],
// We specify 1 reward per pack, and there is 400+100 total rewards, so we will have 500 packs created.
rewardsPerPack: 1,
});
Finally, we run the script and create our packs by running the following command from our terminal:
npx ts-node src/index.ts
Voila! 🎉 We can now see on the dashboard our packs have been created:
Opening Packs
We can open packs directly from the Explorer
tab using the openPack
function:
But let's integrate this contract into Unity now to make it more interesting!
We recommend following the guide below to set yourself up with our Unity SDK before continuing:
First, we import Thirdweb
into our script so that we can instantiate the SDK:
using Thirdweb;
// ... other imports
public class LootBox : MonoBehaviour
{
private ThirdwebSDK sdk;
void Start()
{
sdk = new ThirdwebSDK("optimism-goerli");
animator = GetComponent<Animator>();
}
}
Now our sdk
value is instantiated when the game Start
s.
We'll want users to connect their wallets, and switch to the correct network whenever they attempt to open a pack. Let's create a simple function to perform and await both of these:
async Task<string> EnsureCorrectWalletState()
{
string address = await sdk.wallet.Connect();
await sdk.wallet.SwitchNetwork(420);
return address;
}
Let's connect to our pack contract so that we can open the packs:
async Task<Pack> GetPackContract()
{
await EnsureCorrectWalletState();
return sdk
.GetContract("0xd8Bd34726814855fB9cFF58fe5372558e3B411Cb")
.pack;
}
Finally, call the Open
function to open a pack from the connected wallet!
async Task<ERC1155Reward> OpenPack()
{
// Ensure the user is connected and on the correct network
await EnsureCorrectWalletState();
// Connect to the pack contract
Pack packContract = await GetPackContract();
// Open 1 quantity of pack ID 0
var result = await packContract.Open("0", "1");
// Return the NFT that we opened from the pack!
return result.erc1155Rewards[0];
}
When the user clicks, we call the OpenPack
function and kick off the animation:
if (Input.GetMouseButtonDown(0))
{
var openedPack = await OpenPack();
// ... Begin pack open animation now!
}
Wrapping Up
That's it! 🎉 Our packs are ready to be opened!
In this guide, we've successfully:
- Created in-game item NFTs
- Bundled them into a set of loot box NFTs
- Opened those loot box NFTs from within a C# in a Unity game!
If you have any questions, jump into our Discord server to speak with our team directly.