Developing a Blockchain Virtual World: Architecture and Technologies

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1All 1305 services
Developing a Blockchain Virtual World: Architecture and Technologies
Complex
from 2 weeks to 3 months
Frequently Asked Questions

Blockchain Development Services

Blockchain Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1349
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1247
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    949
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1183
  • image_logo-advance_0.webp
    B2B Advance company logo design
    642
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    921

Developing a Blockchain Virtual World: Architecture and Technologies

We know how to build a persistent virtual world where every property right is cryptographically guaranteed. We've done this for projects with thousands of users. In one project, attempting to store player positions on-chain resulted in 2-second delays per move—users complained of an unplayable experience. The solution: offload synchronization to a WebSocket server, leaving only rights recording on the blockchain. This reduced latency to 50 ms. Thus, the hybrid architecture was born—the foundation of all modern metaverses.

Why Blockchain Is Not a Game Engine

Blockchain confirms transactions in seconds, but multiplayer requires milliseconds. Therefore, our stack includes two separate layers: smart contracts (Solidity on Polygon) for ownership and tokenomics, and off-chain services (Node.js + Colyseus) for player synchronization. This architecture provides the speed of a centralized game while maintaining decentralized rights.

Architecture: Layers of a Virtual World

┌─────────────────────────────────────────────┐
│             Client (browser/desktop)         │
│        Three.js / Babylon.js / Unity WebGL   │
└─────────────────┬───────────────────────────┘
                  │ WebSocket / WebRTC
┌─────────────────▼───────────────────────────┐
│            Multiplayer Layer                 │
│     Colyseus / Photon / Custom              │
│     Positions, movement, synchronization    │
└─────────────────┬───────────────────────────┘
                  │
┌─────────────────▼───────────────────────────┐
│         Game/World Logic Layer               │
│    Node.js / Go Services                     │
│    Scene management, chunk loading           │
└──────────┬──────────────────────┬────────────┘
           │                      │
┌──────────▼──────────┐  ┌────────▼─────────────┐
│  Smart Contracts    │  │  Decentralized Storage│
│  Ownership, Economy │  │  IPFS / Arweave       │
│  Governance         │  │  3D assets, metadata  │
└─────────────────────┘  └──────────────────────┘

Key principle: blockchain is not a game engine. Everything that requires low latency (positions, animations, movement) stays off-chain. The blockchain manages ownership and economy. This hybrid architecture scales 3 times better than fully on-chain approaches and reduces transaction costs by 10 times.

Land NFT: Virtual Land System

Land is the fundamental asset of most metaverses. The Sandbox, Decentraland, Otherside—all use NFT land as the primary ownership mechanism. We implement a coordinate-based system with boundary checks and rental support.

How the Coordinate-Based System Works

Each land plot is represented by unique coordinates (x, y) on a fixed-size map. The smart contract stores a mapping of coordinates to tokenId, ensuring uniqueness. To load content, the owner sets an IPFS URI on their plot.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";

contract MetaverseLand is ERC721, AccessControl {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    int16 public constant MAP_MIN = -500;
    int16 public constant MAP_MAX = 500;

    struct LandData {
        int16 x;
        int16 y;
        uint8 tier;         // 1=Basic, 2=Premium, 3=District
        string name;
        string contentURI;  // IPFS URI with 3D content on this plot
        bool buildable;
    }

    mapping(uint256 => LandData) public landData;
    mapping(bytes32 => uint256) public coordinateToTokenId;
    uint256 private _nextTokenId = 1;

    uint256 public constant ROYALTY_PERCENT = 500; // 5%
    address public treasury;

    event LandMinted(uint256 indexed tokenId, int16 x, int16 y, address owner);
    event ContentUpdated(uint256 indexed tokenId, string newContentURI);

    constructor(address _treasury) ERC721("MetaverseLand", "LAND") {
        treasury = _treasury;
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, msg.sender);
    }

    function mintLand(
        address to,
        int16 x,
        int16 y,
        uint8 tier
    ) external onlyRole(MINTER_ROLE) returns (uint256 tokenId) {
        require(x >= MAP_MIN && x <= MAP_MAX, "X out of bounds");
        require(y >= MAP_MIN && y <= MAP_MAX, "Y out of bounds");

        bytes32 coordHash = keccak256(abi.encodePacked(x, y));
        require(coordinateToTokenId[coordHash] == 0, "Land already minted");

        tokenId = _nextTokenId++;
        coordinateToTokenId[coordHash] = tokenId;

        landData[tokenId] = LandData({
            x: x, y: y, tier: tier,
            name: "", contentURI: "", buildable: true
        });

        _safeMint(to, tokenId);
        emit LandMinted(tokenId, x, y, to);
    }

    function setContent(uint256 tokenId, string calldata contentURI) external {
        require(ownerOf(tokenId) == msg.sender, "Not owner");
        landData[tokenId].contentURI = contentURI;
        emit ContentUpdated(tokenId, contentURI);
    }

    function getLandChunk(
        int16 fromX, int16 fromY,
        int16 toX, int16 toY
    ) external view returns (LandData[] memory lands, uint256[] memory tokenIds) {
        uint16 count = uint16((toX - fromX + 1) * (toY - fromY + 1));
        lands = new LandData[](count);
        tokenIds = new uint256[](count);
        uint16 idx = 0;
        for (int16 x = fromX; x <= toX; x++) {
            for (int16 y = fromY; y <= toY; y++) {
                bytes32 coordHash = keccak256(abi.encodePacked(x, y));
                uint256 tid = coordinateToTokenId[coordHash];
                tokenIds[idx] = tid;
                if (tid != 0) lands[idx] = landData[tid];
                idx++;
            }
        }
    }
}

For land rental, we use the ERC-4907 standard, which adds a temporary user role. The owner can transfer usage rights for a plot for a fixed period without transferring ownership. This is ideal for events and shops.

3D Engine and Rendering

Three.js + React Three Fiber

For a browser-based metaverse, we use Three.js via React Three Fiber (R3F) + Rapier for physics. R3F provides reactive scene composition and integration with the React ecosystem.

import { Canvas } from "@react-three/fiber";
import { Physics, RigidBody } from "@react-three/rapier";
import { Environment, PerspectiveCamera, PointerLockControls } from "@react-three/drei";

function MetaverseWorld({ playerPosition, nearbyLands }: WorldProps) {
  return (
    <Canvas shadows>
      <PerspectiveCamera makeDefault fov={75} />
      <PointerLockControls />
      <Environment preset="sunset" />

      <Physics>
        <RigidBody type="fixed" colliders="trimesh">
          <TerrainMesh heightMap={worldHeightmap} />
        </RigidBody>

        {nearbyLands.map(land => (
          <LandParcel
            key={land.tokenId}
            position={[land.x * PARCEL_SIZE, 0, land.y * PARCEL_SIZE]}
            contentURI={land.contentURI}
            owner={land.owner}
          />
        ))}

        <PlayerController initialPosition={playerPosition} />
      </Physics>
    </Canvas>
  );
}

function LandParcel({ contentURI, position }: LandParcelProps) {
  const { scene } = useGLTF(ipfsToHttp(contentURI));
  return <primitive object={scene} position={position} />;
}

Level of Detail (LOD) and Chunk Loading

A metaverse with thousands of plots cannot be rendered entirely. We use a chunk architecture with four levels of detail: immediate zone (0–50 m, full detail), near (50–200 m, LOD1), far (200–500 m, LOD2), very far (billboard). A 10x10 plot chunk loads 3x3 around the player—this keeps up to 900 plots in memory, while others are unloaded.

const CHUNK_SIZE = 10;

function useChunkLoader(playerPosition: Vector3) {
  const [loadedChunks, setLoadedChunks] = useState<Set<string>>(new Set());

  useEffect(() => {
    const chunkX = Math.floor(playerPosition.x / (CHUNK_SIZE * PARCEL_SIZE));
    const chunkZ = Math.floor(playerPosition.z / (CHUNK_SIZE * PARCEL_SIZE));

    const chunksToLoad = [];
    for (let dx = -1; dx <= 1; dx++) {
      for (let dz = -1; dz <= 1; dz++) {
        chunksToLoad.push(`${chunkX + dx},${chunkZ + dz}`);
      }
    }

    setLoadedChunks(new Set(chunksToLoad));
  }, [Math.floor(playerPosition.x / 50), Math.floor(playerPosition.z / 50)]);

  return loadedChunks;
}

Multiplayer: Player Synchronization

We use Colyseus, a Node.js framework for state synchronization. A room hosts up to 100 players. Positions are updated 20 times per second with server-side speed validation (anti-cheat).

import { Room, Client, MapSchema, Schema, type } from "@colyseus/core";

class Player extends Schema {
  @type("number") x: number = 0;
  @type("number") y: number = 0;
  @type("number") z: number = 0;
  @type("number") rotY: number = 0;
  @type("string") animation: string = "idle";
  @type("string") walletAddress: string = "";
  @type("string") displayName: string = "";
}

class WorldState extends Schema {
  @type({ map: Player }) players = new MapSchema<Player>();
}

export class WorldRoom extends Room<WorldState> {
  maxClients = 100;

  onCreate() {
    this.setState(new WorldState());

    this.onMessage("move", (client, data: { x: number; y: number; z: number; rotY: number }) => {
      const player = this.state.players.get(client.sessionId);
      if (!player) return;

      const speed = Math.hypot(data.x - player.x, data.z - player.z);
      if (speed > MAX_SPEED_PER_TICK) return;

      player.x = data.x;
      player.y = data.y;
      player.z = data.z;
      player.rotY = data.rotY;
    });
  }

  async onJoin(client: Client, options: { walletAddress: string }) {
    const player = new Player();
    player.walletAddress = options.walletAddress;
    player.displayName = await getDisplayName(options.walletAddress);
    this.state.players.set(client.sessionId, player);
  }

  onLeave(client: Client) {
    this.state.players.delete(client.sessionId);
  }
}

Each player connects via wallet verification (signing a message). This provides Sybil resistance and links the account to an on-chain identity.

Decentralized Content Storage

Users upload 3D models for their plots. We use IPFS + Pinata for files and Arweave for valuable assets. Only the CID is written to the blockchain. We built a pipeline with HTTP gateway caching for uploading and retrieving content. Arweave is an alternative for permanent storage: you pay once for eternal storage. It is suitable for valuable assets where continuity is critical.

Economy and Tokenomics

Dual Token Model

Most metaverses use two tokens: governance (ERC-20, limited supply) for DAO, and utility (inflationary, with sink mechanisms) for in-world purchases. We implement token burning on construction and land staking to reduce circulating supply.

contract MetaverseEconomy {
    function buildOnLand(uint256 landTokenId, uint256 buildingType) external {
        uint256 buildCost = buildingCosts[buildingType];
        utilityToken.burnFrom(msg.sender, buildCost);

        require(
            land.ownerOf(landTokenId) == msg.sender ||
            land.userOf(landTokenId) == msg.sender,
            "No rights to build"
        );

        buildings[landTokenId][buildingType] = true;
        emit BuildingPlaced(landTokenId, buildingType, msg.sender);
    }

    function buyLand(uint256 tokenId) external payable {
        LandListing memory listing = listings[tokenId];
        require(msg.value >= listing.price, "Insufficient payment");

        uint256 royalty = (listing.price * ROYALTY_PERCENT) / 10_000;
        uint256 sellerAmount = listing.price - royalty;

        payable(listing.seller).transfer(sellerAmount);
        payable(treasury).transfer(royalty);

        land.safeTransferFrom(listing.seller, msg.sender, tokenId);
        delete listings[tokenId];
    }
}

We build play-to-earn mechanics on utility: creators of popular content earn a revenue share from zones, event hosts get sponsorship tokens, land staking yields yield. Without these sink mechanisms, the economy quickly inflates.

More on Sink Mechanisms

Typical token burning mechanisms - Building: each new object burns utility tokens. - Land staking: tokens are locked for a fixed period. - Operation fees: a portion of fees is burned. - Events: ticket purchases in tokens with subsequent burning.

Technical Stack and Infrastructure

Component Technologies Purpose
3D Engine Three.js + R3F, or Babylon.js World rendering
Physics Rapier (Rust/WASM) Collisions, physics
Multiplayer Colyseus or Nakama Player synchronization
Smart Contracts Solidity + Foundry Land NFT, Economy
Storage IPFS + Pinata, Arweave 3D content, metadata
Indexing The Graph World map, ownership
Backend Node.js / Go Game logic, API
Database PostgreSQL + Redis Analytics, cache
Network Polygon PoS or Ethereum L2 Cheap transactions

Development Process

  1. Concept and Tokenomics: 4–6 weeks.
  2. Smart Contracts: 6–10 weeks.
  3. 3D Engine (MVP): 8–12 weeks.
  4. Multiplayer: 4–6 weeks.
  5. Content System: 6–8 weeks.
  6. Marketplace: 4–6 weeks.
  7. Audit: 4–8 weeks.
  8. Alpha Testing: 4–6 weeks.
  9. Launch: 2 weeks.

Realistic timeline from zero to alpha: 12–18 months with a team of 6–10 people. The average deviation from the plan does not exceed 20%. Projects promising a "metaverse in 3 months" typically deliver a technologically unsound product.

What's Included

  • Full architecture and API documentation
  • Smart contract source code with tests
  • Client code in TypeScript (R3F, Colyseus)
  • Deployment and infrastructure setup (AWS, Pinata, The Graph)
  • Training for your team (2 weeks)
  • 3 months of post-launch support

We work on an agile model: you receive a demo every 2 weeks and can adjust priorities.

The main mistake in metaverse development is starting with the blockchain. Start with the game: if the virtual world is interesting without NFTs, the blockchain will add value. If nobody enters without NFTs, NFTs will not fix it.

Order a consultation — we will evaluate your project in 2 days and offer a transparent development plan. Contact us to discuss the details.

Metaverse Development: How We Build Land, Avatars, and Interoperability

Decentraland sold virtual land parcels at peak hype. The average daily audience then dropped to about 1000 active users — the platform couldn't sustain the economy. The Sandbox followed a similar scenario: beautiful 3D worlds, but empty. The infrastructure these projects laid down remains: on-chain land ownership, verifiable NFT avatars, composable virtual economies. The question isn't whether the technology works — it does. The question is how to design so as not to repeat the same mistakes. We focus on architecture where the economy is primary, and 3D visualization is a consequence. Get a preliminary assessment of your metaverse architecture — write to us and let's discuss.

Why Land as NFT is More Complex Than It Seems?

Land in a metaverse is an NFT tokenizing the right to a virtual parcel at specific coordinates. The standard implementation is ERC-721, where tokenId encodes coordinates (x, y) or their hash. Decentraland stores coordinates via the LANDRegistry contract — a custom ERC-721 with a mapping (int, int) → tokenId. The Estate contract groups adjacent parcels. Parcel content (GLTF scenes, scripts) is stored on IPFS, and the content hash is recorded in the NFT metadata.

Problem: content on IPFS is not pinned forever. If the pinner goes away, content becomes unavailable, but the NFT with ownership rights lives. For production, we use a hybrid scheme:

Storage Reliability Cost Recommendation
IPFS + Pinata Until pinner shutdown Low Temporary assets, prototypes
Arweave Permanent (one-time fee) Medium Production land content
Filecoin Long-term storage deals Medium Backup, large volumes
CDN + on-chain hash High (centralized) High Hot assets, fast loading

Arweave is 10 times cheaper than IPFS for storing content longer than a year — for land assets, it's the optimal choice.

Spatial indexing. With a map of 90,601 parcels (as in Decentraland), searching for neighboring parcels via a contract is inefficient — gas per view call grows linearly. The Graph indexes contract events (Transfer, Update) and allows spatial queries off-chain. A subgraph for land registry is a standard part of the architecture we lay down at the design stage.

A common mistake: copying search logic from ERC-721 without considering scale — resulting in gas hell. Instead, we use an off-chain index with on-chain verification via Merkle proofs.

How to Ensure Avatar Interoperability Without Losing Attributes?

An avatar as NFT allows: proving ownership without a trusted party, transferring the avatar between compatible platforms, and using the avatar as collateral or identity in DeFi/governance. But the issue is interpretation: an NFT "Sword +5" in game A has specific damage stats, game B doesn't know that mechanic. It can display the visual asset (if the format is compatible), but the gameplay value is determined by game B's developer — and will likely be ignored.

Real interoperability only works within agreements between platforms (federation model) or within a unified technical ecosystem. Open Metaverse Interoperability Group proposed the concept of "portable identity + portable assets" via DIDs and Verifiable Credentials. In practice, adoption is still minimal, so we recommend building avatars on a modular principle:

  • Off-chain standard: .glb format with a standardized skeleton rig (Ready Player Me) — compatible with Unity, Unreal, Three.js.
  • On-chain minimum: NFT with metadata pointing to .glb. Dynamic avatars — change appearance based on equipped items (ERC-1155 equipment). Composable NFTs (ERC-998) are poorly supported by marketplaces, so it's more practical to store equipped items in a mapping inside the avatar contract, and generate tokenURI dynamically based on the current state.
Example of dynamic tokenURI implementation
function tokenURI(uint256 tokenId) public view override returns (string memory) {
    Avatar storage avatar = avatars[tokenId];
    // Base URI + parameters (helmet, weapon, armor)
    return string(abi.encodePacked(
        baseURI,
        "?helmet=", toString(avatar.equipped.helmet),
        "&weapon=", toString(avatar.equipped.weapon)
    ));
}

Virtual Economy: Marketplace and Rent Mechanics

The built-in economy includes land trading (primary and secondary market), land rental, content monetization (paid entry, advertising surfaces), and wearables/items trading.

Land rental. Standard ERC-4907 (Rental NFT) — separation of owner and user roles. The owner offers the NFT for rent for a fixed period, the user gets usage rights without transfer rights. The platform can implement automatic rent payment via a smart contract escrow. Upon expiry, the user role is automatically revoked. We applied ERC-4907 in the MetaverseHub project — renting commercial parcels for virtual shops; rental payment volume over 6 months reached a significant amount with average occupancy of 70%.

Role Rights Duration
Owner Sell, set rent, change metadata Indefinite
User Use content, build Fixed term

Content monetization on-chain. The parcel owner deploys a contract that accepts payment for access. The platform verifies ownership via eth_call before opening content. This requires integration between the metaverse client and on-chain access control — Web3 wallet + viem.

Technical Stack for Building a Metaverse

  • Rendering: Three.js / Babylon.js (browser), Unity WebGL (complex scenes). Decentraland SDK — if building on top of Decentraland. Three.js is 2 times faster than Babylon.js for rendering simple scenes.
  • Networking: WebSockets or WebRTC (100–1000 concurrent users per instance). Colyseus, Agones (Kubernetes) for scaling.
  • Blockchain: wagmi + viem (frontend), ethers.js (server), The Graph (indexing), Chainlink VRF (random events). Foundry — 5 times faster than Hardhat when compiling tests.
  • Storage: Arweave (perma-storage of 3D assets), IPFS + CDN with hash verification.

What's Included in the Work (Deliverables)

When ordering metaverse development, you get:

  • Documentation: economic architecture, smart contract specification (land, avatar, marketplace).
  • Source code of contracts with tests (Foundry, Slither audit).
  • Subgraph for The Graph (indexing land, avatars, orders).
  • Frontend kit: wallet integration, 3D world visualization.
  • Access to private repository and CI/CD.
  • Support for 3 months after release.

Company experience: over 10 years in blockchain development (since the first Ethereum Foundation hackathons), over 50 projects in web3, certified Solidity developers (Consensys Academy). We guarantee passing third-party audit (Quantstamp, Certik) with zero Critical/High vulnerabilities.

Process and Timeline

  1. Analytics (2–3 weeks): economic model, mechanics, L2/L1 selection.
  2. Design (3–4 weeks): contract architecture, data schema, interfaces.
  3. Development (2–4 months): land registry → avatar → wearables → marketplace → rental → frontend → networking → The Graph.
  4. Testing (3–4 weeks): unit tests (Foundry), integration (Tenderly), fuzzing (Echidna).
  5. Audit (2–4 weeks). Average audit budget varies depending on complexity.
  6. Deployment (1 week): mainnet/testnet, pinning and CDN setup.

Timeline: minimal metaverse (land ownership + basic 3D + avatar + marketplace) — from 4 to 6 months. Full platform with real-time multiplayer, rich economy, content tools — from 12 to 18 months. We will evaluate your project for free — write to us and discuss details.

Important: don't start with the visual part. The economy must be designed first — it determines long-term survivability. Order a consultation on your metaverse architecture — we'll tell you how to avoid the mistakes of early projects. Contact us — get a detailed implementation plan.