This document provides a guide for exporting a Godot project for HTML 5 and publishing to VIVERSE.
Introduction
In this getting-started guide, we will cover the basics of setting up a Godot HTML5 project and publishing to VIVERSE using the VIVERSE CLI.
For this guide, we are using the VIVERSE CLI, but it is also possible to compress and .
Project Settings for Godot
Web support for Godot currently requires the engine version to be Godot 4.1 or higher for successful exports. Currently using Godot without C# is essential. However, web export support for C# is expected soon from a recent .
Godot 3 web exports are technically supported but not focused on future support.
Export Setting for Godot
Select the desired platform for export. For web exporting, choose HTML5. Also make sure that the export path is set to Build/index.html. This will lower your packaged build size and rename project exported .html to index.html so VIVERSE can easily find and run the project.
Publish to VIVERSE
From here you can publish the project using the CLI tool just like any other platform.
1
Log in to VIVERSE platform
A. Open a command prompt and type: viverse-cli auth login, then click Enter.
B. Enter VIVERSE email and password.
General Limitations of Godot and Web Export
List of Godot WebGL rendering issues:
C. Confirm login was successful.
2
Publish Content
A. To publish content to VIVERSE type the following command with the project path to the project's production build folder: viverse-cli publish <path>, then click Enter.
B. Enter an Application title and Application description.
C. Confirm the content was published successfully.
3
Re-publishing content
A. To re-publish content to VIVERSE when a project is already published, type the following command with the project path to the project's production build folder: viverse-cli publish <path>, then click Enter.
B. Confirm the manifest file is updated.
C. Confirm the content was published successfully.
4
Test project
A. Confirm project was published successfully and working properly in VIVERSE by visiting the URL that is printed in the Publish Details.
Explore all common types of Triggers and Actions implemented in the PlayCanvas Toolkit.
No Code Tools
Explore all major building blocks of no-code functionality provided by the VIVERSE PlayCanvas Toolkit.
Polygon Streaming
This document provides a guide that can be used to setup Polygon Streaming in a VIVERSE project.
Media Polygon Streaming
Streaming 3D Models into The Environment
For Polygon Streaming using the PlayCanvas Extension, you must use the Polygon Streaming Asset IDurl, not the link url.
1
Create the entity that will stream in the 3D model
A. Create a new entity.
B. Change the size of the model using the Scale.
C. Click the Edit Viverse Extension
Scene Settings
This page overviews the interface for controlling global settings for your VIVERSE world in PlayCanvas.
Introduction
The VIVERSE scene settings interface is used to control several settings for your entire VIVERSE world. The interface can be opened by clicking on the triangle button that is added to the left-hand toolbar when the extension is enabled:
Polygon Streaming
The Polygon Streaming settings control how all assets embedded with VIVERSE's service are rendered in your world. For details on these settings, please consult this documentation:
Quest Config
The Quest Config settings allow you to create and add steps to Quests in your world. For details on these settings, please consult this documentation:
Post Effect
The Post Effect settings allow you to add and control the values of post-processing effects on your avatar's camera. For more details on the specific post effects and their values, please consult this documentation:
VIVERSE Studio
This page details important information about using the VIVERSE Creator Studio to publish and manage settings for content associated with your account.
Introduction
The VIVERSE studio is the one-stop-shop for managing all content associated with your VIVERSE account and profile. Studio includes analytics about the performance of your content and tools to manage both video and application content.
Studio Dashboard
The main dashboard of the VIVERSE studio includes metrics on how users engage with your content. With an adjustable timeframe and content filer, you may explore the number of visitors, both new and unique, as well as the number of views and likes your content receives.
Worlds
The worlds page includes tabs for managing existing content and uploading new content. The Content Management page contains links to edit a project's settings, including its visibility, description, and associated media. The Upload tab allows you to create new Worlds, upload and update files for existing worlds.
When updating content through the Upload tab, you will see a new, testable version with a unique link that can be merged into the main version/link for your content after submitting for review. You may also delete or hide Worlds through these settings.
Videos
The Videos tab allows you to explore, upload, and manage settings of uploaded videos. Currently, it is not possible to upload a new version of a video to an existing link; you must delete the current version and upload a new file.
Content Settings
Your content's settings can be edited by clicking the kebab menu next to your world/video.
Worlds can be assigned a genre, which impacts curation and discovery on the VIVERSE webpages.
With the world settings, you can configure your world's name, description, thumbnail, and accessibility settings. Both Genre and Access will influence how your world is categorized and displayed on the VIVERSE world discovery page.
Worlds can be set to one of three accessibility states and can be password protected to add an additional level of security.
Review & Content Moderation
After uploading, your content will be viewable in preview mode only. To submit your world for curation on our webpages, please select "Submit for Review" and select whether you would like iframe support for your experience.
Since VIVERSE content is iframed by default on our landing pages, several web features require requesting permissions, such as xr-spatial-tracking, camera, or allow-pointer-lock. These can be applied to preview links in the "iframe Support for Preview" menu, and must be set when you "Submit for Review," as well.
All content must comply with the standards outlined in the VIVERSE Platform Terms of Use: While not an exhaustive list, we will not tolerate content which...
Depicts graphic or disturbing nudity, gore, sexual acts, violence, whether legal or illegal
Incites violence/hatred against or exposes personal information of individuals or groups
Includes malware, inappropriately collects user data, or inappropriately solicits money/information from users
Images
This document provides a guide that can be used to setup images and extend the functionality of images in a VIVERSE project.
Media Images
Adding Images And Extending Image Functionality
Pick and Throw
This document provides a guide that can be used to setup an entity that can be picked up and threw out. Users in the World can pick the object with "G", Throw it with "T", and put it down with "H".
Pick and Throw
This guide provides instructions for setting up the pick and throw object your Scene.
1
Building with the PlayCanvas Toolkit
Learn how to build projects using common no-code functionality, as well as custom scripted entities and advanced APIs.
Media
Explore all common types of Media supported by the PlayCanvas Toolkit.
button.
2
Add the PolygonStreaming module
A. In the VIVERSE extension, select the Media plugin for the Select plugins dropdown.
B. Select the PolygonStreaming module and add it.
C. Add the polygon streaming url. The URL should be in the following format: https://stream-stage.viverse.com/polygon_file/b9e62012-11e5-49cb-8ede-de596eec537e/aee7496b-b459-4e5d-87fe-2658955eb4f0/model.xrg
The 3D models are visible in the PlayCanvas editor when utilizing Polygon Streaming.
The 3D model streaming into the environment with the avatar.
Worlds can also be assigned a device filter, regulating which user devices are intended to experience the world based on its optimization.
Includes unauthorized connections with technologies that go against the VIVERSE terms of use
Control how users see and express themselves with the .changeAvatar() method on LocalPlayer.
If you don't want to use default VIVERSE avatars for your world, the PlayCanvas SDK features a simple method to swap to any .vrm avatar asset in your project.
NOTE: this script asset must be placed in /scripts or another subfolder, since it assumes the VIVERSE SDK is one level up, located at: "../@viverse/create-sdk.mjs" - or you can alter this import path as needed. For more information on how .mjs scripts and imports work, see .
Because vrmAsset is defined as an attribute of type Asset, we can then select which asset to use directly in the PlayCanvas editor once the script is added to an entity.
When we publish to VIVERSE and load the experience, the .vrm is loaded immediately. Avatar switching for the local player is possible at any point during runtime and can be triggered with UI, trigger colliders, or with any other programmatic callback.
Reference Code:
Supported Media & Settings
This page details the different kinds of media that can be uploaded to a world in Edit Mode and the settings you can control.
Adding Media
Media are added to VIVERSE worlds in Edit Mode using the toolbar at the bottom of the screen. Detailed below are the categories of assets that correspond with the buttons in this toolbar.
Marketplace
Edit Mode
This page details the basics of Edit Mode for decorating your world.
Getting Started with Edit Mode
Edit Mode is available on all worlds you own or where you have been added as a co-owner/moderator. If you are a world owner or co-owner, you will have access to the "Edit Mode" button when you join the world.
When enabling Edit Mode, your controls and interface will be changed, and your camera will be detached from your avatar so that you can more easily navigate and edit your world. When in Edit Mode, your avatar will still be visible and your audio will be audible to others in the world.
Intro to Standalone App Publishing
This page overviews the requirements, tools, and process for building applications on VIVERSE.
Publishing Apps to VIVERSE
3D experiences and web applications are the foundation of VIVERSE's creator community. We invest heavily in the development of amazing interactive content and are always expanding our support for new tools and frameworks where the best experiences are being crafted for the web.
While VIVERSE supports custom publishing pipelines for a few platforms, any platform can publish to VIVERSE using by uploading a .zip file with an index.html file at the top level of its file tree.
Custom Code
The page introduces the basic information about implementing custom code with PlayCanvas in VIVERSE.
Fundamentals
VIVERSE allows developers to use nearly any of the custom scripting interfaces , including but not limited to WebRequests like http & websockets, GLSL shaders, and 3rd party libraries imported directly into your project's hierarchy.
However, by default, VIVERSE's PlayCanvas SDK does automatically handles avatar transform and audio networking. For customizing any features related to the VIVERSE avatar, we provide an additional API reference (see VIVERSE SDK APIs below).
Sharing Content
This page shared details about how VIVERSE creators can share their work and get their work discovered on VIVERSE.
Creator Profile
VIVERSE makes it easy for creators to share their work with audiences on and outside of VIVERSE. All content is associated with the creator profile, which can be customized to showcase additional media and details. The VIVERSE team manually curates creator profiles who actively publish and share their work, so be sure to fully customize your creator profile with details about your creative practice!
Your VIVERSE Creator profile has two visibility modes, public and private. In addition to your banner image, description, media, and content, private mode allows creators to view the content that your have purchased, the creators you follow, and other liked content.
The documentation for VIVERSE's SDK APIs is currently housed here: https://viveportsoftware.github.io/pc-lib/. We provide interfaces for customizing the default VIVERSE Cameras, Player, Network, and Environment, as well as the unique attributes when in an XR/immersive session in a VR headset.
These interfaces are automatically injected when you activate the VIVERSE Chrome Extension; The folder @viverse is added to your asset folder, which contains all interfaces in the create-sdk.mjs file. All interfaces can be imported and manipulated in your custom scripts.
For accessing the APIs in the VIVERSE SDK, you must use .mjs file types, which support import and export statements.
A Note on No-Code Tools
In addition to adding the create-sdk.mjs file on initialization, the VIVERSE Chrome Extension adds create-extensions-sdk.mjs, which contains all of the interfaces between the no-code tools and PlayCanvas.
Within this file, you can see that each no-code function is assigned a unique trigger string, such as 'trigger:300006' for EntitySubscribeTriggerEnter. This is useful, because you can arbitrarily listen for and fire these exact same event names in custom scripts, connecting together the VIVERSE No-Code Functions and your custom code.
Once media have been uploaded, you are able to control several of its properties through the asset's details:
Asset Details |Here you can add an expandable description and a clickable link to an external url.
Transform Properties |Here you can control the asset's position, rotation, and scale.
Frame | For 2D media, such as images or external website links, you can add a colored frame to give your media extra dimensionality.
Playback Settings |For media with some form of playback, such as videos or streams, you can control audio and playback settings.
The media properties editor
Media Playback Settings
Configuring media playback settings for MP4s can be done via Audio (A) toggle.
Configuring media playback settings for MP3s can be done via Audio (A) toggle.
Adding Interactions to VRMs
To add interactions to VRMs, click Add button(A) under Interactions. Configure the interaction in the panel (B).
The Edit Mode asset upload toolbar
The Edit Mode controls
The Edit Mode interface has three sections, the performance report in the top-left corner, the media upload toolbar in the bottom of your screen, and the object list in the top right where you can access and control the settings of all media added to your world in Edit Mode.
The Edit Mode interface.
In order to save your customizations and have others see them, you will need to select the "Close edit mode" button and exit Edit Mode.
Viewing the Performance Report
1
Open the Performance requirement link
Step 1. Click Performance requirement (A).
2
View the world's VRAM consumption
Step 1. View the Performance Manager report (B).
Adding and Handling Media
Media can be added from several different sources through the toolbar in the bottom of the Edit Mode interface: Marketplace assets, uploaded assets, and assets linked from external sources. For more information on the types of media you can add and their settings, see this page.
The media upload toolbar
When media are added to your world, you can access and update their properties through the object list on the right-hand side of the Edit Mode interface. Furthermore, you can quickly reposition your media by clicking and dragging them through your world.
The Edit Mode object list
Adding Collaborators
You can add five additional VIVERSE accounts as co-owners of your world. By promoting these users, you are giving them full control over Edit Mode, moderation tools, and world settings for your world. Co-owners can be removed and will not be able to delete the world on your behalf. Co-owners can be added outside of Edit Mode by going to the hamburger settings button in the top-right of your world, selecting the "Permissions" tab, and adding Co-Owners by their user id or display name.
Adding Co-owners through world permissions.
The Edit Mode button
Supported Tools & Frameworks
Platform
Description
HTML5 & WebGL
Creators can generally publish any project compatible with HTML5. See for details on requesting advanced features, such as user microphone permissions.
WebGL & WebGPU
Creators can generally publish any WebGL project on VIVERSE. Certain features for WebGPU, such as support for multi-threading, may need to be approved manually. See for how to submit requests for these permissions.
PlayCanvas
VIVERSE supports publishing from PlayCanvas through and with the , which adds multiplayer avatars, UI, and a cross-device character controller by default.
ThreeJS
Don't see your platform or want to request new features? Join our Discord Server and let us know if you would like more support.
Developer Tools
Along with our platform integrations that allow you to publish to VIVERSE, we also have a number of standalone developer tools that can be utilized in experiences hosted on and off of VIVERSE. These tools help creators get the most out of their 3D experience and make the difficult parts of online development easier.
NOTE: VIVERSE SDKs cannot be used with projects published via the PlayCanvas Create SDK extension, which do not have App IDs.
Tool
Description
Documentation
Polygon Streaming
Upload and embed high quality 3D assets in web-based experiences. Polygon Streaming's innovative technology makes highly-detailed, large assets accessible to billions of devices through the web browser!
Avatar & Account SDK
Utilize our avatar and virtual identity system to bring multiplayer to your 3D experience.
Bringing Your Own Game Servers & Analytics
While VIVERSE provides free services and SDKs for creators to integrate into their projects, developers may also provision and connect with their own servers/analytics on VIVERSE. This process does require manual approval by the VIVERSE team, but we are able to quickly approve these requests. Please email the VIVERSE team with your request and a description of the external server you would like to connect to.
After your content has been approved and set to Public, it will automatically be discoverable based on its assigned Genres and Description details. The VIVERSE recommendation system also suggests content related to players' interests and based on a content's popularity (both likes and recent viewership).
In addition to algorithmically recommending content, the VIVERSE team manually curates and features content on our webpages which can help your work get seen by more players. The best way to get curated is to make the VIVERSE team aware of your work. We recommend sharing your project on social media and tagging @VIVERSEofficial, and to join our discord server to show off your work in the #share channel.
Embedding Content
The VIVERSE team supports creators who want to share their work across the internet, including embedding on other high-traffic webpages and curation surfaces. Underneath your content, the share button presents options for sharing via social media and through iframe embedding.
Iframes are a powerful and easy way to allow users experience content hosted on VIVERSE on other webpages. When you select Embed, you will receive an iframe html element that can be easily added to your webpage.
In some cases, you may need the VIVERSE team to manually approve the webpage you wish to embed on. To process this manual request, please email the VIVERSE team with your content's URL, the URL of the webpage you want to embed your content on, and a description of the webpage.
Avatar Teleport & Checkpoint
This document provides guides that can be used to change the spawn location of an avatar and transfer an avatar to a different location. These actions can be configured to execute with triggers.
EntityCheckPoint
Create An Action That Sets A New Spawn Point
This guide provides instructions for setting up the EntityCheckPoint action. In the sample app, once the avatar enters one of the green trigger areas, the area becomes the new spawn location.
In this example, a trigger area is created and when triggered, an action sets a new spawn location. Any object can be used as a trigger, as long as the object has a collision component.
1
Create a trigger area
A. Create a new Sphere entity.
B. The Collision component is not required for EntityCheckPoint action to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
TeleportAvatar
Create An Action That Teleports An Object To A Specific Location
This guide provides instructions for setting up the TeleportAvatar action. In the sample app, once the avatar enters one of the green cylinder trigger areas, the avatar is teleported to another location.
In this example, a trigger is created and when the avatar or other objects enter the trigger area, an action teleports the avatar to a specific location. Any object can be used as a trigger, as long as the object has a collision component.
1
Create a trigger area
A. Create a new Sphere entity.
B. The Collision component is not required for TeleportAvatar action to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
Creating From Templates
This document details the process of creating a world from a template.
Templates are starter projects that are pre-built in VIVERSE. They are available on the profile page of your VIVERSE account.
Prerequisites
In order to create worlds you must first create a VIVERSE account.
1
Navigate to
2
Scroll down to "Worlds" and select the "Create World" button
3
Select from the list of premade templates
4
Updating the World Settings
Step 1. Select the Details page (A).
Step 2. Give the world a name in the Name field (B).
Step 3. Give the world a description in the Description
5
Adding gameplay trailer and screenshots
Step 1. Click on the Media (A) tab.
Step 2. Add a trailer video to the Trailer (B) section.
Step 3. Add images to the Images (C) section.
6
Adding a GitHub link
Step 1. Click on the Code & Collab (A) tab.
Step 2. Add a GitHub link to the GitHub (B) section.
7
Managing World Settings after creating a world
Step 1. Select the Worlds tab (A).
Step 2. Select the 3 dots (B) on the world that needs to be updated.
Step 3. Click World Settings
Audio
This document provides a guide that can be used to setup audio and extend the functionality of audio in a VIVERSE project.
Media Audio
Adding Audio and Extending Audio Functionality
An audio clip has been added to the scene.
1
Setup audio
A. Create a new entity.
B. Click the Edit Viverse Extension button.
2
Video
This document provides a guide that can be used to setup videos and extend the functionality of videos in a VIVERSE project.
Media Video
Adding Video And Extending Video Functionality
1
Setup video
A. Create a new entity
B. Resize the video using the Scale.
C. Click the Edit Viverse Extension button.
Custom Virtual Reality UX
Use `XrService` to interact with virtual reality devices and controllers.
WebXR experiences can run on desktop, mobile and virtual reality devices alike. Utilizing the XrService in the Create SDK, you can write custom code to manage VR controllers, locomotion settings, and XR session callbacks.
Custom Locomotion Settings
By default, the VIVERSE character controller uses teleport for locomotion, since this is the more comfortable option, in general. However, smooth locomotion (where the player glides smoothly across the floor) can be enabled on either or both controllers by setting the
Custom Loading Screens
Learn how to create a custom loading screen on VIVERSE during asset pre-loading.
Default Loading Experience
Because web games and assets take time to transfer over the internet and load onto the player's device, user experience during loading is important. If shown a blank or broken-looking screen during this time, users may leave early, and never get to try the full experience.
While creators should , it's also somewhat inevitable. As such, VIVERSE provides a default loading experience during the asset pre-load phase:
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
2
Add the EntityCheckPoint action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityCheckPoint.
E. Add an entity that has a position that will be used for the new spawn location. SpawnLocation1 has been added to the pick up an entity id.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
2
Add the TeleportAvatar action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityTeleportAvatar.
E. Add an entity that has a position that will be used for the teleport location. TeleportLocation2 has been added to the Specify the Entity whose location you want to teleport to.
The avatar enters the green trigger area and the trigger area becomes the new spawn location.
The avatar has fallen off the map and needs to be respawned.
When the avatar respawns, it is spawned at the new location.
The avatar enters the green trigger area.
After entering the green trigger area, the avatar is teleported to another location.
field (C).
Step 4. Upload a thumbnail of the world in the Thumbnail (D) section.
Step 5. Assign at least genre to the world in the Genre (E) section.
Step 6. Set the compatible devices types for the world in the Devices (F) section.
A. In the VIVERSE extension, select the Media plugin for the Select plugins dropdown.
B. Select the Audio module and add it.
C. Add the audio to the Asset field.
D. Uncheck the auto play property to prevent the audio from starting when the avatar enters the environment.
2
Add the video module
A. In the VIVERSE extension, select the Media plugin for the Select plugins dropdown.
B. Select the Video module and add it, then select either "Asset" for files contained in your PlayCanvas project, or "URL" for a video to stream, such as a YouTube URL (but please note: YouTube or other embeds are run inside iframe elements, which do not render in VR). For this example, choose "Asset."
C. Add the video to the Asset field by selecting it within your project.
D. Uncheck the auto play property to prevent the video from starting when the avatar enters the environment.
The user uses the mouse to hover over the video to access the controls.
The video is playing.
of each.
Import the XrService from the Create SDK into an .mjs script. Per the API docs, this gives you access to both left and right controllers, and their properties, to set on init:
NOTE: this script asset must be placed in /scripts or another subfolder, since it assumes the VIVERSE SDK is one level up, located at: "../@viverse/create-sdk.mjs" - or you can alter this import path as needed. For more information on how .mjs scripts and imports work, see Introduction to MJS.
When switching to Smooth Locomotion, this also enables flight in VR in any World where flight is enabled in World Settings. Just "click" the Smooth Locomotion joystick to enter flight mode. Once flying, pressing forward on the joystick will fly forward along the VR camera's forward axis (i.e. wherever you're looking), and vice versa backwards.
After defining the vrControllerAssetL and vrControllerAssetR attributes of type Asset in the above script, we then reference custom 3D controller assets in the editor, which our script instantiates at runtime in VR.
However, some creators may wish to make custom loading screens more in line with the aesthetics of their game or app. This can help sell an overall sense of quality and immediately set the tone for users.
VIVERSE creators can make full use of PlayCanvas' built-in loading screen feature. Just navigate to PlayCanvas Project Settings > Loading Screen and click "Create Default."
If you have the VIVERSE-PlayCanvas browser extension installed, this will inject a VIVERSE logo into the loading screen template, which is required for all projects.
Other than that, loading-screen.js is yours to customize. Add your logo, a tagline in a custom font, or a cool background image, grounding your users in your experience immediately.
The custom loading screen from In Tirol.
Control Which Assets Download During the Loading Screen
All assets with the "Preload" box checked in asset settings will be downloaded during the loading screen phase. Limiting pre-loaded assets can help get users to your game view faster, which will result in fewer overall "bounces" from your game (meaning users who quit the game during loading). So only check "Preload" if the asset is immediately needed - otherwise it will stream in behind the scenes as needed, per PlayCanvas' docs.
VIVERSE supports most ThreeJS projects, as well as the many tools and frameworks that have been built on top of the library, such as React-Three-Fibre (R3F)nd AFRAME.
VIVERSE sponsors the development of an open source ThreeJS and R3F-compatible avatar system called pmndrs/viverse.
Unity WebGL
Creators can publish projects built with Unity's WebGL export pipeline, and we recommend they upgrade to the latest version of Unity to benefit from the recent upgrades for web optimization made in Unity 6. We have written multiple examples in for how to utilize our SDKs in your Unity Projects.
Open Brush
In December 2025, VIVERSE worked with the Icosa Foundation, to build a pipeline for publishing from Open Brush to VIVERSE with multiplayer avatars.
Wonderland Engine
In November 2025, VIVERSE worked with the Wonderland Engine team to develop a plug-in for Wonderland Engine, including examples of a cross-device character controller and one-click publishing to VIVERSE.
Godot HTML5
VIVERSE supports publishing from Godot using their HTML5 publishing pipeline.
BabylonJS
VIVERSE supports publishing Babylon projects.
Unreal Engine
Unfortunately, there is no 1st-party pipeline for publishing from Unreal Engine to web. VIVERSE is open to discussing support for any 3rd party publishing/streaming pipelines from Unreal Engine to the web.
Leaderboard SDK
Add a leaderboard to single and multiplayer gaming experiences. Our leaderboard system allows you to keep track of player performance between sessions.
Matchmaking & Networking SDK
Add persistent data to single and multiplayer gaming experiences.
Storage SDK
Persist data between sessions for users associated with their VIVERSE account.
Learn how to install the VIVERSE Chrome Extension for PlayCanvas Editor, create your first world, then publish it to VIVERSE.
Introduction
PlayCanvas is an open-source game engine designed to advance the development of 3D web games, interactive content and rich multimedia. Unlike similar WebGL engines like Three.js or Babylon, PlayCanvas comes with sophisticated in-browser Editor (inspired by early Unity 2.x - 3.x), which provides its users with a rich set of tools — allowing to assemble scenes from imported assets, setup real-time and baked lighting, write custom scripts, create animation graphs, and much much more.
To make creator experience even smoother, VIVERSE has developed a special Extension for Chrome browsers which extends PlayCanvas Editor functionality with additional set of no-code tools and publishing options. It provides common building blocks like Triggers, Actions and Quests, enables Player locomotion and Avatar system in your project, and allows one-click testing and publishing right from the Editor.
Below is a useful set of tutorials to help you get started with VIVERSE PlayCanvas Extension. We assume you're already familiar with PlayCanvas Editor itself and have PlayCanvas account. If not, please feel free to explore first!
Install PlayCanvas Extension
1
Get the latest Extension from VIVERSE
Create and publish your first project
Before proceeding any further, we assume you're familiar with the basics of PlayCanvas Editor. If you're looking for a comprehensive introduction to it — please refer to a dedicated first!
1
Initialize your new project
"Factory Reset" PlayCanvas Extension
Sometimes issues in the installation process can produce persistent bugs that are only fixed by fully resetting the Extension. If you're experiencing these bugs please follow the steps below
1
Sign in and out of VIVERSE
Sign out of your account on viverse.com and then sign back in. MAKE SURE you are using the same email account as the one associated with your PlayCanvas account
2
Asset Management
This document provides several guides that can be used to optimize VIVERSE projects by controlling when assets are rendered.
EntityAssetUnload
Create An Action That Unloads An Asset From The Scene, Stops The Asset From Rendering And Retains The Asset In Memory
This guide provides instructions for setting up the EntityAssetUnload action. In the sample app, the trigger area is outlined in blue. Once the avatar enters into the trigger area, the asset stops rendering in the scene. This will decrease draw calls and improve frames per second, but the asset will be retained in memory.
In this example, a trigger is created and when triggered, an action unloads an object. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
1
Create a trigger area
A. Create a new 3D Box entity.
B. The Collision component is not required for EntityAssetUnload action to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
EntityAssetReload
Create An Action That Reloads An Asset Into The Scene From Memory And Causes The Asset To Be Rendered
This guide provides instructions for setting up the EntityAssetReload action. In the sample app, the trigger area is outlined in blue. Once the avatar leaves the trigger area, the asset is reloaded from memory and starts rendering in the scene.
In this example, a trigger is created and when triggered, an action reloads an object. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
1
Create a trigger area
A. Create a new 3D Box entity.
B. The Collision component is not required for EntityAssetReload action to work. The Collision component is required for the EntitySubscribeTriggerLeave trigger that will be used in this example.
EntityDestroy
Create An Action That Destroys An Asset, Removes It From Memory and Stops It From Rendering
This guide provides instructions for setting up the EntityDestroy action. In the sample app, the trigger area is outlined in blue. Once the avatar enters the trigger area, the asset is destroyed, which removes it from memory and stops it from rendering.
In this example, a trigger is created and when triggered, an action destroys an object. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
1
Create a trigger area
A. Create a new 3D Box entity.
B. The Collision component is not required for EntityDestroy action to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
Networked
This page details the usage of the networked component on individual entities in PlayCanvas.
Overview
The Networked plugin allows local updates to certain properties of an entity's components to be sent to other connected avatars.
Transform
By adding the Transform component, an entity's position and rotation will be networked across clients.
At this time, Transform does not network the Scale property of the entity.
Anim
By adding the Anim component, an entity's animation state will be networked across clients.
Networking Example
In this video, we have created an arena with a floor, four walls and a ball. The networking module has been added to the ball. After publishing and creating the world in VIVERSE, multiple players can join in the environment. The location of the ball is tracked across all player sessions.
To create the arena and ball in the video, you can follow the tutorial. The instructions below can be used to add Networking functionality to the ball or any other entity of your choosing.
1
Create the entity
A. We have already created the Ball entity in the tutorial linked above. Here's a screenshot of the Ball entity.
2
Camera Management: Settings and Switching
How to use VIVERSE SDK's CameraService to manage camera settings and switch between different VIVERSE and custom cameras.
VIVERSE provides a powerful camera system alongside its player controller and input scripting that allows developers to switch between different views and control various camera behaviors. This guide will show you how to implement camera switching in your VIVERSE project.
Basic Camera Switching
The VIVERSE player rig creates several cameras and switches between them depending on your settings and/or world scripting: CAMERA_3RD,
import { Script, Asset } from "playcanvas";
import { XrService, XrTypes } from "../@viverse/create-sdk.mjs";
export class ViverseXrManager extends Script {
static scriptName = "viverseXrManager";
initialize() {
this.xrService = new XrService();
this.xrService.controllers.right.locomotionType = XrTypes.LocomotionTypes.Teleport;
this.xrService.controllers.left.locomotionType = XrTypes.LocomotionTypes.Smooth; // Smooth
// See enum definitions here:
// https://viveportsoftware.github.io/pc-lib/enums/XrTypes.LocomotionTypes.html
}
}
The CameraService provides methods to switch between different camera views provided by the VIVERSE avatar rig. Here's a basic .mjs script importing the CameraService and switching to first-person camera mode on init. Simply attach this script to any entity in your project.
NOTE: this script asset must be placed in /scripts or another subfolder, since it assumes the VIVERSE SDK is one level up, located at: "../@viverse/create-sdk.mjs" - or you can alter this import path as needed.
Custom Camera Override Example
If the VIVERSE player rig cameras don't totally meet your needs, you can switch to your own camera entity for cut scenes or preview cameras. Here's a practical example of how to override the default VIVERSE camera with a custom camera on init:
Camera Switching on Events: VR and Player Ready
You can listen for certain events from other services that may be related to your desired camera behavior. For example, on the player:ready event, we know that all player cameras and scripting have loaded in and are ready to interact with the scene:
Additional Camera Properties
The CameraService provides several properties to customize camera behavior:
import { Script } from "playcanvas";
import { CameraService, CameraTypes } from "../@viverse/create-sdk.mjs";
export class CameraManager extends Script {
initialize() {
this.cameraService = new CameraService();
// Switch to first person view to first person
this.cameraService.switchPov(CameraTypes.PovTypes.FirstPerson);
// At any time, you can switch back to CameraTypes.PovTypes.ThirdPerson
// Prevent users from switching POV, which is usually done in user settings or with the keyboard shortcut "V"
this.cameraService.canSwitchPov = false;
}
}
import { Script, Entity } from "playcanvas";
import { CameraService } from "../@viverse/create-sdk.mjs";
export class OverrideViverseCamera extends Script {
/**
* @attribute
* @type {Entity}
*/
overrideCamera = null;
initialize() {
if (!this.overrideCamera) {
console.error("No override camera set!");
return;
}
this.cameraService = new CameraService();
this.cameraService.switchCamera(this.overrideCamera);
}
}
// Wait for the XR start event then get the VR camera
this.app.xr.on("start", () => {
// The VIVERSE player rig will switch to its "CAMERA_VR" automatically
// So getting reference to the activeCamera at this time will point to
// the "CAMERA_VR" entity
const vrCamera = this.cameraService.activeCamera;
// You could also search for this by name
// const vrCamera = this.app.root.findByName("CAMERA_VR");
// Then raycast from the forward vector, apply scripts, etc.
});
// Or wait for player to be ready before switching cameras
this.playerService.localPlayer.on("player:ready", () => {
this.cameraService.switchCamera(this.previewCamera);
});
// Set minimum and maximum zoom distances
this.cameraService.minZoomDistance = 1;
this.cameraService.maxZoomDistance = 10;
// Disable camera zooming
this.cameraService.canZoom = false;
// Disable camera rotation
this.cameraService.canRotate = false;
// Get current POV type
const currentPov = this.cameraService.pov; // Returns PovTypes enum value
// Get active camera entity
const activeCamera = this.cameraService.activeCamera; // Returns null | Entity
Download the latest version of Playcanvas Extension
Unzip downloaded file on your computer
2
Navigate to Chrome Extensions manager
Click Extensions icon in Chrome toolbar and open the Extensions Popup
Click Manage Extensions at the bottom and open the Extensions Manager in a new tab
3
Install the Extension
Enable Developer Mode at the top right corner
Click Load Unpacked and select the folder with unpacked Extension you downloaded previously
Verify the Extension is now present in Extensions Manager tab
Create a new PlayCanvas project or open an already existing one
Make sure VIVERSE Extension is properly initialized — you should see ExtensionEntity in your scene hierarchy and @viverse folder added to your project. Refresh the page if it's not the case
Login into VIVERSE via dedicated button in the left toolbar. Once logged in, you should see VIVERSE Scene Settings button there
2
Setup 3D environment
First, delete default Camera in Scene Hierarchy. The Extension will provide its own Camera system that will be added to your Scene at runtime
Import Ammo physics library and add a Floor plane with Collision component and static Rigidbody. This is crucial because VIVERSE Player system relies on built-in PlayCanvas physics engine for moving around. Without a floor, your player will be simply falling through
Add additional geometry and lights if want!
3
Create a Spawn Point
In order for a Player to appear in your world, it should be spawned somewhere first. VIVERSE Extension provides a convenient way to control that!
Simply create a new empty Entity in your scene and add spawn-point tag to it
Make sure it's positioned at the floor level or above. Feel free to rotate it to change the initial orientation of your Player
4
Preview your project
Once you have a walkable floor and a spawn point, it's time to test your project live!
Go to the Publish / Download menu and open the Builds popup window. In that window, click Publish to Viverse button and wait until your project is successfully uploaded
Once it's uploaded and ready, the Preview button should appear. Clicking it will open your project in a new tab, in preview mode. This preview URL is public and you can share it with your friends and colleagues to test the current version of your work
Return back to PlayCanvas Editor and modify your project as you see fit. Keep publishing and previewing to see your most recent changes live in VIVERSE environment
5
Final: Create a VIVERSE World for your project
After confirming everything is working correctly in preview mode, you can publish your project to production environment!
In preview mode, click "Create World" button, give your World a name and click the "Create" button to publish it to the VIVERSE Create platform
The resulting URL is the public link to your World. You can return back to your project any time and republish an updated version as you see fit
Feel free to configure your as well
Delete VIVERSE entities from PlayCanvas project
Go back to your PlayCanvas project and delete:
The Extension Entity from your scene hierarchy
The @viverse folder from your project assets
The extension-image folder from your project assets
The extension-script folder from your project assets
3
Clear Application Storage
Open the Developer Tools in your Chrome brower, go to "Application", select "Storage" in the left hand toolbar and click the "Delete Site Data" button
4
Refresh the page
Refresh your PlayCanvas project page with the VIVERSE extension enabled
5
Sign in back to PlayCanvas
Sign in to PlayCanvas when prompted. MAKE SURE you are using the same email account as the one associated with your VIVERSE account
6
Sign in back to VIVERSE
Sign in to VIVERSE from within your PlayCanvas project using the VIVERSE Scene Settings
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
2
Add the EntityAssetUnload action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityAssetUnload.
E. Add an object that will be unloaded when the avatar enters the trigger area. The House2 entity has been added to the pick up specify execution entity.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
2
Add the EntityAssetReload action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerLeave.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityAssetReload.
E. Add an object that will be unloaded when the avatar enters the trigger area. The House2 entity has been added to the pick up specify execution entity.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
2
Add the EntityDestroy action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityDestroy.
E. Add an object that will be destroyed when the avatar enters the trigger area. The House2 entity has been added to the pick up specify execution entity.
When the avatar is outside the blue trigger area, the house asset is being rendered.
When the avatar enters the blue trigger area, the house asset is unloaded, but is retained in memory.
When the avatar enters the blue trigger area, the house asset is unloaded, but is retained in memory.
When the avatar leaves the blue trigger area, the house asset is reloaded from memory.
When the avatar is outside the blue trigger area, the house asset is being rendered.
When the avatar enters the blue trigger area, the house asset is destroyed and removed from memory.
Add the Networking module
A. In the VIVERSE extension, select the Networking plugin for the Select plugins dropdown.
B. Change the dropdown to Transform in the Select a module and add field. Click the plus sign.
C. Confirm the enabled checkbox is checked.
3
Publish and create world
A. To test the project, publish to VIVERSE and create the world.
4
Share and play
A. Share the world link with another player and have them join the environment. We the other player interacts with the ball, you should be able to see the ball movement in your session. When you move the ball, the other player should be able to see the ball movement in their session.
A PlayCanvas sample project that provides demonstrations of how to use the features in the VIVERSE Extension.
We created a PlayCanvas sample project that contains examples of how to utilize the PlayCanvas Extension. Download the project and import it into a PlayCanvas account. Publish the project to VIVERSE and enter Preview mode to test out the functionality. The pages listed under API Reference are the functionality that the sample project is demoing.
Project Name
Download
Version
VIVERSE_PlayCanvas_Sample_1.2
This project is separated into different stations. Each station has Tags added to help identify the VIVERSE functionality the station is demonstrating.
This page details the two methods to publish to VIVERSE: VIVERSE Studio and our command line interface.
Introduction
You can upload to VIVERSE from all web-compatible frameworks, including 3D experiences, web applications, and videos! No matter what you are building with, you can upload and manage your builds easily using VIVERSE Studio or our command-line interface (CLI). Once uploaded, VIVERSE content is associated with your VIVERSE account and profile located at https://worlds.viverse.com/profile. This page guides you through the uploading process using both methods!
While 3D experiences and applications can be uploaded using either VIVERSE Studio or the CLI, currently videos can only be uploaded via Studio, not the CLI.
Publishing with VIVERSE Studio
The VIVERSE Studio offers a user-friendly interface that makes it easy for creators of all skill levels to upload and manage content on VIVERSE. You can learn the process for uploading or below.
Publishing Apps with VIVERSE Studio
Learn more about , including supported file types, requirements, and integrations with our SDKs.
1
Begin Upload
Open VIVERSE Studio, navigate to the Worlds section, select the Upload tab, and click Create New World.
Publishing Videos with VIVERSE Studio
Learn more about , including upload limits, output specs, and our transcoding matrix.
1
Upload your video file
Open VIVERSE Studio, navigate to Videos section, and drag-n-drop your video file to start uploading. As alternative, click Upload button at the right upper corner.
Publishing with the CLI
The can be used to publish any web-compatible WebGL / HTML5 build to the VIVERSE platform after an authentication process.
Installation
Using npm:
Note: This CLI requires Node.js version 22.15.0 or higher.
Authentication
Login to VIVERSE platform:
Or directly pass in login credentials for CI/CD integration:
In such CI/CD environments, it's recommended to use environment variables:
After login, check your authentication status:
And to logout:
After , the VIVERSE CLI can be used to publish any working WebGL build to the VIVERSE platform after an authentication process. When publishing, you'll either access your existing projects, or create a new one.
Creating Applications
You can use the VIVERSE CLI to create a new application directly:
Or specify a name:
Alternately, you can use the workflow to create an application ID:
Listing Applications
Once authenticaed, you can view your account's available application list:
The output will be displayed in a table format with the following columns:
ID: Application identifier
STATE: Application state
TITLE: Application name
URL: Application preview URL
Publishing
Publishing content requires two inputs:
App ID — the target application to publish to (required)
Content path — the directory containing your content (optional if you're already in that directory)
Option 1: Specify content path
Option 2: From within content directory
Note: The App ID is required. You can use the viverse-cli app list command to query your existing application IDs, or view the IDs of newly created applications after using app create.
Important: After uploading content successfully, you'll need to visit the Creator Studio website to complete the review and publishing process.
Warning: The <path> parameter MUST point to your build output folder and NOT your source code folder. Publishing source code folders (containing src/, node_modules/, or development files like .tsx, .jsx, .vue, .unity, etc.) will result in non-functional content and deployment failures.
Specifications for Video Content
Input video specifications
Feature
Supported Formats and Types
Output video specifications
Resolution
Codec / Bitrate
Audio Specs
Description
Transcoding matrix
If You Upload (Input)
Your Viewers Get These Resolutions and Frame Rates
Worlds are containers for content on VIVERSE and, once created, you can upload your 3D experience or application to your World.
2
Complete Upload Details
Enter a Name and Description for your project and agree to VIVERSE's Platform Agreement.
Once completed, select Create.
3
View the Overview Tab
Once your World is created, you can view and adjust settings for your content in the Overview Tab, such as its Name and App ID.
The App ID is an important piece of information for anyone into their project.
4
Upload a .zip File
Within the Content Versions Tab, drag-and-drop or click the Select File button to begin the upload process.
Select your .zip file and click Upload.
5
(Optional) Add Additional Permissions
Many projects may want additional permissions, allowing access to advanced features, such as the ability to download content from your application or open a new tab:
Content Behavior Permissions
allow-forms - Submit forms
allow-modals - Open modal dialogs
allow-popups - Open popup windows
allow-top-navigation - Navigate top window
allow-pointer-lock - Use pointer lock
allow-presentation - Start presentations
allow-downloads - Download files
allow-orientation-lock - Allow orientation lock
allow-popups-to-escape-sandbox - Allow popups to escape sandbox
allow-top-navigation-by-user-activation - Allow top navigation by user activation
Device and Sensor Access Permissions
accelerometer - Allows access to accelerometer sensor data
camera - Allows access to device camera
gyroscope - Allows access to gyroscope sensor data
Select Apply iframe Settings to apply your desired settings.
6
Preview and Test Content
Select Preview for a link that is only accessible to the account that created the world.
Select Guest Preview for a 15-minute link that you may share with any other testers.
7
Submitting for Review
Once you are satisfied with your creation, select Submit for Review to submit your world for moderation. Moderation usually takes less than 48 hours. If you need support with moderation, please reach out to us through this form.
Please make sure your video is authored in correct format, otherwise the uploading process will return an error
2
Fill in content details
While the video is processing, feel free to fill in content details:
Video title
Description (optional)
Thumbnail image
Genre tags
3
Preview your content
Once the video is uploaded and processed, it is available for preview!
Click View button to see your video in a new tab. You can adjust Quality Settings on the fly to check how it was transcoded into different resolutions.
4
Adjust visibility
The visibility is set to Private by default, but you can always set it to Public or Unlisted in the dropdown at the top of the page
5
Save and publish
When you're happy with everything, click Create button at the top right corner — this will save your video with the Visibility Settings you adjusted earlier.
And when you're ready to publish — just click Edit and set your video to Public. Congratulations, it's now live and can be viewed by entire VIVERSE community!
Please note that you can always hide your video later by setting its Visibility back to Private
This page provides several guides that can be used to setup event listeners in a VIVERSE project. The event listeners use triggers. Triggers can be configured to perform actions once activated.
EntitySubscribeTriggerEnter
This guide provides instructions for setting up the EntitySubscribeTriggerEnter trigger. In the sample app below, the trigger areas are outlined in blue. Once the avatar enters into the blue area, an action occurs.
Entity Collision Enabling & Disabling
This document provides several guides that can be used to enable and disable colliders in a VIVERSE project. These actions can be configured to execute when triggers are activated.
EntityToggleCollision
This guide provides instructions for setting up the EntityToggleCollision action. In the sample app, every time the avatar enters the green trigger area, a notification is sent to the wall and the collider on the wall is toggled on/off. The wall is green when the avatar can pass through and red when the avatar can not pass through.
Introduction to Creator Tools
This page is the starting point for creators interested in learning about building on VIVERSE.
The Best on the Web
VIVERSE is home to the best content on the internet that can be shared with audiences around the world through the web browser. Whether you are building engaging 3D experiences, web applications, or videos, your work can easily be hosted on and shared through VIVERSE. Our goal is to help creators distribute and monetize their work through VIVERSE's easy hosting and content distribution.
xr-spatial-tracking - Allows access to VR/AR features
MP3
The avatar is outside the blue trigger area and the gold coin is not visible.
The avatar has entered the blue trigger area and the gold coin is visible.
In our example above, a trigger area is created. When the avatar enters the trigger area, an action is then initiated. Any object can be used as a trigger, as long as the object has a collision component. Our example uses a 3D box as the trigger area.
Create a trigger for when an object enters an area
1
Create a trigger area
A. Create a new 3D Box entity.
B. Add a Collision component.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
2
Add the EntitySubscribeTriggerEnter trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityEnableById.
E. Add an object that will be enabled when the avatar enters the trigger area. The golden_coin entity has been added to the pick up specify execution entity. The
EntitySubscribeTriggerLeave
This guide provides instructions for setting up the EntitySubscribeTriggerLeave trigger. In the sample app, the trigger areas are outlined in blue. Once the avatar leaves the blue area, an action occurs.
The avatar is inside the the blue trigger area and the gold coin is visible.
The avatar leaves the blue trigger area and the gold coin is no longer visible.
In this example, a trigger area is created and when the avatar leaves the trigger area, an action is initiated. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
Create a trigger for when an object leaves an area
1
Create a trigger area
A. Create a new 3D Box entity.
B. Add a Collision component.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
2
Add the EntitySubscribeTriggerLeave trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerLeave.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityDisableById.
E. Add an object that will be disabled when the avatar leaves the trigger area. The golden_coin entity has been added to the pick up specify execution entity.
EntitySubscribeCollisionStart
This guide provides instructions for setting up the EntitySubscribeCollisionStart trigger. In the sample app, the golden_coin is a trigger. Once the avatar collides with the golden_coin, an action occurs.
The avatar approaches the gold coin.
Once the avatar collides with the gold coin, the gold coin is removed.
In this example, a trigger is created and when the avatar collides with the trigger, an action is initiated. Any object can be used as a trigger, as long as the object has a collision component. Because this specific example uses a 3D object that the avatar can collide with, a RigidBody component needs to be added. In this example, the object golden_coin is used, but a simple cube will suffice.
Create a trigger for when an object collides with another object
1
Create the 3D object that the avatar will collide with
A. Add 3D object to the scene.
B. Add a Collision component.
C. Add a Rigidbody component.
D. Click the Edit Viverse Extension button.
2
Add the EntitySubscribeCollisionStart trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeCollisionStart.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityDisable.
EntitySubscribeCollisionEnd
This guide provides instructions for setting up the EntitySubscribeCollisionEnd trigger. In the sample app, a flattened 3D cube is a trigger. Once the avatar stops colliding with the cube, an action occurs.
The avatar is colliding with the red platform.
Once the avatar stops colliding with the red platform, the red platform begins to fade out.
In this example, a trigger is created and when the avatar or other objects collide with the trigger, an action is initiated. Any object can be used as a trigger, as long as the object has a collision component. Because this specific example uses a 3D object that the avatar can collide with, a RigidBody component needs to be added.
Create A Trigger Based On When An Object Stops Colliding With Another Object
1
Create the 3D object that the avatar will collide with
A. Add 3D object to the scene.
B. Add a Collision component.
C. Add a Rigidbody component.
D. Click the Edit Viverse Extension button.
2
Add the EntitySubscribeCollisionEnd trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeCollisionEnd.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityFadeOut.
NotificationCenterSubscribeEntityPicking
This guide provides instructions for setting up the NotificationCenterSubscribeEntityPicking trigger. In the sample app, the user clicks on the buttons to show and hide the whale.
The whale is visible.
When the user clicks on the whale, the whale is disabled.
In this example, a trigger area is created on a button. When the user clicks on the trigger area, an action causes the 3D model to be disabled. Any object can be used as a trigger, as long as the object has a collision component.
Create a trigger for when a user clicks an object
1
Create the 3D object that the user will click on
A. Add a 3D object to the scene. In this example, a button is used, but any 3D object will work.
B. Add a Collision component.
C. Click the Edit Viverse Extension button.
2
Add the NotificationCenterSubscribeEntityPicking trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select NotificationCenterSubscribeEntityPicking.
C. Add an Action and select EntityDisable. Add an object that will be disabled.
This guide provides instructions for setting up the NotificationCenterPublish action and the NotificationCenterSubscribe trigger. In the sample app, every time the avatar enters the green trigger area, a notification is sent to the wall and the collider on the wall is toggled on/off. The wall is green when the avatar can pass through and red when the avatar can not pass through.
Before the avatar enters the green trigger area, the wall is red and the avatar can not pass through the wall.
Once the avatar enters the green trigger area, the green trigger sends a notification to the wall and the collider on the wall is disabled.
In this example, a trigger is created and when the avatar enters the trigger area, an action sends a notification to another object. The other object receives the notification via trigger, then initiates an action.
Action and Trigger combination to send a notification from one object to another
1
Create the 3D object that will send the notification
A. Add a 3D object to the scene.
B. The Collision component is not required for NotificationCenterPublish action or NotificationCenterSubscribe trigger to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
C. Click the Edit Viverse Extension button.
2
Add the NotificationCenterPublish action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select NotificationCenterPublish.
E. Create a unique notification name and add it to the notification name to publish field. In this example, the notification is called ToggleWall.
3
Create the 3D object that will receive the notification
A. Add a 3D object to the scene.
B. The Collision component is not required for NotificationCenterPublish action or NotificationCenterSubscribe trigger to work. The Collision component is required for the EntityToggleCollision action that will be used in this example.
C. The Rigidbody component is not required for the NotificationCenterPublish action or NotificationCenterSubscribe trigger to work. The Rigidbody component is required for the EntityToggleCollision action that will be used in this example.
4
Add the NotificationCenterSubscribe action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select NotificationCenterSubscribe.
C. The same text that was added to the notification name to publish needs to be added to the notification name to subscribe.
D. Add an Action and select
Before the avatar enters the green trigger area, the wall is red and the avatar can not pass through it.
Once the avatar enters the green trigger area, the collider on the wall is toggled to be disabled. The wall is green and the avatar can pass through it.
In this example, a trigger is created and when the avatar enters the trigger area, an action sends a notification to toggle another object's collider on/off. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
An action that toggles an object's collider on/off
1
Create the 3D object that will send the notification
A. Add a 3D object to the scene.
B. The Collision component is not required for EntityToggleCollision action to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
C. Click the Edit Viverse Extension button.
2
Add the NotificationCenterPublish action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
3
Create the 3D object that will receive the notification
A. Add a 3D object to the scene.
B. Add a Collision component.
C. Add a Rigidbody component.
4
Add the EntityToggleCollision action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select NotificationCenterSubscribe.
EntityEnableCollision
Create An Action That Enables An Object's Collider
This guide provides instructions for setting up the EntityEnableCollision action. In the sample app, every time the avatar enters the red trigger area, a notification is sent to the wall object and the collider on the wall object is enabled. The wall is green when the avatar can pass through and red when the avatar can not pass through.
The avatar is able to pass through the wall when the wall’s collider is disabled.
Once the avatar enters the red trigger area, the EntityEnableCollision action enables the wall’s collider
The avatar is unable to pass through the wall once the wall’s collider is enabled.
In this example, a trigger is created and when the avatar enters the trigger area, an action sends a notification to enable another object's collider. Any object can be used as a trigger, as long as the object has a collision component.
1
Create a trigger area
A. Create a new 3D Box entity.
B. Add a Collision component.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
2
Add the EntitySubscribeTriggerEnter trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
3
Create the object that will have it's collider enabled
A. Create a new 3D Box entity.
B. Add a Collision component.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
4
Add the EntityEnableCollision action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select NotificationCenterSusbscribe.
EntityDisableCollision
Create An Action That Disables An Object's Collider
This guide provides instructions for setting up the EntityDisableCollision action. In the sample app, every time the avatar enters the green trigger area, a notification is sent to the wall object and the collider on the wall object is disabled. The wall is green when the avatar can pass through and red when the avatar can not pass through.
The avatar is unable to pass through the wall when the wall’s collider is enabled.
Once the avatar enters the green trigger area, the action disables the wall’s collider
The avatar is able to pass through the wall when the wall’s collider is disabled.
In this example, a trigger is created and when the avatar enters the trigger area, an action sends a notification to disable another object's collider. Any object can be used as a trigger, as long as the object has a collision component.
1
Create a trigger area
A. Create a new 3D Box entity.
B. Add a Collision component.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
2
Add the EntitySubscribeTriggerEnter trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
3
Create the object that will have it's collider disabled
A. Create a new 3D Box entity.
B. Add a Collision component.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
4
Add the EntityDisableCollision action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select NotificationCenterSubscribe.
Publishing to VIVERSE
Creators can host web-compatible content of all kinds on VIVERSE using Studio, the one-stop-shop for managing content on VIVERSE. Through Studio, creators can upload new experiences, apps, and videos, and monitor the performance of content already on VIVERSE. In addition to Studio, we also offer a Command Line Interface for creators uploading 3D experiences and applications to publish from the terminal (and even integrate publishing to VIVERSE directly into their tools).
Engaging 3D experiences are the bread and butter of VIVERSE. As part of HTC, the VIVERSE team has a rich legacy of empowering creators building in 3D and XR. As such, we have implemented several tools to help creators building 3D experiences.
Platform
Description
Documentation
Standalone App Publishing
Developers may publish to VIVERSE using any platform that can build for WebGL/HTML5. Publish from UnityWebGL, Godot, ThreeJS, Babylon, AFRAME, and more!
PlayCanvas Toolkit
PlayCanvas is an open source game engine with a web-based editor. We have created a toolkit for the PlayCanvas editor that allows creators to publish to VIVERSE with automatic support for multiplayer VIVERSE avatars.
Sharing Content
VIVERSE makes it easy for creators to share work with audiences both on and outside of VIVERSE. After uploading their creations to VIVERSE, creators may select from multiple visibility levels, participate in content curation and discovery, and embed their VIVERSE-hosted content on any webpage of their choosing.
At VIVERSE, our goal is not only to help creators share their work, but also to help creators earn from their creations! We offer a variety of tools for creators to earn on VIVERSE, including engagement-based compensation, channel subscriptions, paid titles, and in-app purchases. Additionally, we frequently host competitions and programs where creators can participate and receive rewards and funding for building with VIVERSE.
Learn more about !
Optimization
The web browser is the most accessible platform for content sharing across the internet. Billions of devices, from mobile phones, to desktop computers, and VR headsets, have access to the browser! However, with so many potential users and devices, it is important to ensure that your content performs well for all of your intended users. Even if you do not have experience building for the web browser, we are here to help creators bring their work to the web for the first time!
Learn more about !
The Creator Community & Getting Support
VIVERSE is proud to support the work many of the most innovative artists, developers, educators, and entrepreneurs across the world. Our Community Discord Server is the epicenter of our creator community and the best way to get connected with other innovative builders.
In the Discord Server, the community and VIVERSE team would love to hear your questions, bug reports, and ideas for making a more accessible platform. Simply create a new post in the #get-help channel when you land.
This document provides several guides that can be used to show and hide objects in a VIVERSE project. These actions can be configured to execute when triggers are activated.
EntityDisable
This guide provides instructions for setting up the EntityDisable action. In the sample app, once the avatar collides with the gold coin, the gold coin is disabled.
In this example, a trigger is created and when triggered, an action disables an object.
Create an action that disables an object
1
Create the 3D Object that will be disabled
A. Add 3D object to the scene.
B. The Collision component is not required for EntityDisable action to work. The Collision component is required for the EntitySubscribeCollisionStart trigger that will be used in this example.
C. The Rigidbody component is not required for the EntityDisable action to work. The Rigidbody component is required for the EntitySubscribeCollisionStart trigger that will be used in this example.
EntityEnableById
This guide provides instructions for setting up the EntityEnableById action. In the sample app, once the avatar enters the trigger area, the gold coin is enabled.
In this example, a trigger is created and when triggered, an action enables an object. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
Create an action that enables a single object
1
Create a trigger area
A. Create a new 3D Box entity.
B. The Collision component is not required for EntityDisableById action to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
EntityDisableById
This guide provides instructions for setting up the EntityDisableById action. In the sample app, once the avatar leaves the trigger area, the gold coin is disabled.
In this example, a trigger is created and when triggered, an action disables an object. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
Create an action that disables a single object
1
Create a trigger area
A. Create a new 3D Box entity.
B. The Collision component is not required for EntityDisableById action to work. The Collision component is required for the EntitySubscribeTriggerLeave trigger that will be used in this example.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
2
EntityEnableByTag
This guide provides instructions for setting up the EntityEnableByTag action. In the sample app, once the avatar enters the trigger area, multiple balls are enabled.
In this example, a trigger is created and when triggered, an action enables multiple objects. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
Create an action that enables multiple objects
1
Create a trigger area
A. Create a new 3D Box entity.
B. The Collision component is not required for EntityEnableByTag action to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
EntityDisableByTag
This guide provides instructions for setting up the EntityDisableByTag action. In the sample app, once the avatar leaves the trigger area, multiple balls are disabled.
In this example, a trigger is created and when triggered, an action disables multiple objects. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
Create an action that disables multiple objects
1
Create a trigger area
A. Create a new 3D Box entity.
B. The Collision component is not required for EntityDisableByTag action to work. The Collision component is required for the EntitySubscribeTriggerLeave trigger that will be used in this example.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
Click the Edit Viverse Extension button.
EntityFadeIn
This guide provides instructions for setting up the EntityFadeIn action. In the sample app, once the avatar starts colliding with the red platform, the red platform will fade in.
In this example, a trigger is created and when triggered, an action fades in the object it has been added to. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
Create an action that fades in an object
1
Create the 3D object that will fade in
A. Add a 3D object to the scene.
B. A Collision component is not required for the EntityFadeIn action to work. The Collision component is required for the EntitySubscribeCollisionStart trigger that will be used in this example.
C. A Rigidbody component is not required for the EntityFadeIn action to work. The Rigidbody component is required for the EntitySubscribeCollisionStart trigger that will be used in this example.
EntityFadeOut
This guide provides instructions for setting up the EntityFadeOut action. In the sample app, once the avatar stops colliding with the red platform, the red platform will fade out.
In this example, a trigger is created and when triggered, an action fades an object. Any object can be used as a trigger, as long as the object has a collision component.
Create an action that fades out an object
1
Create the 3D object that will fade out
A. Add a 3D object to the scene.
B. A Collision component is not required for the EntityFadeOut action to work. The Collision component is required for the EntitySubscribeCollisionEnd trigger that will be used in this example.
C. A Rigidbody component is not required for the EntityFadeOut action to work. The Rigidbody component is required for the EntitySubscribeCollisionEnd trigger that will be used in this example.
EntityToggleEnabled
This guide provides instructions for setting up the EntityToggleEnabled action. In the sample app, every time the avatar enters the blue trigger area, a notification is sent to the purple box to toggle it’s enabled state.
In this example, a trigger is created and when the avatar or other objects enter the trigger area, an action sends a notification to toggle another object's enabled state. Any object can be used as a trigger, as long as the object has a collision component.
Create an action that toggles an object's enabled state
1
Create a trigger area
A. Create a new 3D Box entity.
B. A Collision component is not required for the EntityToggleEnabled action to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
Animation & Sound
This document provides several guides that can be used to setup event listeners for animations, control animations and control audio in a VIVERSE project.
EntityPlayAnimation
Create An Action That Plays An Animation
This guide provides instructions for setting up the EntityPlayAnimation action. In the sample app, once the avatar enters the trigger area, the character switches to the dancing animation state. When the avatar leaves the trigger area, the character switches back to the idle animation state.
In this example, a trigger area is created and when triggered, an action plays an animation. Any object can be used as a trigger, as long as the object has a collision component.
1
Create the animation state graph
A. Create an Animation State Graph and rename the initial state to Idle.
B. Create an additional animation state and name it Dancing.
EntitySubscribeAnimationStart
Create A Trigger Based On When An Animation Starts
This guide provides instructions for setting up the EntitySubscribeAnimationStart trigger. In the sample app, when the avatar enters the blue trigger area, the character’s dancing animation begins to play. The dancing animation has an animation event added and the animation event is triggered whenever the animation starts to play.
In the EntityPlayAnimation example, a 3D model was added, an animation state graph was created, animation states were created and a trigger area was created to initiate the animations. In this example, an animation event is created for the start of the animation.
1
Open animation file that will have the animation event
A. Click on the animation file to open up the properties.
2
EntitySubscribeAnimationEnd
Create A Trigger Based On When An Animation Ends
This guide provides instructions for setting up the EntitySubscribeAnimationEnd trigger. In the sample app, when the avatar enters the blue trigger area, the character’s dancing animation begins to play. The dancing animation has an animation event added and the animation event is triggered whenever the animation stops playing.
In the EntityPlayAnimation example, a 3D model was added, an animation state graph was created, animation states were created and a trigger area was created to initiate the animations. In this example, an animation event is created for the end of the animation.
1
Open animation file that will have the animation event
A. Click on the animation file to open up the properties.
2
EntitySubscribeAnimationEvent
Create A Trigger Based On A Specific Time During An Animation
This guide provides instructions for setting up the EntitySubscribeAnimationEvent trigger. In the sample app, when the avatar enters the blue trigger area, the character’s dancing animation begins to play. The dancing animation has an animation event added and the animation event is triggered during the animation.
In the EntityPlayAnimation example, a 3D model was added, an animation state graph was created, animation states were created and a trigger area was created to initiate the animations. In this example, an animation event is created for during the animation.
1
Open animation file that will have the animation event
A. Click on the animation file to open up the properties.
2
EntityPlaySound
Create An Action That Plays A Sound
This guide provides instructions for setting up the EntityPlaySound action. In the sample app, once the avatar enters the trigger area, a sound plays.
In this example, a trigger is created and when triggered, an action plays a sound. Any object can be used as a trigger, as long as the object has acollisioncomponent. This example uses a 3D box as the trigger area.
1
Create a trigger area
A. Create a new 3D Box entity.
B. The Collision component is not required for EntityPlaySound action to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
EntityStopSound
Create An Action That Stops Playing A Sound
This guide provides instructions for setting up the EntityStopSound action. In the sample app, once the avatar leaves the trigger area, the sound stops playing.
In this example, a trigger is created and when triggered, an action plays a sound. Any object can be used as a trigger, as long as the object has acollisioncomponent. This example uses a 3D box as the trigger area.
1
Create a trigger area
A. Create a new 3D Box entity.
B. The Collision component is not required for EntityStopSound action to work. The Collision component is required for the EntitySubscribeTriggerLeave trigger that will be used in this example.
Connecting No-Code Events to Custom Scripts
This document provides a guide for setting up no-code events in custom scripts.
The VIVERSE no-code events can be accessed through custom scripts. The events can be found in the root directory of your PlayCanvas project in the @viverse/create-extensions-sdk.mjs file. Here's a look at the file.
Trigger usage
Calling custom code from script when the player clicks on an object
Let's say we want to give our players the ability to click on an object and when that object is clicked, we want to call a method from a custom script. This is a good use-case for the NotificationCenterSubscribeEntityPicking trigger. In this example, when the user clicks on the specific object, a door opens.
1
Add the NotificationCenterSubscribeEntityPicking trigger
A. Select the object that the player will click on and add the NotificationCenterSubscribeEntityPicking trigger using the PlayCanvas extension. No need to add an action.
2
Tigger usage with more flexibility
Calling custom code from script when the player clicks on an object and making the script more flexible
In the previous example, we created a custom script called ClickableObject.mjs. The script added functionality that rotates a door whenever a specific object is clicked. Let's say there was another scenario where we wanted to have a 2nd object that the user could click on, but we wanted to fire a different event other than the rotateDoor method. We could easily copy our ClickableObject.mjs script, give it a different name and change the rotateDoor call inside the script. The downside here is that we now have 2 scripts that we have to maintain. As alternative, we can remove the rotateDoor event call, add an attribute to our script for the event name and then add the different event names through the PlayCanvas editor.
1
Update the ClickableObject.mjs script
A. Modify the code in ClickableObject.mjs script to the following.
2
Additional trigger usage
Calling custom code from script when a player enters a trigger area
Another common scenario that creators may face is firing an event when a player enters a trigger area. This is a good use-case for the EntitySubscribeTriggerEnter trigger. In this example, when the user enters a trigger area, a door opens.
1
Add the EntitySubscribeTriggerEnter trigger
A. Select the trigger area that the player will walk through and add the EntitySubscribeTriggerEnter trigger using the PlayCanvas extension. No need to add an action.
2
Action usage
Calling custom code from script when an action executed
Let's say we want to give our players the ability to click on an object and when that object is clicked, we want to call a method from a custom script. This is a good use-case for the NotificationCenterSubscribeEntityPicking trigger. In this example, when the user clicks on the specific object, a door opens.
1
Add the EntitySubscribeTriggerEnter trigger and the EntityDisable action
A .Select the trigger area that the player will walk through and add the EntitySubscribeTriggerEnter trigger along with the EntityDisable action using the PlayCanvas extension.
2
ThreeJS
This document provides a guide for creating a sample app in Three.js, building the app with Vite and deploying the app to VIVERSE.
Introduction
In this getting-started guide, we will cover the basics of setting up a ThreeJS project and publishing to VIVERSE using .
PlayCanvas Toolkit Changelog
Get download link to the latest version of VIVERSE Extension and explore the changelog.
E. Create a unique notification name and add it to the notification name to publish field. In this example, the notification is called ToggleWall.
D. Click the Edit Viverse Extension button.
C. The same text that was added to the notification name to publish needs to be added to the notification name to subscribe.
D. Add an Action and select EntityToggleCollision.
C. Add local-player to the tags to filter field.
E. Add an Action and select NotificationCenterPublish.
F. Create a unique notification name and add it to the notification name to publish field. In this example, the notification is called EnableWall.
D. Click the Edit Viverse Extension button.
C. The same text that was added to the notification name to publish needs to be added to the notification name to subscribe.
D. Add an Action and select EntityEnableCollision.
C. Add local-player to the tags to filter field.
E. Add an Action and select NotificationCenterPublish.
F. Create a unique notification name and add it to the notification name to publish field. In this example, the notification is called DisableWall.
D. Click the Edit Viverse Extension button.
C. The same text that was added to the notification name to publish needs to be added to the notification name to subscribe.
D. Add an Action and select EntityDisableCollision.
D. Click the Edit Viverse Extension button.
2
Add the EntityDisable action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeCollisionStart.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityDisable.
2
Add the EntityEnableById action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityEnableById.
E. Add an object that will be enabled when the avatar enters the trigger area. The golden_coin entity has been added to the pick up specify execution entity. The golden_coin entity has also been disabled by default.
Add the EntityDisableById action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerLeave.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityDisableById.
E. Add an object that will be disabled when the avatar leaves the trigger area. The golden_coin entity has been added to the pick up specify execution entity. The golden_coin entity has also been disabled by default.
2
Add the EntityEnableByTag action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityEnableByTag.
E. Create a unique Tag and add it to the enable entity with tag field. In this example, the Balls tag is added.
3
Add Tag to multiple objects
A. Multiple objects can be enabled using the EntityEnableByTag action. Create multiple objects in the scene.
B. In the Tags field, add the same tag from the enable entity with tag field. Do this for all of the objects or parents of multiple objects.
2
Add the EntityDisableByTag action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerLeave.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityDiableByTag.
E. Create a unique Tag and add it to the enable entity with tag field. In this example, the Balls tag is added.
3
Add EntityEnableByTag to multiple objects
A. Multiple objects can be enabled using the EntityEnableByTag action. Create multiple objects in the scene.
B. In the Tags field, add the same tag from the enable entity with tag field to all of the objects or parents of multiple objects.
D. Click the Edit Viverse Extension button.
2
Add the EntityFadeIn action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeCollisionStart.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityFadeIn. To customize how long before the fade begins or duration of the fade, update delay in ms and duration in ms fields.
D. Click the Edit Viverse Extension button.
2
Add the EntityFadeOut action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeCollisionEnd.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityFadeOut. To customize how long before the fade begins or duration of the fade, update delay in ms and duration in ms fields.
2
Add the NotificationCenterPublish action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select NotificationCenterPublish.
E. Create a unique name for the notification and add it to the notification name to publish field. In this example, the ToggleEnabled name is added.
3
Create a 3D object that will have it's enabled state toggled
A. Add a 3D object to the scene.
B. Click the Edit Viverse Extension button.
4
Add the NotificationCenterSubscribe trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select NotificationCenterSubscribe.
C. In the notification name to subscribe field, add the same name from the notification name to publish field.
D. Add an Action and select EntityToggleEnabled.
The avatar is not colliding with the gold coin.
Once the avatar collides with gold coin, the gold coin is disabled.
When the avatar is outside of the blue trigger area, the gold coin is disabled.
When the avatar enters the blue trigger area, the gold coin is enabled.
When the avatar is inside the blue the trigger area, the gold coin is enabled.
When the avatar leaves the blue trigger area, the gold coin is disabled.
When the avatar is outside the blue trigger area, the balls are disabled.
When the avatar enters the blue trigger area, the balls are enabled.
When the avatar enters the blue trigger area, the balls are enabled.
When the avatar leaves the blue trigger area, the balls are disabled.
The red platform has been faded out and is invisible, but the avatar can still collide with it.
Once the avatar begins colliding with the invisible red platform, the red platform fades in and is now visible.
The avatar is colliding with the red platform.
Once the avatar stops colliding with the red platform, the red platform begins to fade out.
The purple box is enabled/visible before the avatar enters the blue trigger area.
Once the avatar enters the blue trigger area, a notification is sent to the purple box to toggle it’s enabled stated. The purple box is disabled.
The avatar leaves the blue trigger area.
Once the avatar enters the blue trigger area again, a notification is sent to the purple box to toggle it’s enabled stated. The purple box is enabled again.
2
Configure 3D model for animation
A. Add a 3D model to the scene.
B. Add an Anim component.
C. Add the Animation State Graph.
D. Add the Idle animation.
E. Add the Dancing animation.
3
Create a trigger area
A. Create a new 3D Box entity.
B. The Collision component is not required for EntityPlayAnimation to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
4
Add the EntityPlayAnimation action for the dancing animation state
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityPlayAnimation.
E. Add the name of an animation state to the animate state to play field. In this example, the animation state name is Dancing.
F. Add the 3d model to the pick up specify execution entity field.
5
Add the EntityPlayAnimation action for the Idle animation state
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerLeave.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityPlayAnimation.
E. Add the name of an animation state to the animate state to play field. In this example, the animation state name is Idle.
F. Add the 3d model to the pick up specify execution entity field.
Create animation event
A. Create an event, add value 0 to the time field and start to the name field.
3
Add the EntitySubscribeAnimationStart trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeAnimationStart.
C. Add an Action and select EntityEnableById.
D. For the EntityEnableById action to work, an object needs to be added that will be enabled. In this example, the AnimationStartText object is added.
Create animation event
A. Create an event, add value 8 to the time field and end to the name field. The value 8 is used because the dancing animation has a duration of 8.83 seconds.
3
Add the EntitySubscribeAnimationEnd trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeAnimationEnd.
C. Add an Action and select EntityEnableById.
D. For the EntityEnableById action to work, an object needs to be added that will be enabled. In this example, the AnimationEndText object is added.
Create animation event
A. Create an event, add value 4 to the time field and create a unique name for the event. In this example, the event name animate was added to the name field.
3
Add the EntitySubscribeAnimationEvent trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeAnimationEvent.
C. Add the event name to the event name to subscribe.
D. Add an Action and select EntityEnableById.
E. For the EntityEnableById action to work, an object needs to be added that will be enabled. In this example, the AnimationEventText object is added.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Add a Sound component.
E. Create a unique name for the sound file and add it to the name field. In this example, Slot2 is added.
F. Add the audio file to the Asset field.
G. Click the Edit Viverse Extension button.
2
Add the EntityPlaySound action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityPlaySound.
E. In the sound name to play field, add the same name that was created on the Sound component.
F. Add the entity with the Sound component to the pick up specify execution entity.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Add a Sound component.
E. Create a unique name for the sound file and add it to the name field. In this example, Slot2 is added.
F. Add the audio file to the Asset field.
G. Click the Edit Viverse Extension button.
2
Add the EntityStopSound action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerLeave.
C. Add local-player to the tags to filter field.
D. Add an Action and select EntityStopSound.
E. In the sound name to play field, add the same name that was created on the Sound component.
F. Add the entity with the Sound component to the pick up specify execution entity.
The character is in the idle state when the avatar is outside of the trigger area.
The character switches to the dancing animation state when the avatar enters the trigger area.
Before the character’s dancing animation begins.
When the character’s dancing animation begins, the animation event is triggered and text is displayed to show that the animation event was triggered.
The character’s dancing animation has started.
When the character’s dancing animation ends, the animation event is triggered and text is displayed to show that the animation event was triggered.
The character’s dancing animation has started.
During the character’s dancing animation, the animation event is triggered and text is displayed to show that the animation event was triggered.
The avatar is outside of the blue trigger area and the sound does not play.
The avatar enters the blue trigger area and the sound plays.
The avatar enters the blue trigger area and the sound plays.
The avatar is outside of the blue trigger area and the sound stops playing.
Create the ClickableObject.mjs script
A. Create the following script and name it ClickableObject.mjs.
B. Add ClickableObject.mjs script to the object that the player will click on.
3
Create the DoorRotator.mjs script
A. Create the following script and name it DoorRotator.mjs.
B. Add the DoorRotator.mjs script to an object or entity.
4
Confirm the event is being fired
A. Test the functionality by publishing to VIVERSE and clicking on the object that has the ClickableObject.mjs script added to it.
B. Confirm the event was fired by checking in the browser debug console.
Add the event name in to the script inside the PlayCanvas editor
A. Add the DoorRotator:rotateDoor text to the Event To Fire attribute text field.
B. If we added ClickableObject.mjs to a 2nd object and wanted to fire a different method, it could look like the following screenshot.
3
Confirm the event is being fired
A. Test the functionality by publishing to VIVERSE and clicking on the object that has the ClickableObject.mjs script added to it.
B. Confirm the event was fired by checking in the browser debug console. It should yield the same results as in the previous example.
Create the TriggerArea.mjs script
A. Create the following script and name it TriggerArea.mjs.
B. Add TriggerArea.mjs script to trigger area that the player will walk through.
3
Confirm the event is being fired
A. Test the functionality by publishing to VIVERSE and walking through the trigger area that has the TriggerArea.mjs script added to it.
B. Confirm the event was fired by checking in the browser debug console. It should yield the following results.
Create the DisabledObject.mjs script
A. Create the following script and name it DisableObject.mjs.
B. Add DisabledObject.mjs script to trigger area that the player will walk through. In this example the DisabledObject.mjs script was added to the trigger area in the previous example. Be sure to disable or remove the TriggerArea.mjs script from the previous example.
3
Confirm the event is being fired
A. Test the functionality by publishing to VIVERSE and walking through the trigger area that has the DisabledObject.mjs script added to it.
B. Confirm the event was fired by checking in the browser debug console. It should yield the following results.
A. Use the defaults during the installation, but place a checkmark
in the Automatically install the necessary tools checkbox
3
Confirm Node.js is installed with at least v22
A. Open a command prompt and type: node, then click Enter.
B. Confirm that Node.js is installed when the following message prints in command prompt: Welcome to Node.js v##.##.##.
Installing Three.js and making an example project
This guide is a walkthrough for creating an example Three.js project
1
Create project folder
A. Create a new folder that will contain the project.
2
Create the index.html
A. Create the index.html page inside the project folder. This can be done by creating a text file, pasting the code and saving it as a .HTML page or using an IDE, such as Visual Studio Code.
index.html
3
Create the main.js
A. Create the main.js page inside the project folder. This can be done by creating a text file, pasting the code and saving it as a .JS file or using an IDE, such as Visual Studio Code.
main.js
4
Install Three.js framework
A. Three.js needs to be installed in the project folder. Open command prompt and change directories to your Three.js project.
B. Type: npm install --save three.
5
Confirm Three.js framework is installed
A. Confirm node_modules folder and package.json have been added to the directory.
B. Confirm the three folder folder and .package-lock.json
Installing Vite and using it to build your project
1
Install the build tool Vite
A. If choosing to use Vite as the build tool, it needs to be installed in the Three.js project folder also. With command prompt opened and the directory set to your Three.js project, type the command: npm install --save-dev vite.
2
Confirm Vite has been installed
A. Confirm Vite has been installed by checking for additional folders in the node_modules folder.
3
Add the Vite build settings
A. Add the Vite build settings to package.json file.
package.json
4
Add the vite.config.js file
A. Add the vite.config.js file to the root of the project.
vite.config.js
5
Create a development build of the Three.js project
A. To create a development build of the Three.js project, type the following command inside command prompt under the Three.js project directory: npx vite.
B. Confirm the development build of the Three.js project was built successfully when Vite provides a
6
Test development build
A. To test a development build of the Three.js project, open the browser and navigate to the URL that was printed in the previous step. In this example, the URL is . Confirm the app works as expected.
7
Create production build
A. To create a production build of the Three.js project, type the following command inside command prompt under the Three.js project directory: npx vite build.
B. Confirm the production build of the Three.js project was built successfully by confirming the dist folder was created and populated.
Installing the VIVERSE CLI
1
Install the VIVERSE (CLI) command-line tool
A. Inside a command prompt, type: npm install -g @viverse/cli, then click Enter. Installing a package with -g installs the package globally. The location of globally installed packages depends on your operating system and npm configuration:
Windows : In windows, packages are installed in %APPDATA%\npm\node_modules.
macOS and Linux : In mac or Linux packages are typically installed in /usr/local/lib/node_modules or a user-specific directory like ~/.npm-global.
B. Confirm that the command line tool is installed based on screen feedback.
Logging in with the VIVERSE CLI
1
Login to VIVERSE platform
A. Open a command prompt and type: viverse-cli auth login, then click Enter.
B. Enter VIVERSE email and password.
C. Confirm login was successful.
Publishing from VIVERSE
1
Publish content
A. To publish content to VIVERSE type the following command with the project path to the project's production build folder: viverse-cli publish <path>, then click Enter.
B. Enter an Application title and Application description.
C. Confirm the content was published successfully.
2
Re-publishing content
A. To re-publish content to VIVERSE when a project is already published, type the following command with the project path to the project's production build folder: viverse-cli publish <path>, then click Enter.
B. Confirm the manifest file is updated.
C. Confirm the content was published successfully.
3
Test project
A. Confirm project was published successfully and working properly in VIVERSE by visiting the URL that is printed in the Publish Details.
Fix the issue where adding or removing a post effect doesn’t immediately update the UI
Update Polygon Streaming SDK to 2.6.8
8/15/2025
Adds support for publishing PlayCanvas projects that utilize multiple scenes, as well as an IWorldNavigationService to the Create SDK API to allow for programmatic scene switching.
Adds the ability to set nearClip and farClip camera configuration:
Create from Templates
Create from our library of world templates and add 3D elements and media directly in VIVERSE. World decoration is great for meetup hosts and beginners looking to customize their first world from a wide range of template environments.
This document provides a guide that can be used to add a seat to objects in VIVERSE project. This allows the avatar to sit down.
Seat
Add functionality to allow avatar to sit down
1
Add the chair
A. In this example, the chairs and table have been created in the scene under a single entity.
B. Click the Edit Viverse Extension button.
import { Script } from 'playcanvas';
import { TriggerTypes } from '../@viverse/create-extensions-sdk.mjs';
export class ClickableObject extends Script {
/**
* Called when the script is about to run for the first time.
*/
initialize() {
const event = TriggerTypes.NotificationCenterSubscribeEntityPicking;
this.entity.on(event, () => {
this.objectClicked();
this.app.fire('DoorRotator:rotateDoor');
});
}
/**
* Called for enabled (running state) scripts on each tick.
*
* @param {number} dt - The delta time in seconds since the last frame.
*/
update(dt) {
}
objectClicked() {
console.log('Objected Clicked!');
}
}
import { Script } from 'playcanvas';
export class DoorRotator extends Script {
/**
* Called when the script is about to run for the first time.
*/
initialize() {
// listen for the DoorRotate:rotateDoor event
this.app.on('DoorRotator:rotateDoor', this.rotateDoor);
}
/**
* Called for enabled (running state) scripts on each tick.
*
* @param {number} dt - The delta time in seconds since the last frame.
*/
update(dt) {
}
rotateDoor() {
console.log('Rotate Door!');
}
}
import { Script } from 'playcanvas';
import { TriggerTypes } from '../@viverse/create-extensions-sdk.mjs';
export class TriggerArea extends Script {
/**
* Called when the script is about to run for the first time.
*/
initialize() {
const event = TriggerTypes.EntitySubscribeTriggerEnter;
this.entity.on(event, () => {
this.triggerEntered();
this.app.fire('DoorRotator:rotateDoor');
});
}
/**
* Called for enabled (running state) scripts on each tick.
*
* @param {number} dt - The delta time in seconds since the last frame.
*/
update(dt) {
}
triggerEntered() {
console.log('Trigger Entered!');
}
}
import { Script } from 'playcanvas';
import { ActionTypes } from '../@viverse/create-extensions-sdk.mjs';
export class DisabledObject extends Script {
/**
* Called when the script is about to run for the first time.
*/
initialize() {
const event = ActionTypes.EntityDisable;
this.entity.on(event, () => {
this.objectDisabled();
this.app.fire('DoorRotator:rotateDoor');
});
}
/**
* Called for enabled (running state) scripts on each tick.
*
* @param {number} dt - The delta time in seconds since the last frame.
*/
update(dt) {
}
objectDisabled() {
console.log('Object Disabled!');
}
}
import { Script } from 'playcanvas';
import { TriggerTypes } from '../@viverse/create-extensions-sdk.mjs';
export class ClickableObject extends Script {
/**
* @attribute
* eventToFire
* @type { string }
* @title Event To Fire
*/
eventToFire
/**
* Called when the script is about to run for the first time.
*/
initialize() {
const event = TriggerTypes.NotificationCenterSubscribeEntityPicking;
this.entity.on(event, () => {
this.objectClicked();
this.app.fire(this.eventToFire);
});
}
/**
* Called for enabled (running state) scripts on each tick.
*
* @param {number} dt - The delta time in seconds since the last frame.
*/
update(dt) {
}
objectClicked() {
console.log('Objected Clicked!');
}
}
A. In the VIVERSE extension, select the Seat plugin for the Select plugins dropdown.
B. Select the Seat module and add it.
C. Add a value to the number of seats field.
3
Adjust the sitting boundary
A. The Seat is automatically generated.
B. Adjust the Radius on the Collision component to modify the sitting boundary.
4
View the SeatHintFarAway icon
A. The SeatHintFarAway icon is a white dot that is automatically generated and hovers above each seat.
5
Adjust the boundary for the SeatHintFarAway icon
A. The SeatHintFarAwayTriggerSphere is automatically generated.
B. Adjust the Radius on the Collision component to modify the distance away before the SeatHintFarAway icon displays. Also ensure the height of the collider is above ground level, so the player capsule collider is sure to intersect with it.
6
View the SeatHint button
A. The SeatHint button has an icon of a sitting person. The button is automatically generated and hovers above each seat. When clicked, the avatar will sit.
7
Adjust the boundary for the SeatHint button
A. The SeatHintTriggerSphere is automatically generated.
B. Adjust the Radius on the Collision component to modify the distance away before the SeatHint icon displays.
When the avatar enters the SeatHintFarAwayTriggerSphere, the SeatHintFarAway icon (white dot) shows above the seat.
When the avatar enters the SeatHintTriggerSphere, the SeatHint button (sitting person icon) shows above the seat.
When the avatar clicks on the SeatHint button, the avatar sits down.
Flying in VR: switch to Smooth Locomotion using the XRService, then in any World where flying is enabled in World Settings, press down/click the Smooth Locomotion joystick to enter flight mode. Once flying, pressing forward on the joystick will fly forward along the VR camera's forward axis (i.e. wherever you're looking), and vice versa backwards.
Bug fix: prevent duplicate injection of custom loading screen scripts during publishing.
Re-enables debugging in the browser by adding publishing modes: Debug mode is designed to assist in development and debugging processes, whereas Standard mode delivers an optimized, minified build intended for distribution.
This page details how to publish to VIVERSE from the VR illustration tool Open Brush.
Introduction
In December 2025, VIVERSE and the Icosa Foundation, Open Brush's steward, teamed up with digital artist SUTU to create a publishing pipeline for Open Brush creators to host, distribute, and monetize their work on VIVERSE. When publishing to VIVERSE, creators are able to share their work on Mobile, Desktop, and VR through the web browser, complete with networked VRM avatars and real-time chat. The publishing process is a simple and powerful way for Open Brush creators to expand their audiences and make their work more accessible!
Publishing Tutorial
1
Sign into VIVERSE from Open Brush
Within the Open Brush application in VR, navigate to the "Accounts" toolbar and select "VIVERSE" to open the browser window. Enter your VIVERSE account credentials and complete the sign in process, closing the browser window when prompted.
2
Tips & Troubleshooting
What should I do after publishing?
After publishing, we encourage all creators to curate their and . These help with discoverability on VIVERSE.
We also encourage creators to take advantage of the easy sharing of your work on VIVERSE. You can quickly share your VIVERSE url with anyone and even embed it on your artistic website. If you post your world, tag @VIVERSEOfficial on all platforms and we will help share!
How can I monetize my Open Brush work?
We want to help Open Brush creators earn from their awesome work on VIVERSE! Consult our and contact our team if you have any questions.
How can I get help or request a new feature?
In the , we have a dedicated #open-brush channel where we want to hear your feedback, bug reports, and feature requests!
Are there any content restrictions on VIVERSE?
All Open Brush content must abide by the . In general, these terms restrict the depiction of NSFW content.
import { defineConfig } from 'vite';
import path from 'path';
// https://vite.dev/config/
export default defineConfig({
base: './', // Use relative path as base URL
});
Navigate to the "Upload" tab and select VIVERSE. Wait for the uploading process to complete.
3
Test and Finish Publishing on VIVERSE Studio
After uploading, a web browser window will open with studio.viverse.com. From here, sign into VIVERSE if necessary, and finish accessing and testing your world.
This document provides a guide that can be used to add a physics force to objects in VIVERSE project. The action can be configured to execute when a trigger is activated.
EntityRigidbodyAddForceInPhysics
Create An Action That Adds Force To An Object
This guide provides instructions for setting up the EntityRigidbodyAddForceInPhysics action. In the sample app, once the avatar enters the blue trigger area, a force is applied to the sphere.
In this example, a trigger is created and when the avatar or other objects enters the trigger area, an action adds force to an object. Any object can be used as a trigger, as long as the object has a collision component. This example uses a 3D box as the trigger area.
1
Create a trigger area
A. Create a new 3D Box entity.
B. This Collision component is not required for the EntityRigidbodyAddForceInPhysics action to work. The Collision component is required for the EntitySubscribeTriggerEnter trigger that will be used in this example.
Introduction to MJS
This document provides an introduction to MJS (.mjs) also known as Modular JavaScript
Modular JavaScript is an evolved form of JavaScript in which related functionality is kept in a single file or module and that functionality is exposed when required using import and export functionality.
CommonJS (NodeJS) example
Here's a comparison between MJS and CommonJS. The latter requires node.js, and relies on require() statements to import other scripts/modules:
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
2
Add the EntitySubscribeTriggerEnter trigger
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select NotificationCenterPublish.
E. Create a unique name for the notification and add it to the notification name to publish field. In this example, the AddForce name is added.
3
Create the 3D object that the physics force will be applied to
A. Create a new 3D object.
B. Add a Collision component.
C. Add a Rigidbody component.
D. Set the Collision Type to Dynamic.
E. Click the Edit Viverse Extension button.
4
Add the EntityRigidbodyAddForceInPhysics action
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select NotificationCenterSubscribe.
C. The same text that was added to the notification name to publish needs to be added to the notification name to subscribe.
D. Add an Action and select EntityRigidbodyAddForceInPhysics.
E. In the X Force, Y Force and Z Force fields, add values for the amount of force to apply in each direction.
The sphere is not moving before the avatar enters the trigger area.
Once the avatar enters the trigger area, a force is applied to the sphere in the direction based on the parameters.
MJS, on the other hand, can use import statements like other languages.
MJS PlayCanvas Script Structure
Further, MJS is now supported by PlayCanvas and the VIVERSE Create SDK, to make script imports easier and mroe modern. Here's an example of a script called GameManager.mjs (critically, the file extension is .mjs, not just .js as usual) created for PlayCanvas, extending its built-in Script class:
Accessing a function in a MJS(.mjs) file from regular JavaScript (.js) code example
DoorRotator.mjs can can be added to a PlayCanvas entity. This allows functions to be executed on that entity such as a door that needs to be opened. After adding additional code inside the rotateDoor function, this function can be called from another script to open the door.
TriggerArea.js - Script can be added to a trigger area entity. When another entity or the avatar enters the trigger area, the rotateDoor function is called and the door will open.
Debugging MJS files
The process for debugging MJS files is simple. You can add the debugger; statement to any of the methods.
With the project running in Chrome, pressing F12 will bring up the Chrome DevTools window. Refresh the page with the DevTools window open and the project will stop at the debugger statement.
When testing your project in PlayCanvas Launch mode, the Chrome Dev Tools can also be opened by right-clicking on the screen and selecting Inspect.
1
Right-click on the viewing area of the project
2
Select Inspect
Open up Chrome DevTools through browser menu
1
Click the Customize and control Google Chrome Button in the browser
2
Click More Tools
3
Click Developer Tools
Keyboard shortcut for DevTools window
Breakpoints can also be set manually by clicking on the line code number in the margin. The line code number will be highlighted in blue when a breakpoint is set.
MJS file with custom properties and methods example
GameManager.mjs - GameManager script can be used to control the different game states of the project. This example script has multiple properties of different types added (including arrays), some with default values. In addition to the properties, there are multiple functions added that show how these properties can be utilized and their values are printed to the console.
import { Script } from 'playcanvas';
import * as pc from 'playcanvas';
import { PlayerService } from '../@viverse/create-sdk.mjs'
export class LocalPlayerManager extends Script
{
initialize() {
this.playerService = new PlayerService();
//attach playerService for global access, reference this.app.playerServiceManager in other files
this.app.playerServiceManager = this;
//FOR ALL CUSTOMIZABLE PROPS AND METHODS, see: https://viveportsoftware.github.io/pc-lib/interfaces/ILocalPlayer.html
//enable flight
this.playerService.localPlayer.canFly = true;
//enable movement
this.playerService.localPlayer.canMove = true;
//hide avatar
this.playerService.localPlayer._entity.visibility = false;
}
update(dt)
{
}
}
import { Script } from 'playcanvas';
import * as pc from "playcanvas"
import { CameraService } from './@viverse/create-sdk.mjs'
/**
* The {@link https://api.playcanvas.com/classes/Engine.Script.html | Script} class is
* the base class for all PlayCanvas scripts. Learn more about writing scripts in the
* {@link https://developer.playcanvas.com/user-manual/scripting/ | scripting guide}.
*/
export class CameraServiceManager extends Script {
/**
* Called when the script is about to run for the first time.
*/
initialize() {
this.cameraService = new CameraService();
//FOR ALL CUSTOMIZABLE PROPS AND METHODS, see https://viveportsoftware.github.io/pc-lib/interfaces/ICameraService.html
//switch to 1st person pov
this.cameraService.switchPov(0);
//prevent pov switching
this.cameraService.canSwitchPov = false;
}
/**
* Called for enabled (running state) scripts on each tick.
*
* @param {number} dt - The delta time in seconds since the last frame.
*/
update(dt) {
}
}
// To include the File System module, use the require() method
const fs = require('fs');
// Using the File System module to read files
fs.readFile();
// Exporting the greet function so it can be used in other modules, use module.exports
module.exports = function greet(name) {
return 'Hello, ${name}!';
};
// To include the File System module, you no longer use require() method
// Use import instead.
import fs from 'fs';
// Using the File System module to read files
fs.readFile();
// Exporting the greet function so it can be used in other modules, you no longer
// use `module.exports`. Use `export` instead.
export const greet = (name) => {
return 'Hello, ${name}!';
};
import { Script } from 'playcanvas';
export class GameManager extends Script {
/**
* Called when the script is about to run for the first time.
*/
initialize() {
}
/**
* Called for enabled (running state) scripts on each tick.
*
* @param {number} dt - The delta time in seconds since the last frame.
*/
update(dt) {
}
}
import { Script } from 'playcanvas';
export class DoorRotator extends Script {
/**
* @attribute
* @type {number}
* @title First Number
*/
firstNumber = 10;
initialize() {
// Add the DoorRotator script to this.app
this.app.doorRotator = this;
}
rotateDoor() {
console.log('Rotate Door!');
}
}
var TriggerArea = pc.createScript('triggerArea');
TriggerArea.prototype.initialize = function() {
// Setup listening for the triggerenter event
this.entity.collision.on('triggerenter', this.onTriggerEnter, this);
};
// Handle the onTriggerEnter event
TriggerArea.prototype.onTriggerEnter = function(entity) {
// Calling function in DoorRotator.mjs
this.app.doorRotator.rotateDoor();
// Accessing property in DoorRotator.mjs
console.log("FirstNumber: " + this.app.doorRotator.firstNumber);
}
import { Script } from 'playcanvas';
export class Debug extends Script {
/**
* Called when the script is about to run for the first time.
*/
initialize() {
debugger;
console.log("Debug initialize!");
this.testFunction();
}
testFunction() {
debugger;
console.log('Test Function!');
}
}
import { Script } from 'playcanvas';
export class GameManager extends Script {
/**
* @attribute
* @type {number}
* @title First Number
*/
firstNumber
/**
* @attribute
* @type {number}
* @title Second Number
*/
secondNumber = 5;
/**
* @attribute
* @type {string}
* @title First String
*/
firstString
/**
* @attribute
* @type {string}
* @title Second String
*/
secondString = 'Default Text';
/**
* @attribute
* @type {boolean}
* @title First Boolean
*/
firstBoolean
/**
* @attribute
* @type {boolean}
* @title Second Boolean
*/
secondBoolean = false;
/**
* @attribute
* @type { pc.Entity }
* @title Entity
*/
entity
/**
* @attribute
* @type {number[]}
* @title Number Array
*/
numberArray
/**
* @attribute
* @type {string[]}
* @title String Array
*/
stringArray
/**
* @attribute
* @type {boolean[]}
* @title Boolean Array
*/
booleanArray
/**
* @attribute
* @type { pc.Entity[] }
* @title Entities
*/
entityArray
/**
* @attribute
* @type { CustomObject[] }
* @title Custom Objects Array
*/
customObjectArray
/**
* Called when the script is about to run for the first time.
*/
initialize() {
this.changeFirstNumber();
this.printValue("FirstNumber: " + this.firstNumber);
this.printValue("SecondNumber: " + this.secondNumber);
this.modifyFirstString();
this.printValue("FirstString: " + this.firstString);
this.printValue("SecondString: " + this.secondString);
this.modifyFirstBoolean();
this.printValue("FirstBoolean: " + this.firstBoolean);
this.printValue("SecondBoolean: " + this.secondBoolean);
this.printValue("Entity Name: " + this.entity.name);
this.printValue("Number Array: ");
this.printArray(this.numberArray);
this.printValue("String Array: ");
this.printArray(this.stringArray);
this.printValue("Boolean Array: ");
this.printArray(this.booleanArray);
this.printValue("Entity Array: ");
this.printEntityArray(this.entityArray);
this.printValue("CustomObjectArray: ");
this.printCustomObjectArray(this.customObjectArray);
}
/**
* Called for enabled (running state) scripts on each tick.
*
* @param {number} dt - The delta time in seconds since the last frame.
*/
update(dt) {
}
changeFirstNumber() {
this.firstNumber = 3;
}
modifyFirstString() {
this.firstString = "modified string";
}
modifyFirstBoolean() {
this.firstBoolean = true;
}
printValue(value) {
console.log(value);
}
printArray(array) {
for (var x = 0; x < array.length; x++) {
console.log(array[x]);
}
}
printEntityArray(array) {
for (var x = 0; x < array.length; x++) {
console.log(array[x].name);
}
}
printCustomObjectArray(array) {
for (var x = 0; x < array.length; x++) {
console.log(array[x].valueOf());
}
}
}
/** @interface */
class CustomObject {
/**
* @attribute
* @type { number }
* @title Number
*/
number
/**
* @attribute
* @type { pc.Entity[] }
* @title Entities Array
*/
entities
}
```
Quests
This document provides a guide that can be used to setup a Quest-based system in a VIVERSE project.
Quest System
Understanding the Quest System
Currently, the Quest system is unavailable for testing in Preview mode and can only be seen after clicking the Create World button in Preview mode.
In the sample app below, the trigger area is outlined in blue. Once the avatar enters the trigger area, the Quest system starts.
The first task requires the user to click the red box. Once the user clicks the red box, the first task is completed and the Quest system updates.
The second task requires the user to click multiple green boxes. Each green box that is clicked adds progress toward completing the task. Once all green boxes have been clicked, the task is completed and the Quest is finished.
If the user clicks a blue box during the quest, the Quest system resets. The user will need to re-enter the trigger area to restart the quest.
If the user clicks on a blue box before both tasks are completed, the Quest system resets and needs to be triggered again.
Create the quest
A. Give the quest a name in the Quest name field. The text: Find the boxes! was added.
B. Give the quest a description in the Quest description field. The text: Click on the boxes that are a specific color. was added.
C. Create the first task and give the task a description in the Task description field. The text: Click on the red box. was added.
D. Set the Task type to check.
E. Create the second task and give the task a description in the Task description field. The text: Click on the green boxes. was added.
F. Set the Task type to progressBar.
G. Add the value 4 to the Progress Steps field.
3
Create the trigger area that will start the quest
A. Create a new 3D Box entity.
B. Add a Collision component.
C. Adding a material is optional. A transparent material has been added so that the trigger area is visible in play mode.
D. Click the Edit Viverse Extension button.
4
Starting the quest
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select EntitySubscribeTriggerEnter.
C. Add local-player to the tags to filter field.
D. Add an Action and select Quest.
E. In the selected quest field, choose Find the boxes!
F. In the quest response field, choose startQuest.
5
Create an object that can be clicked to complete the first task
A. Create a 3D object.
B. Add a Collision component.
C. Add a material. Red has been added because this will be the box that will be clicked on to complete the first task.
D. Click the Edit Viverse Extension button.
6
Completing the first task
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select NotificationCenterSubscribeEntityPicking.
C. Add an Action and select Quest.
D. In the selected quest field, choose Find the boxes!
E. In the quest response field, choose completeTask.
F. In the selected task field, choose Click on the red box.
7
Create multiple objects that can be clicked to complete the second task
A. Create multiple 3D objects.
B. Add a Collision component to each object.
C. Add a material. Green has been added because these will be the boxes that will be clicked on to complete the second task.
D. Click the Edit Viverse Extension button.
8
Completing the second task
The following steps are completed for all green boxes.
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select NotificationCenterSubscribeEntityPicking.
C. Add an Action and select Quest.
D. In the selected quest field, choose Find the boxes!
E. In the quest response field, choose addTaskProgress.
F. In the selected task field, choose Click on the green boxes.
9
Create multiple objects that can be clicked to reset the quest
A. Create multiple 3D objects.
B. Add a Collision component to each object.
C. Add a material. Blue has been added because these will be the boxes that will be clicked on to reset the quest.
D. Click the Edit Viverse Extension button.
10
Resetting the quest
The following steps are completed for all blue boxes.
A. In the VIVERSE extension, select the TriggerAndAction plugin for the Select plugins dropdown.
B. Add a Trigger and select NotificationCenterSubscribeEntityPicking.
C. Add an Action and select Quest.
D. In the selected quest field, choose Find the boxes!
E. In the quest response field, choose resetQuest.
The avatar enters the trigger area and the Quest system dialog appears.
With the Quest system started, the user clicks on the red box and the first task is completed.
When the user clicks each green box, progress is added to the second task.
Once the user clicks on the final green box, the second task is complete and the Quest system dialog disappears.
Unity WebGL
Code examples, compatibility guides, and technical documentation for Unity WebGL builds targeting VIVERSE. Includes render pipelines, WebGL templates, loading screens, and deployment examples.
Publishing Tutorial
Anyone can publish their WebGL-compatible Unity project to VIVERSE in a few simple steps. In this guide, we'll walk through the process of creating an new Unity project, making sure it is compatible with WebGL, and publishing to VIVERSE using the VIVERSE CLI.
For this guide, we are using the VIVERSE CLI, but it is also possible to compress and .
While VIVERSE is a great place for multiplayer games with networked avatars — and we have a number of services that can help you implement these features — it is not required to implement networked avatars to publish to VIVERSE.
Prerequisites
Unity Hub and Unity installed on your device.
and installed on your device. Please use at least Node v22 - Only required if using the CLI, not VIVERSE Studio
In this tutorial, we will be using Unity v6.1, however any WebGL-compatible version of Unity should be supported.
Configure Your Unity Project
1
Create a Unity Project
2
Build and Publish to VIVERSE
1
Build Your Project
Navigate to Publish and select "WebGL Publish". In the pop-up, click "Build and Publish", selecting the desired folder for your build. When doing this for the first time, Unity will automatically publish to their web-servers for testing. For future builds, you can disable this behavior to just the builds without publishing.
2
Unity & VIVERSE Compatibility Overview
VIVERSE supports Unity WebGL builds with specific requirements and recommendations for optimal performance and compatibility. This section covers essential settings and considerations for targeting VIVERSE.
Supported Unity Versions
VIVERSE supports the following Unity versions:
Unity 2021 LTS (2021.3.x) - Recommended for stability
Unity 2022 LTS (2022.3.x) - Recommended for newer features
Unity 2023.x - Supported, but verify compatibility with VIVERSE SDK
Note: Always use LTS (Long Term Support) versions for production projects targeting VIVERSE to ensure long-term compatibility and support.
Required Unity Modules
Install the following modules via Unity Hub:
WebGL Build Support - Essential for building WebGL projects
WebGL Development Build Support - Recommended for debugging
IL2CPP - Required for WebGL builds (automatically included with WebGL module)
Verify installation: Edit → Preferences → External Tools or check installed modules in Unity Hub.
Supported Render Pipelines
Important: Unity WebGL does NOT support HDRP (High Definition Render Pipeline).
Built-in Render Pipeline:
Fully supported for WebGL/VIVERSE
Best compatibility across all browsers
Recommended for projects targeting maximum compatibility
Universal Render Pipeline (URP):
Fully supported for WebGL/VIVERSE
Recommended for new projects targeting WebGL
Better performance and modern features optimized for web platforms
High Definition Render Pipeline (HDRP):
NOT supported on WebGL/VIVERSE
HDRP is designed for high-end GPUs and requires features unavailable in WebGL:
Real-time ray tracing
Choosing a Render Pipeline
For New Projects Targeting WebGL/VIVERSE:
URP is strongly recommended for modern features and optimal WebGL performance
Install via Window → Package Manager → Unity Registry → Universal RP
For Existing Projects:
Built-in: Works without changes, but URP offers better WebGL performance
Custom templates allow full control over presentation
Fullscreen Canvas Benefits
A fullscreen canvas template provides:
Immersive Experience: No browser UI distractions
Maximum Screen Usage: Canvas fills entire viewport
Better Performance: No layout calculations for browser elements
Key Features:
Canvas set to 100% width and height
Body and container with overflow: hidden
No scrollbars or browser chrome
Custom Loading Screen Overview
Custom loading screens enhance user experience by:
Branding: Display your logo/branding during load
Progress Feedback: Show loading progress to users
Professional Appearance: Custom design matching your project
Components:
Loading bar container (centered on screen)
Logo/branding element
Progress bar (animates from 0% to 100%)
Create the WebGL Template Folder Structure
1
Navigate to Assets Folder
In Unity, open your project and navigate to the Assets folder in the Project window.
2
Create the Fullscreen HTML Template
1
Create index.html File
Right-click on the Fullscreen folder → Show in Explorer (Windows) or Reveal in Finder (Mac)
Customize the Loading Screen
1
Understanding the Loading Screen Elements
The template includes several customizable elements:
Configure Build Settings
1
Open Build Settings
In Unity, go to File → Build Settings...
Build the WebGL Project
1
Prepare for Build
Ensure your scene is saved (Ctrl+S / Cmd+S
Test the Fullscreen Build Locally
1
Set Up Local Server
WebGL builds require a web server to run (cannot open index.html directly due to CORS restrictions).
Option 1: Python HTTP Server (if Python installed):
Deploy to VIVERSE
1
Prepare Build for Upload
Navigate to your build output folder
Advanced Customization
1
Customize Background Color
Modify the canvas background in the CSS:
2
Troubleshooting
Template Not Appearing in Build Settings:
Ensure the folder is named exactly WebGLTemplates (case-sensitive)
Ensure index.html is directly in the template folder (e.g., Assets/WebGLTemplates/FullScreen/index.html)
Loading Screen Not Showing:
Check browser console for JavaScript errors (F12)
Verify image paths in CSS are correct
Ensure loadingBar.style.display = "block" is called before Unity loads
Fullscreen Not Working:
Desktop: verify canvas has width/height100% (set in JS in this template) and html/body/#unity-container fill the viewport
Mobile:
Build Too Large:
Enable compression in Publishing Settings
Increase Managed Stripping Level
Remove unused assets and scripts
VIVERSE Upload Issues:
Ensure ZIP contains index.html at root level
Verify all required files are included (Build folder, etc.)
Check file size limits in VIVERSE Studio
Wonderland Engine
Integration example of VIVERSE Avatar SDK with Wonderland Cloud networking for multiplayer VR experiences.
Introduction
In November 2025, VIVERSE and the Wonderland Engine team collaborated to develop a plugin allowing developers to publish to VIVERSE from directly within the Wonderland Engine editor. In addition, we developed examples of using the VIVERSE Avatar and Account SDKs with Wonderland's multiplayer SDK.
This repository is a template project that demonstrates how to integrate the VIVERSE Avatar SDK with Wonderland Cloud networking. It provides a compact, production-minded workflow to:
Spawn and persist user data (name, avatar) via the VIVERSE Avatar SDK
Relay avatar + presence state to Wonderland Cloud for performant, medium-scale multiplayer sessions
Use spatial audio for immersive multiplayer experiences
Designed for quick iteration and easy publishing through the VIVERSE / Wonderland tooling.
Live Demo:
Features
The example project includes the following key features:
VIVERSE Avatar SDK Integration: Login, avatar spawn, and user metadata management
Wonderland Cloud Networking: Client + server template for multiplayer functionality
VIVERSE CLI Plugin: Simple integration for publishing and previewing projects
Project Structure
The repository contains the following directories and files:
js/ - JavaScript/TypeScript source files
models/ - 3D model assets
plugins/viverse-publish-plugin/ - VIVERSE CLI plugin for publishing
Quick Setup (Editor)
1
Open the plugin
Open the viversePublishPlugin inside the Wonderland Editor.
2
Scene Configuration
1
Navigate to Avatar Component
In the Wonderland Editor hierarchy, navigate to: Avatar -> VrmDynamic and select the VrmDynamic object.
2
Networking Setup (Wonderland Cloud)
1
Access Wonderland Cloud
Open your web browser and navigate to: https://cloud.wonderland.dev/create-server. Log in with your Wonderland Cloud credentials if required.
2
Publish & Preview
1
Open VIVERSE CLI Plugin
In the Wonderland Editor, open the VIVERSE CLI plugin.
2
Component Configuration Details
VIVERSE Provider Component
The Viverse Provider component (or viverse-provider-component) handles authentication and avatar management:
App ID: Your VIVERSE application identifier (required)
Avatar Spawning: Automatically spawns user avatars based on VIVERSE account
User Metadata: Retrieves and stores user name and avatar data
Simple Example Client Component
The simple-example-client component manages networking:
Server Path: WebSocket URL to your Wonderland Cloud server (required)
js/ - Contains component scripts and application logic
models/ - 3D models and avatar assets
server/ - Wonderland Cloud server implementation
Build Process
Development: Edit scenes and components in Wonderland Editor
Configuration: Set App ID and server path in components
Publishing: Use VIVERSE CLI plugin to build and upload
Multiplayer Architecture
The example uses a client-server architecture:
Client: Wonderland Engine application running in browser
Server: Wonderland Cloud server handling networking
Communication: WebSocket connection for real-time updates
Example Components: Pre-configured components showing where to place appid and server path
Spatial Audio: Avatar position replication with spatial audio for medium-scale sessions
server/ - Wonderland Cloud server package
shaders/ - Custom shader files
static/ - Static assets
app.js - Main application entry point
package.json - Node.js dependencies and scripts
tsconfig.json - TypeScript configuration
viversecli.wlp - VIVERSE CLI configuration file
Log In with VIVERSE Credentials
3
Create Application
Click Create Application — this redirects to VIVERSE Studio.
4
Copy the App ID
In VIVERSE Studio create an app and copy the App ID.
5
Paste the App ID
Paste the App ID into the appid field of the plugin.
Expand VIVERSE Provider Component
In the Inspector, expand the Viverse Provider component (or viverse-provider-component).
3
Paste the App ID
Locate the appid field in the component properties and paste the App ID that you copied from VIVERSE Studio.
4
Verify Configuration
Double-check that the App ID is correctly set in both the VIVERSE Publish Plugin and the VrmDynamic -> Viverse Provider component, then save the scene to preserve your changes.
Locate Server Package
Locate the server package in your project: server/wonderland-cloud-example-simple-1.0.0.tgz and verify the file exists and is not corrupted.
3
Upload Server Package
In the Wonderland Cloud interface, click Upload or Create Server, select the file: server/wonderland-cloud-example-simple-1.0.0.tgz, and wait for the upload to complete. Wonderland Cloud will process and deploy your server.
4
Copy Server Path
After the server is created, Wonderland Cloud will display server information. Copy the server path that is provided (typically looks like: wss://your-server-id.wonderland.dev).
5
Configure Client Component
Return to the Wonderland Editor, select the Player object in the hierarchy, locate the simple-example-client component in the Inspector, find the serverPath field, paste the server path you copied from Wonderland Cloud, and save the scene.
Publish Project
Click Publish to build and upload your project. Wait for the publishing process to complete. The plugin will show the status of the upload.
3
Preview Your Project
After publishing, click Preview URL in the plugin. This will open a preview build in your browser. Test all functionality including avatar spawning, multiplayer connectivity, spatial audio, and user interactions.
4
Submit for Review
In the VIVERSE CLI plugin, click Submit for Review. This will open the VIVERSE Creator page for your application. Complete any required information in the VIVERSE Creator interface and review your application settings before submission.
5
Guest Preview Testing
From the VIVERSE Creator page, use the Guest Preview link. Share this link with others for testing. Test multiplayer functionality with multiple devices/accounts, verify that avatars appear correctly for all users, and test spatial audio and networking in production-like conditions.
6
Final Submission
Once testing is complete and you're satisfied with the build, submit the app for review to list it publicly. Wait for VIVERSE approval. After approval, your application will be available in VIVERSE.
Presence State: Manages user presence in the multiplayer session
Check that the App ID matches the one from VIVERSE Studio
Ensure you're logged in with a valid VIVERSE account
Check browser console (F12) for authentication errors
Verify CORS settings in VIVERSE Studio if using custom domains
)
Check that the server is running and accessible
Review browser console (F12) for WebSocket connection errors
Navigate to Window > Package Manager > Unity Registry and search for "WebGL Publisher". Add the module to your project.
3
(Optional) Enable Decompression Fallback
Compression is supported on VIVERSE, however you can enable fallback if you are encountering errors or would like to have it included. Navigate to Edit > Project Settings > Player > Web Settings > Publishing Settings and check "Decompression Fallback".
Install the VIVERSE CLI
In a terminal session, run npm install -g @viverse/cli to install the CLI globally. Make sure you are using at least node v22.
3
Login to VIVERSE
In the terminal session, run viverse-cli auth login and enter your VIVERSE account email and password.
4
Create VIVERSE App
In the terminal session, run viverse-cli app create . Once complete, copy the app ID to be used when publishing.
5
Publish to VIVERSE
In the terminal session, run viverse-cli app publish {path/to/unity/webgl/build} --app-id {your app id from step 4} referencing folder containing the index.html of your Unity build.
6
Test & Configure World Settings
Navigate to the preview url created for the world. You can also access the world and its settings in studio.viverse.com/content.
7
Submit for Curation and Discovery
By default, worlds uploaded will only be accessible via preview urls. For placement and curation on our webpages, meaning your experience will be easier to share, please submit for review.
No additional packages required
Requires URP package (installed via Package Manager)
Optimized for low-end and web platforms
Advanced volumetrics
Compute shaders with full GPU access
Large render targets
Advanced shader models
WebGL runs in a browser sandbox with restricted GPU access and memory
You must convert HDRP projects to URP for WebGL builds
Review and update materials (HDRP materials need URP equivalents)
Test shaders and lighting (some HDRP features may not have direct URP equivalents)
Optimize for WebGL performance (WebGL is sensitive to draw calls, textures, and shader complexity)
Built-in has maximum compatibility but lower performance
HDRP cannot be used for WebGL builds
Render Scale: 1.0 (or lower for performance)
HDR: Disabled (WebGL doesn't support HDR)
MSAA: 2x or 4x (balance quality vs performance)
Shadow Distance: Adjust based on your scene needs
HDRP shaders are NOT compatible - must convert to URP shaders for WebGL
WebGL 2.0 supports most modern shader features, but not HDRP-specific features
WebGL is sensitive to shader complexity - optimize for performance
Mobile responsiveness
Fullscreen functionality
Professional Appearance: Clean, game-like presentation
User Engagement: Keep users informed during asset loading
Optional loading text or animations
Styled with CSS for custom appearance
Create WebGLTemplates Directory
Right-click in the Assets folder → Create → Folder
Name the folder WebGLTemplates (exact name required by Unity)
This folder will contain all custom WebGL templates
3
Create Fullscreen Template Folder
Right-click on WebGLTemplates → Create → Folder
Name it Fullscreen (this will be the template name visible in Build Settings)
Unity will automatically detect this folder as a WebGL template
Create a new text file named index.html (not index.html.txt)
This file will serve as the main HTML template for your WebGL build
2
Add Fullscreen HTML Structure
Open index.html and add the following fullscreen template code:
Key Features:
html, body, and #unity-container fill the viewport with overflow: hidden for true fullscreen
Desktop: canvas style width/height set to 100% in JavaScript
Mobile (VIVERSE-friendly): full-viewport fixed container, canvas 100% via CSS, viewport meta tag, and config.devicePixelRatio = 1 to reduce high-DPI backing-store cost
Loading bar centered on screen during asset loading
Footer hidden by default (can be shown if needed)
3
Refresh Unity Project
Return to Unity Editor
The index.html file should appear in the Project window under Assets/WebGLTemplates/Fullscreen/
If not visible, right-click in Project window → Refresh, or press Ctrl+R (Windows) / Cmd+R (Mac)
#unity-loading-bar: Container for loading screen elements
#unity-logo: Logo image displayed during loading
#unity-progress-bar-empty: Background of the progress bar
#unity-progress-bar-full: Animated progress bar that fills from 0% to 100%
All elements are centered on screen using CSS transforms.
2
Replace Default Loading Images
In the Fullscreen folder, replace the default Unity loading images with your custom assets:
unity-logo-dark.png (154×130px recommended) - Your logo/branding
progress-bar-empty-dark.png (141×18px) - Progress bar background
progress-bar-full-dark.png (141×18px) - Progress bar fill image
Alternatively, modify the CSS in index.html to use different image paths or create custom loading UI with HTML/CSS instead of images.
3
Custom Loading Screen with HTML/CSS
To create a fully custom loading screen without images, modify the #unity-loading-bar section:
Update the JavaScript progress callback to also update text:
4
Add Custom Loading Animations
Enhance the loading screen with CSS animations. Add to the <style> section:
Select WebGL from the Platform list
Click Switch Platform if not already on WebGL (this may take a few minutes)
2
Select the Fullscreen Template
Click Player Settings... (or go to Edit → Project Settings → Player)
In the Player Settings window, expand the Publishing Settings section
Under WebGL Template, select Fullscreen from the dropdown
The template you created should now be available in this list
3
Configure Additional WebGL Settings
For optimal VIVERSE deployment, configure these settings:
Resolution and Presentation:
Default Canvas Width: 1920 (or your target resolution)
Default Canvas Height: 1080 (or your target resolution)
Run In Background: Enabled (recommended for VIVERSE)
Publishing Settings:
Compression Format: Gzip or Brotli (for smaller file sizes)
Data caching: Enabled (improves load times for returning users)
Name Files As Hashes: Enabled (better caching)
Other Settings:
Strip Engine Code: Enabled (reduces build size)
Managed Stripping Level: Medium or High (further reduces size)
)
In Build Settings, verify the scenes you want to include are checked
Click Add Open Scenes if your current scene isn't listed
2
Build the Project
Click Build in the Build Settings window
Choose or create an output folder (e.g., Builds/WebGL)
Click Select Folder
Unity will compile and build your project (this may take several minutes)
Once complete, navigate to the build output folder
TemplateData/ folder (if using default template) - Contains template assets
StreamingAssets/ folder (if you have streaming assets) - Contains additional assets
The index.html should be your custom fullscreen template with the loading screen.
Then open http://localhost:8000 in your browser.
Option 2: Node.js HTTP Server:
Option 3: Unity's Built-in Server: After building, Unity may offer to open a local server automatically.
2
Test Fullscreen Functionality
Open the build in your browser
Verify the loading screen appears and progress bar animates
Once loaded, the canvas should fill the entire browser window
Test the fullscreen button (if visible) or press F11 for browser fullscreen
Verify no browser UI elements are visible (address bar, scrollbars, etc.)
Test on different screen resolutions and aspect ratios
3
Test Mobile Responsiveness
Open browser developer tools (F12)
Enable device emulation mode
Test on various mobile device presets (iPhone, Android, tablets)
Verify the viewport meta tag works correctly
Test touch interactions if your project uses them
Select all files and folders (index.html, Build/, StreamingAssets/ if present)
Create a ZIP archive of these files
Name it appropriately (e.g., MyProject_WebGL_Build.zip)
Verify the ZIP contains the root index.html file (not nested in a subfolder)
2
Upload to VIVERSE Studio
Log in to VIVERSE Studio (https://worlds.viverse.com/)
Navigate to Manage Content or your project dashboard
Click Upload or New Content
Select your ZIP file
Wait for upload and processing to complete
3
Configure VIVERSE Settings
In VIVERSE Studio, configure your content settings:
Set appropriate title and description
Configure access permissions (public/private)
Set thumbnail/preview image
Configure any required VIVERSE SDK settings
Ensure WebGL compatibility is enabled
4
Preview and Publish
Use VIVERSE Studio's preview feature to test your content
Verify fullscreen behavior works correctly in VIVERSE environment (test on mobile as well as desktop; layout and GPU memory behave differently on phones)
Test loading screen appearance and timing
Once satisfied, submit for approval/publishing
After approval, your content will be available in VIVERSE
Add Splash Screen or Branding
Add custom HTML before the canvas loads:
Then hide it in JavaScript after Unity loads:
3
Implement Custom Error Handling
Enhance error messages for better user experience:
4
Optimize Loading Performance
Enable Compression: In Player Settings → Publishing Settings, use Gzip or Brotli compression
Reduce Build Size: Enable code stripping and remove unused assets
Use Addressables: For large projects, consider Unity Addressables for on-demand loading
cd path/to/your/build/folder
python -m http.server 8000
#unity-canvas {
background: #231F20; /* Change to your desired color */
/* Or use a gradient: */
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
npm install -g http-server
cd path/to/your/build/folder
http-server -p 8000