Unity to Three.js
1.4 K

There are times when a lightweight problem calls for a lightweight solution.

While Unity's WebGL framework is a great way to get fully-realized game environments into a browser, the time it takes to compile the framework upon opening the app creates a bit of overhead. And while those in charge of the WebGL platform have managed to reduce that overhead to about 9 seconds, it still clocks in well behind a WebGL implementation that focuses more on austerity than power. To that end, I wanted to have a way to reliably get a model (including all of its submeshes and materials) into Three.js. My current setup includes the following:
  1. Unity Editor Script that exports the information contained in an entire GameObject hierarchy's renderers into an XML script containing all mesh node data (in jSON) and material data associated with each.
  2. Three.js Model Viewer that parses the resulting XML script, loads the entire hierarchy, and allows the user to drag-rotate it to preview.

Current technical limitations:

  • Each submesh currently has each of its vertices offset by its GameObject's local transformation in the hierarchy. To potentially allow for nodal autonomy in Three.js, these submeshes will need to have their proper transform data send from Unity and interpreted by Three.js.
  • Z-sorting meshes with transparency appears to be a bit more complicated in Three.js than in Unity. In the Windmill example (model courtesy of Polygrade) the leaves that make up the climbing ivy on the stone foundation appear more discrete from each other, but also tend to z-fight among themselves.
  • Since Three.js is quite strict about using the Metallic-Roughness workflow, it's helpful if models are set up using said workflow in Unity, which is not the default but thankfully was recently made available in the standard shader set.

Features I should add:

  • Being able to export a SkinnedMeshRenderer and accompanying Armature would be useful (it would mirror the functionality of World of Warcraft's Armory, for example).
  • Three.js allows for a single map to represent ambient occlusion, roughness, and metalness, reading from the red, green, and blue channels respectively. Either customizing Unity's standard shader to handle all three tasks using a single map or writing an external tool to combine the three maps would result in two fewer maps having to be loaded and stored at runtime.
  • Particles and volumetric lighting are often important parts of even a stationary object's appearance. Being able to transfer these as well would be nice... eventually.
Dan Wild
XR Developer - Programmer