> For the complete documentation index, see [llms.txt](https://docs.viverse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.viverse.com/polygon-streaming/polygon-streaming-javascript-sdk/playcanvas.md).

# PlayCanvas

This document provides a guide for integrating Polygon Streaming web player for PlayCanvas using the NPM package.

***

This is a guide to use Polygon Streaming web player for PlayCanvas using the NPM package.

### **Getting Started - Sample Project** <a href="#getting-started-sample-project" id="getting-started-sample-project"></a>

You can download a sample project to get started [here](https://stream.viverse.com/assets/streamablemodel/2.10.0/playcanvas/PolygonStreaming-PlayCanvas-Example.zip).

To run the sample project you first need to make sure you have [Node.js](https://nodejs.org/) installed. Then run the following in a terminal:

```bash
npm install
npm run dev
```

This will open a browser window and display the 3D model.

### Explanation of the Code <a href="#toc_1" id="toc_1"></a>

You first need to import registerScripts function from the package:

```javascript
import { registerScripts } from '@polygon-streaming/web-player-playcanvas';
```

And run it:

```javascript
registerScripts();
```

Next, you need to create an entity with a camera component:

```javascript
const camera = new pc.Entity('camera');
camera.addComponent('camera');
```

Your page must contain an entity that has a stream controller script component. The camera entity created above is passed in as an attribute to the stream controller:

```javascript
const streamController = new pc.Entity('Stream Controller');
streamController.addComponent('script');
streamController.script.create('streamController', {
  attributes: {
    camera,
    cameraType: 'nonPlayer',
    triangleBudget: 5000000,
    mobileTriangleBudget: 3000000
  }
});
```

Next you need to create an entity that has a streaming model script component - one for each of your streaming models where you pass in the URL of your XRG file.

```javascript
const streamableModelEntity = new pc.Entity('Streamable Model');
streamableModelEntity.addComponent('script');
streamableModelEntity.script.create('streamableModel', {
  attributes: {
    path: 'https://stream.viverse.com/demos/jet-engine-11m/',
    qualityPriority: 1
  }
});
```

The streaming model entity needs to be a child of the stream controller entity:

```javascript
streamController.addChild(streamableModelEntity);
```

And then you need to add the stream controller entity to the scene:

```javascript
app.root.addChild(streamController);
```

### To Play an Embedded or VRM Animation

```javascript
streamableModelEntity.fire('streamable-model:play-animation', 'animationName', 0.2);
```

The first argument can be the name of the animation or if you don't know the name an index e.g. 0 for the first animation. The second argument is the transition duration and is optional, it will default to one second. This method should be called after the initial model data has loaded. VRM animations need to be provided in the streaming model attributes. Below is an example of passing in two VRM animations. See the `vrmAnimations` attribute in the Streamable Model Attributes section for more information.

```javascript
streamableModelEntity.script.create('streamableModel', {
  attributes: {
    path: '/model.xrg',
    vrmAnimations: [
      {
        name: 'idle',
        asset: new pc.Asset('', 'container', { url: '/Idle.vrma' }),
        default: true
      },
      {
        name: 'yawn',
        asset: new pc.Asset('', 'container', { url: '/Yawn.vrma' }),
        loop: false
      }
    ]
  }
});
```

### To Animate a VRM Expression

```javascript
streamableModelEntity.fire('vrm-expression:start-emotion', 'expressionName', { 
  times: [0, 0.1, 0.2],  
  values: [0, 1, 0]
});
```

The second argument is the expression name and has to exist in the VRM file that the XRG was generated from. The third argument is the animation keyframes.

### Files Required at the Web Root

Polygon Streaming expects the service worker that is used to cache model data to be available at the web root e.g. `/service-worker.js`. This is handled by Vite in the config file - vite.config.js.

### Using Your Own Model <a href="#toc_2" id="toc_2"></a>

* Upload your 3D model to the [console](https://stream.viverse.com/console).
* To get the model URL go to the models section of the [console](https://stream.viverse.com/console/models) and click on the three dots next to your model and select "Copy asset ID".
* Paste this URL into the path attribute of the streaming model script component.

### Stream Controller Attributes <a href="#toc_3" id="toc_3"></a>

* **camera**: The camera entity in your scene.
* **cameraType**: 'nonPlayer' | 'player', default: 'nonPlayer'
  * **nonPlayer**: A camera that is not attached to a player e.g. a camera that orbits an object.
  * **player**: A camera that is attached to a player.
* **occlusionCulling**: boolean, default: false. Whether occlusion culling is enabled. Requires that device supports WebGL 2.
* **occlusionGeometry**: 'boundingBox' | 'mesh', default: 'boundingBox'
  * **boundingBox**: Use the bounding box of the mesh to check if it's occluded. It's slower but more accurate in determining whether a mesh is occluded.
  * **mesh**: Use the mesh to check if it's occlused. It's quicker but less accurate in determining whether a mesh is occluded.
* **occlusionQueryFrequency**: number, default: 8. Value is in times per second. A value of 0 means will it run on every frame.
* **triangleBudget**: number, default: 5000000. The maximum amount of triangles that you want to be in the scene at any single point.
* **mobileTriangleBudget**: number, default: 3000000. The triangle budget used on a mobile device. If it is set to 0 it will use the non-mobile triangle budget.
* **minimumDistance**: number, default: 0.01. The smallest possible distance to the camera.
* **distanceFactor**: number, default: 1.1. Preference for nearby objects over objects further away. Values above one mean a preference for nearby objects. Values below one mean a preference for objects further away. One is neutral.
* **maximumQuality**: number, default: 15000. Stops improving geometry that exceeds the maximum quality. This can be used to stop far away objects from showing more detail which can be wasteful. Setting it to 0 means there is no maximum quality.
* **closeUpDistance**: number, default: 3. The distance where it starts using close-up distance factor. Set it to 0 to not use close-up distance factor.
* **closeUpDistanceFactor**: number, default: 5. The distance factor used when close-up to an object. Should be higher than the standard distance factor.
* **iOSMemoryLimit**: number, default 0. The maximum amount of memory in MB that meshes and textures can consume on iOS devices to avoid the page crashing. Use 0 to let Polygon Streaming determine the limit or -1 for no limit.
* **showLoadingModel**: boolean, default: true. Whether to show the animated loading model when loading streaming models.
* **loadingModelUrl**: string, default: null. URL of a custom animated loading GLB file that overrides the default one.

### Streamable Model Attributes <a href="#toc_4" id="toc_4"></a>

* **path**: string, default: '/model.xrg'. Path or URL of the model.
* **qualityPriority**: number, default: 1. How much to prioritize the quality of this model relative to the quality of other models in the scene. This parameter does nothing if this is the only model in the scene.
* **initialTrianglePercent**: number, default: 0.1. Percentage of triangle budget to initialize the model with.
* **castShadows**: boolean, default: true. Whether the model should cast shadows.
* **receiveShadows**: boolean, default: true. Whether the model should receive shadows.
* **forceDoubleSided**: boolean, default: false. Render the model double sided regardless of the setting in the model file.
* **useAlpha**: boolean, default: true. Whether to render semi-transparency in materials. You might turn this off to increase performance but all your materials will render opaque.
* **useEmbeddedCollider**: boolean, default: true. Wether to use the embedded collider.
* **playAnimationAutomatically**: boolean, default: true. Whether to play the embedded animation automatically.
* **animation**: string or number, default: null. The name or index of the embedded animation to play. An index value of 0 is the first animation. If not value is supplied it will play the first animation.
* **animationStateGraph**: asset, default: null. Supply a state graph if you want more advanced control over the animations. Use toAnimStateGraphAsset function to convert a JavaScript object of the state graph to an asset.
* **animationStateMappings**: array, default: empty array. If you supply an animation state graph you will also need to supply an array of objects that map states to the embedded animations.
  * **state**: string. The state name used in the state graph.
  * **animation**: string or number. The name or index of the embedded animation.&#x20;
  * **layer**: string, default: null. The layer name used in the state graph. If it's omitted it will default to the base layer.
* **vrmAnimations**: array, default: empty array. This is where you add the VMRA animations to animate an XRG generated from a VRM file.
  * **name**: string, default: null. The name of the animation. This is used in the playAnimation method.
  * **asset**: pc.Asset, default: null. A pc.Asset with asset type container that specifies the URL of the VRMA file.
  * **loop**: boolean, default: true. You would set this to false if you want the animation to play once i.e. for an action. Non-looping animations will go back to the default animation when they finish.
  * **default**: boolean, default: false. The default animation is the animation that plays after a non-looping animation. This is usually the idle animation.
* **environmentAsset**: asset, default: null. Use either a cubemap asset with a prefiltered image or the prefiltered image as a texture asset.
* **hashCode**: string, default: ''. Hash code to validate streaming model.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.viverse.com/polygon-streaming/polygon-streaming-javascript-sdk/playcanvas.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
