---
# System prepended metadata

title: Optimizing for Accessibility and Scale for Hyperfy
tags: [Hyperfy, threejs, metaverse]

---

# Creating Optimized Models and Worlds

The Hyperfy engine heavily relies on client-side processing to deliver an immersive experience.

The user experience in world can be significantly impacted by the optimizations of the models and other components set up in the world.

To provide the most users with the best experiences, we recommend the following focus areas for optimization:
* [Reducing the size of texture ](https://hackmd.io/YtEOOp2FQhWq3qfHOrLiiw#Textures-and-Meshes)
* [Reducing the number of draw calls](https://hackmd.io/YtEOOp2FQhWq3qfHOrLiiw#Draw-Calls)
* [Reducing the number of triangles](https://hackmd.io/YtEOOp2FQhWq3qfHOrLiiw#Triangles-and-Polygons)
* [Reducing collider complexity](https://hackmd.io/YtEOOp2FQhWq3qfHOrLiiw#Collision)


![image](https://hackmd.io/_uploads/rkG-e4Pwyg.png)


![image](https://hackmd.io/_uploads/rJbnamDDkg.png) Additional detail found in [Hyperfy discord](https://discord.com/channels/958209073277456457/994775534733115412/1329394170963558460) chat.


## Measuring Performance
Press the ~ button in world to pull up live world performance statistics:
* Frames per Second
* Draw Calls
* Triangles
* Geometris
* Textures

## Improving Performance

The following are focus areas to improve performance of models rendered in world.

### **Draw Calls**
> Draw calls are necessary, reduce them.

Draw calls are requests made to the graphics API to render objects on the screen. Inefficient configuration of a model will lead to excessive draw calls when a single consoldiated call could be used.

| Perfect | Great | Good | Uhh | Unoptimized
| -------- | -------- | -------- | -------- |-------- |
| < 100     | <101-300     | 301 - 600| 601 - 900 | 901+


### **Textures and Meshes**
> Textures are great, jpeg them.

| Perfect | Great | Good | Uhh | Unoptimized
| -------- | -------- | -------- | -------- |-------- |
| < 100     | <101-300     | 301 - 600| 601 - 900 | 901+


### **Triangles and Polygons**
> Triangles are great; decimate, retopo, or bake them.

| Perfect | Great | Good | Uhh | Unoptimized
| -------- | -------- | -------- | -------- |-------- |
| < 100k     | <101-200 | 201 - 300| 301 - 500k | 501k+

### **Collision**
> Physics are great; select colisions appropriately.


##### Collision Setting Optimization
Ask yourself "Do I really need a collision on this object?" if you can get away without one, do so by setting collision to *Nothing*. If you do require collision, consider the appropriate level of collision required to be calculated by the engine:

```flow
st=>start: Do I need a collision on this?
e=>end: End
op1=>operation: Nothing
op2=>operation: Static
op3=>operation: Kinematic
op4=>operation: Dynamic
condYN=>condition: Yes or No?
condStatic=>condition: Is object 
stationary?
condKinematic=>condition: Does it move via 
code or physics? 
condDynamic=>condition: Dynamic

st->condYN->op1(left)
condYN(yes, right)->condStatic
condYN(no)->op1
condStatic(no@stationary, bottom)->op2
condStatic(yes@moves)->condKinematic
condKinematic(no@code, bottom)->op3
condKinematic(yes@physics)->op4

```
* **Static** - For basic objects that will not move such as buildings, walls, or trees use static collision. This is the most common type and requires the least computation for object collision.
* **Kinematic** - For objects that you want to control through code (e.g. a moving platform), use kinematic. This will allow the collider to move (i.e. the collider's position is updated as it moves) but is computationally cheaper than dynamic.
* **Dynamic** - Use this when you want to create objects that react in a physically accurate way. Think: balls that get kicked/moved by players, cars that crash into stuff etc. It's very computationally expensive so use this option sparingly. 

##### Collision Mesh Optimization

Regardless of which collider setting is used, make sure you create simple collision meshes rather than the original model. Fewer vertices is definitely better here! Make really simple collision shapes if you can. 

Don't model every detail, it's rare that you'll need a super-detailed collision mesh. Less is more! For example, if you don't allow players to fly you don't need collisions above where they can walk/run/jump. It's just a waste of compute. So for a big tree just add a 3m tall cylinder/box (no endcaps!) to where the trunk is. This will stop people running through it but will be cheap.

### **Other Factors**
Other factors that impact performance include:
* Lighting and shading - bake where possible
* Skybox HDR - similar technique to texture optimization; ideally fit into 128x128 or up to 2k for best overall performance
* Animation and rigging
* Number of users and their avatars - plan the experience and anticipate the number of users intended; provide optimized avatars for higher volume of users

## **Hyperfy Engine Optimizations**
The Hyperfy engine provides the following further optimizations:

* Automatic GPU instancing where thousands of duplicates of the same object only result in 1 draw call.
* Linked duplicates (cmd+D in Blender) are also optimized down to a single shared draw call.
* Frustum culling is applied with a few exceptions so meshes that are outside of the camera frustum do not get drawn. Occlusion culling is not currently supported.
* Level-of-Details (LOD's) are respected and can be configured from 3d tools such as Blender.


## Optimizing Avatars
* VRM's should be less than 4mb and less than 20k tris

>[7:16 AM ashxn](https://discord.com/channels/958209073277456457/958209074045026327/1068867119451750480): 
> - select all, edit mode, merge by distance (removes ~80k tris)
> - remove all hidden vertices that shouldn't be there
> - decimate each mesh as much as possible without losing visuals (preferably down to 20k tris)
> - rebake to 2k atlas texture
> - t-pose
> - mixamo rig and download
> - re-export as vrm
> - voila! 
> (Mesh > Merge > By Distance)

Additional resources to build VRM avatars:
* [Simple VRM](https://vrm-addon-for-blender.info/en/create-simple-vrm-from-scratch/)
* [Humanoid VRM](https://vrm-addon-for-blender.info/en/create-humanoid-vrm-from-scratch/)
 

## Links to Optimization Tools
* [Collider Optimization for Blender by hiro](https://github.com/docherty/hiros-tools) 
* [gltf-optimizer](https://github.com/M3-org/gltf-optimizer/issues) 
* [Mesh Optimizer](https://github.com/zeux/meshoptimizer/releases)
* [VRM-Addon-for-Blender](https://github.com/saturday06/VRM-Addon-for-Blender)
* [UniVRM](https://vrm.dev/en/univrm/)
* [ Cats Blender Plugin](https://github.com/absolute-quantum/cats-blender-plugin) 
* [Mals-Blender-VRM0-Utility](https://github.com/Menithal/Mals-Blender-VRM0-Utility)

## Links to Other Resources
* [Optimizing your Mesh by MONAVERSE](https://docs.monaverse.com/create/creating-assets/optimizing-your-mesh)
* [Super optimizing GLB files using Texture Compression with ZenCompress](https://www.youtube.com/watch?v=gsqrHDmgTfA&ab_channel=ConorWoodard)
* Demo: https://www.khronos.org/gltf/gltf-asset-auditor/
* [Recommended Schema](https://github.com/KhronosGroup/gltf-asset-auditor/blob/main/tests/schemas/khronos-recommended.json)
* [Publishing guideline summary](https://github.com/KhronosGroup/3DC-Asset-Creation/blob/main/asset-creation-guidelines/RealtimeAssetCreationGuidelines.md#publishing-targets-summary): 
* [3DC Asset Creation More details](https://github.com/KhronosGroup/3DC-Asset-Creation/blob/main/asset-creation-guidelines/full-version/sec99_PublishingTargets/PublishingTargets.md)
* [Optimizing Webaverse Island in Blender](https://youtu.be/R-fdhUzjeIs)
* [SugarClub.eth Optimizing base mesh avatar](https://twitter.com/sugarclub_/status/1664001303230423041?s=46)
* [Creating and Prepping Assets](https://sparkar.facebook.com/ar-studio/learn/articles/creating-and-prepping-assets/toolkit-for-blender/) also see Hyperfy [Discord chats](https://discord.com/channels/958209073277456457/1031058655581323324/1131694339194638358): 


{%hackmd Syq4xkPwkg %}


## TODO **Some other relevant details to digest**
> Ash: : I don't know who needs to hear this but, whenever you use third party models or models not made in blender, run a "merge by distance" on each mesh to make sure its a proper manifold mesh.
> For some reason on the web this makes a huge difference to performance, especially on larger meshes.
> It's super inefficient on your GPU.
> 
> Alternatively, you can just apply Draco compression in https://gltf.report/ because that usually makes it manifold for you as part of compression.
> Actually, you should just always use Draco lol.
> That and KTX textures 😉
> 
> You'll thank me for it later 🫡 

>[9:40 PM jin](https://discord.com/channels/958209073277456457/999870741069692958/1156042590722990201):
> * naming conventions
    * collision
    * wind
    * LOD
> * authoring pipelines
    * MSFT_lod
    * blender -> web
> * where to bake occlusion culling
> * gltf
    * glb and atlas maps
    * how much to extend it
> * Wish list
    * gltf-transform backend auto-optimization
    * your ideas here
> 
> You can now upload your own models to Meshy3D and use the AI Texturing, Remesh and Animation tools.
I ran one of my fish things through the texturing. It can take existing meshes with UV layouts and print the textures. Then you can just repaint in Blender or just use ai to recycle different versions. No limits outside of the credits. https://www.meshy.ai/ ... also https://github.com/comfyanonymous/ComfyUI?tab=readme-ov-file#installing ... https://huggingface.co/spaces/stabilityai/stable-point-aware-3d/tree/main ... https://github.com/Stability-AI/stable-point-aware-3d/blob/main/README.md#comfyui-extension ... see [Discord chat](https://discord.com/channels/958209073277456457/1031058655581323324/1329235207827750984) for the pipeline for imagination to 3d

> I use Luma to lay out 3D templates then I make them in Low poly in Blender

> Vox: We should find a way to make "optimization" a central topic for builders. I would suggest to open a separate channel under "Platform" where the most relevant information about the topic is pinged.

> ashxn: imo gpu instancing is the key to large optimized worlds.
a palette of 10-20 models used thousands of times to build a world, max fps in 10-20 draw calls

![image](https://hackmd.io/_uploads/BJ8u0QPDkx.png)

> Animating: https://www.mixamo.com/#/?page=1&query=lying+down&type=Motion%2CMotionPack
> 
> Hiro: I'm obviously new to Hyperfy building and I'm trying to get my pipeline dialled so I can build highly optimised worlds with "best practice" in mind. Once I've got it all dialled I'll ask fewer silly questions...I promise 🙂
> SO, I'm getting 5-8ms consistently. I have a 3060Ti and I'm watching the memory etc in task manager and it's not being troubled. My current process:
> create mesh in blender using alt+D to instance parts wherever possible
> export to Substance Painter (SP) for texturing
> export packed textures from SP using appropriate sizes for the different meshes (from 256 to 4k)
> create materials in Blender using the exported packed textures (separate channels) and export the gltf
> use gltf to optimise the gltf (using your script above) and export the optimised /compressed gltf
> import the optimised gltf into Hyperfy
> 
> So the obvious culprit is the 4k texture I've added to the terrain, I've exported that as 1k to see if it made a difference to the performance. Literally, identical...5-8ms depending on what the avatar is doing. So, I think it must be the instancing that's causing the overhead. I really want to have a high number of instances (grass, trees etc) so would be a shame if I have to remove them but is there any more detailed way I can troubleshoot performance than gltf.report and the tools in Hyperfy? Or some ninja way of creating grass that doesn't cost 3ms 🤣  Any suggestions/observations would be very welcome.
> [11:06 AM]hiroP: Update: it's definitely how I was instantiating the grass. Any tips on creating clumps of grass in a super optimised way would be great 😀
> [11:12 AM]hiroP: Even with the 4k texture I'm getting 1-2ms which is blowing my mind. So cool.

> i have been generating meshes in the lumaAI discord, the 'refined' meshes that come out of there are mostly between 3 and 4 MB in size.
> Running 'merge by distance' deletes around 10000 vertices every time. After doing that i run the textures through here https://imagecompressor.com/
> Then I export with 'draco compression' in Blender. After all this, the resulting size is approx 900KB.

>You can also use anything from mixamo:
> download rig only FBX (no mesh)
import into blender (3.4+ recommended), edit armature and add a root bone at origin (parent to the mixamo hips bone so its actually a root bone)
export as glb (select "optimize animation" and probably sample at ~3 to get a super optimized file)

>Ash: quantization is important for keeping file size down.

>7:17 PM]jin: drag n drop model, click model, inspect menu gives you rating + info about how to further optimize, educating the user on best practices for better performance

> Learn from MetaRick, he was visited by the Poly Police:
![image](https://hackmd.io/_uploads/S1I0D4DDJx.png)


> **Technical Considerations for worlds**
> * File size
> * Number of triangles
> * Draw calls
> * Minimum system requirements
> * Optimal browser configurations
> * Limiting world file sizes


**Q&A**
1. Q: Does anyone know why/if it matters whether KHR extensions are on. In Jin's example above I believe KHR_materials_ior is the refraction of glass-like materials (i.e. distortion seen through transparent materials). A: If it’s not being used it won’t have a performance impact. It’s simply a notation inside the GLB saying that if it DOES find any, it should be processed
2. Q: Anyone know how to best deal with importing glbs into blender when they’re using meshopt or Draco. A: Drop them into gltf.report and select “uncompressed” and reexport!
3. Q: Anyone have any suggestions to clean up and further optimize my Beast VRM? I cleaned up all unused data blocks and decimated it until I could't anymore? A: Reduce texture sizes, Make sure all textures are jpg
, Make sure draco compression is on, conversely play around with decimate modifier
4. Q: How to spot issues with normals? A: ???
5. Q: What's the difference between textures and materials? A: ???
6. Q: Will decimate be my friend? A: Yes
7. Q: What does LODs have to do with optimization? A: ???
8. Q: What browsers and devices work best with Hyperfy? A: ???
9. Q: What are the performance specs to run Hyperfy worlds? A: At minimum 512mb of RAM
10. Q: Will baking make my world smell great? A: ???
11. Q: What are common 3d file formats used to represent models? * .GLB / .GLTF,  .OBJ, .FBX, .Blend


