How to Make A BEEG Production On-Chain Game with Unity

2025-07-14
How to Make A BEEG Production On-Chain Game with Unity

Building a blockchain-based game like BEEG with Unity is a thrilling way to jump into GameFi, blending gaming with decentralized finance. This guide walks you through creating an on-chain game, inspired by a Rock, Paper, Scissors demo, using ChainSafe’s web3.unity SDK and Chainlink’s Verifiable Random Function (VRF) to ensure fairness. 

We’ll tailor the process for a BEEG-style game powered by the BEEG coin, keeping it transparent and fun. Let’s dive in!

sign up on Bitrue and get prize

Want to trade crypto while reading our latest news? Head over to Bitrue and explore your options today!

What You Need to Start

Before you get going, make sure you have:

  • Unity: Install the latest Unity version for full compatibility.

  • MetaMask Wallet: Set up MetaMask for blockchain transactions with BEEG coin.

  • Testnet AVAX: Grab testnet AVAX on the Avalanche Fuji Testnet for testing.

  • web3.unity SDK: Follow ChainSafe’s docs to download the SDK, create a project on their dashboard, and add your project ID to Unity’s network settings.

With these tools, you’re ready to build a BEEG on-chain game!

Read Also: BEEG Coin vs. Beeg.com: Speculation or Streaming?

Setting Up Your Unity Project

Import Game Assets

Choose or create images for your game’s core elements, like BEEG project characters or items. Place them in an “Images” folder in Unity and convert them to 2D sprites.

Build the Game Canvas

  • Add a Canvas to your Unity scene.

  • Insert Image components for each game element (e.g., three BEEG-inspired options).

  • Add a Button component to each image to make them interactive.

  • Include a Text element at the top of the canvas to display game results.

Create a GameManager

  • Add an empty GameObject named “GameManager” at the top of your hierarchy.

  • Attach a Manager Script to handle game logic and BEEG coin blockchain interactions.

Manajer script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class Manager : MonoBehaviour
{
    // Text element to display the result of the game.
    public TMP_Text Result;
    // Image to display the opponent's choice visually.
    public Image OpChoice;
    // Array to store the choices: Rock, Paper, Scissors.
    public string[] Choices;
    // Sprites for Rock, Paper, and Scissors to visually represent choices.
    public Sprite Rock, Paper, Scissors;

    // Called when a player clicks a button corresponding to their choice.
    public void Play(string myChoice)
    {
        // Set the opponent's choice to always defeat the user's choice.
        string opponentChoice = GetWinningChoice(myChoice);

        // Update the opponent's choice sprite and the result text.
        UpdateOpponentChoice(opponentChoice);
        UpdateResult(myChoice, opponentChoice);
    }

    // Returns the choice that will defeat the user's choice.
    private string GetWinningChoice(string myChoice)
    {
        switch (myChoice)
        {
            case "Rock":
                return "Paper"; // Paper beats Rock
            case "Paper":
                return "Scissors"; // Scissors beats Paper
            case "Scissors":
                return "Rock"; // Rock beats Scissors
            default:
                return "Rock"; // Default choice
        }
    }

    // Updates the opponent's displayed choice.
    private void UpdateOpponentChoice(string choice)
    {
        switch (choice)
        {
            case "Rock":
                OpChoice.sprite = Rock;
                break;
            case "Paper":
                OpChoice.sprite = Paper;
                break;
            case "Scissors":
                OpChoice.sprite = Scissors;
                break;
        }
    }

    // Updates the result to always display "You Lose!"
    private void UpdateResult(string myChoice, string opponentChoice)
    {
        Result.text = "You Lose!";
    }
}
  • In the Inspector, drag your game elements (images, buttons) into the matching fields in the GameManager script.

  • For each button’s OnClick function, link the GameManager and assign actions (e.g., “Play” with selections like “Option 1,” “Option 2,” etc.).

Build for WebGL

Go to Build Settings, switch to WebGL, and build your game. You’ll have a basic game, but without fairness measures, outcomes might be predictable, causing players to lose trust.

Ensuring Fairness with Chainlink VRF

To make your BEEG game reliable, use Chainlink VRF for tamper-proof random outcomes, ensuring players trust the game when using BEEG coin.

Set Up Chainlink VRF

  • Visit the Chainlink Dashboard and create a subscription to fund VRF calls.

  • Add 0.1 AVAX to your subscription.

  • Note your Subscription ID for smart contract deployment.

Deploy a Smart Contract

  • Go to Remix to deploy your contract.

  • Use a script to request a random number (0–2) from Chainlink VRF for the opponent’s choice.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {VRFConsumerBaseV2Plus} from "@chainlink/contracts@1.2.0/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";
import {VRFV2PlusClient} from "@chainlink/contracts@1.2.0/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";

contract SimpleRandomNumber is VRFConsumerBaseV2Plus {
    event RequestSent(uint256 requestId);
    event RandomNumberGenerated(uint256 requestId, uint256 randomNumber);

    struct RequestStatus {
        bool fulfilled; // Whether the request has been fulfilled
        uint256 randomResult; // Random number between 0 and 2
    }
    mapping(uint256 => RequestStatus) public s_requests; // Mapping requestId to request status

    uint256 public s_subscriptionId;
    uint256 public lastRequestId;

    bytes32 public keyHash =
        0xc799bd1e3bd4d1a41cd4968997a4e03dfd2a3c7c04b695881138580163f42887;

    uint32 public callbackGasLimit = 100000;
    uint16 public requestConfirmations = 3;
    uint32 public numWords = 1; // Request one random number

    /**
     * HARDCODED FOR FUJI AVALANCHE
     * COORDINATOR: 0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE
     */
    constructor(
        uint256 subscriptionId
    ) VRFConsumerBaseV2Plus(0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE) {
        s_subscriptionId = subscriptionId;
    }

    /**
     * @notice Request a random number using Sepolia ETH as payment.
     */
    function requestRandomNumber() external returns (uint256 requestId) {
        // Always use Sepolia ETH for payment
        requestId = s_vrfCoordinator.requestRandomWords(
            VRFV2PlusClient.RandomWordsRequest({
                keyHash: keyHash,
                subId: s_subscriptionId,
                requestConfirmations: requestConfirmations,
                callbackGasLimit: callbackGasLimit,
                numWords: numWords,
                extraArgs: VRFV2PlusClient._argsToBytes(
                    VRFV2PlusClient.ExtraArgsV1({
                        nativePayment: true // Always use native token (Sepolia ETH)
                    })
                )
            })
        );

        s_requests[requestId] = RequestStatus({
            fulfilled: false,
            randomResult: 0 // Initialize to 0 until fulfilled
        });

        lastRequestId = requestId;
        emit RequestSent(requestId);
        return requestId;
    }

    /**
     * @notice Callback function called by Chainlink VRF to fulfill the random number request.
     * @param _requestId The ID of the randomness request
     * @param _randomWords The array of random words generated
     */
    function fulfillRandomWords(
        uint256 _requestId,
        uint256[] calldata _randomWords
    ) internal override {
        require(s_requests[_requestId].fulfilled == false, "Request already fulfilled");

        // Compute random number between 0 and 2
        uint256 randomResult = _randomWords[0] % 3;

        // Update the request status
        s_requests[_requestId].fulfilled = true;
        s_requests[_requestId].randomResult = randomResult;

        emit RandomNumberGenerated(_requestId, randomResult);
    }

    /**
     * @notice Get the status and result of the last random number request.
     * @param _requestId The ID of the randomness request
     */
    function getRandomNumber(
        uint256 _requestId
    ) external view returns (bool fulfilled, uint256 randomNumber) {
        RequestStatus memory request = s_requests[_requestId];
        require(request.fulfilled, "Request not yet fulfilled");
        return (request.fulfilled, request.randomResult);
    }
}
  • Compile the code, select Injected Provider (MetaMask), input your Subscription ID, and deploy.

  • Copy the Contract Address from Remix and add it as a consumer in the Chainlink Dashboard.

  • Test by requesting a random number. A successful transaction means VRF is ready!

Read Also: Is BEEG Still Worth Analyzing? Looking at Its Products

Integrate VRF into Unity

Update your Manager Script to use VRF:

  • Add required namespaces for blockchain integration. 

using ChainSafe.Gaming.UnityPackage;
using ChainSafe.Gaming.UnityPackage.Connection;
using ChainSafe.Gaming.Web3;
using ChainSafe.Gaming.Evm.Contracts.Custom;
using System.Numerics;
  • Replace local random number generation with VRF calls. 

[SerializeField] private string ContractAddress;

    private vrf _vrf;
    private bool _randomNumberReady = false;
    private BigInteger _randomNumber;

    private void Awake()
    {
        Web3Unity.Web3Initialized += Web3UnityOnWeb3Initialized;
    }

    private async void Web3UnityOnWeb3Initialized((Web3 web3, bool isLightWeight) obj)
    {
        // Initialize the VRF contract.
        _vrf = await obj.web3.ContractBuilder.Build<vrf>(ContractAddress);

        // Subscribe to the random number generated event.
        _vrf.OnRandomNumberGenerated += OnRandomNumberGenerated;
    }

    private void OnDestroy()
    {
        Web3Unity.Web3Initialized -= Web3UnityOnWeb3Initialized;

        // Unsubscribe from the event.
        if (_vrf != null)
        {
            _vrf.OnRandomNumberGenerated -= OnRandomNumberGenerated;
        }
    }
  • Paste your contract address into Unity’s contract address component.

  • Add the Event Service Adapter to the Web3Unity object and enable Force Event Polling for VRF responses.

Now, player choices trigger VRF requests, ensuring fair outcomes for BEEG coin-based gameplay.

Connecting Player Wallets

Wallets let players interact with the BEEG coin on the blockchain securely.

  • Set Up Wallet Integration

  • Select the Web3Unity object in Unity’s hierarchy.

  • In the Inspector, go to Connection Handler and add MetaMask as a provider.

  • Remove unneeded components like SDKCallSamples and Scroller.

Test Wallet Interaction

  • Run the game and connect your MetaMask wallet with BEEG coin.

  • Choose an option and confirm the transaction.

  • Check the browser’s developer console to verify the VRF request.

Wait 20–30 seconds for the transaction to process, and see the opponent’s choice.

For transparency, you can:

  • Display transaction details in-game.

  • Link to the contract on a block explorer like Snowtrace for players to verify BEEG coin transactions.

Read Also: How to Chase Your Beeg Trading Dreams: A Complete Guide

Why Blockchain Powers BEEG

Using blockchain, as shown in the Rock, Paper, Scissors example, ensures your BEEG game is fair and transparent. Chainlink VRF and on-chain records build trust, letting players use BEEG coin confidently in competitive or economic gameplay, a core feature of GameFi.

Conclusion

Creating a BEEG on-chain game with Unity is an awesome way to explore GameFi with BEEG coin. By setting up Unity, integrating Chainlink VRF, and connecting wallets, you build a fair, engaging, and blockchain-powered game. The Rock, Paper, Scissors demo shows how to ensure trust, which you can adapt for BEEG’s unique style. Start experimenting with the web3.unity SDK and bring your BEEG coin-powered game to life!

FAQ

How do I add Chainlink VRF to my Unity game?

Create a subscription on Chainlink, deploy your smart contract via Remix with VRF logic, then plug the contract address into Unity and enable event polling.

What’s needed to connect MetaMask in Unity?

Add MetaMask in the Web3Unity object’s Connection Handler, remove unused components, and test wallet link in play mode.

How do I trigger randomness for opponent choices?

Replace local RNG in your Manager Script with a VRF request from your deployed contract—results come back on-chain for full transparency.

Can I test BEEG coin interactions without spending real AVAX?

Yes! Use Avalanche Fuji Testnet, grab testnet AVAX, and fund your Chainlink VRF subscription for gas-free testing.

How do I verify if VRF is working in my Unity build?

Connect MetaMask, select an option, then check the dev console or Snowtrace for VRF transaction logs and confirmed opponent moves.


 

Bitrue Official Website: 

Website: https://www.bitrue.com/

Sign Up: https://www.bitrue.com/user/register

Disclaimer: The views expressed belong exclusively to the author and do not reflect the views of this platform. This platform and its affiliates disclaim any responsibility for the accuracy or suitability of the information provided. It is for informational purposes only and not intended as financial or investment advice.

Disclaimer: The content of this article does not constitute financial or investment advice.

Register now to claim a 1012 USDT newcomer's gift package

Join Bitrue for exclusive rewards

Register Now
register

Recommended

Crypto Profit Calculator: How to Measure Your Gains or Losses in Crypto
Crypto Profit Calculator: How to Measure Your Gains or Losses in Crypto

Learn how a crypto profit calculator works, its benefits, and how to use it to track gains or losses from your cryptocurrency investments with real examples.

2025-07-16Read