UnitySplats is a cross-platform Unity 6 package for importing, loading, and rendering 3D Gaussian Splatting (3DGS) content. It supports the Built-in Render Pipeline, URP, and HDRP, with GPU and portable CPU sorting paths selected at runtime.
UnitySplats is a modified and substantially extended fork of wuyize25/gsplat-unity. The original Unity renderer is Copyright (c) 2025 Yize Wu and is distributed under the MIT License.
The package also adapts parts of the Gaussian-splat architecture and format behavior from the PlayCanvas Engine, including concepts used by the PLY, SOG, and GLB implementations. The PlayCanvas reference used during this Unity work was v2.21.0-beta.14 (d5fe88878e338936fe763bbce1a58bc315e89cbe). PlayCanvas Engine is Copyright (c) 2011-2026 PlayCanvas Ltd and is distributed under the MIT License.
UnitySplats is a Unity implementation maintained by ARLOOPA. It is not an official PlayCanvas product and does not include the PlayCanvas JavaScript engine. Existing upstream copyright and license notices are retained in the source and in Third Party Notices.
- Standard binary 3DGS PLY and PlayCanvas compressed PLY import and runtime loading.
- Bundled and unpacked PlayCanvas SOG v1/v2 support.
- SPZ v1-v4 support, including Zstandard-compressed SPZ v4 attributes.
- Gaussian-splat GLB support using
KHR_gaussian_splatting. - Runtime loading from file paths, byte arrays, and streams.
- Spark-packed and uncompressed Unity asset representations.
- Asynchronous GPU upload with optional rendering during upload.
- Orthographic cameras, MSAA, cutouts, active source ranges, and XR integration.
- Runtime graphics-backend selection for Direct3D, Vulkan, Metal, OpenGL, and WebGL 2.
| Format | Import | Runtime load | Notes |
|---|---|---|---|
.ply |
Yes | Yes | Binary little-endian standard 3DGS and PlayCanvas compressed PLY |
.sog |
Yes | Yes | Bundled SOG v1/v2 |
unpacked SOG meta.json |
Yes | Yes | Requires the complete SOG directory |
.spz |
Yes | Yes | SPZ v1-v4, SH degrees 0-4 |
.glb |
Yes | Yes | Requires KHR_gaussian_splatting; select the UnitySplats importer per file |
The importer's Auto coordinate mode uses glTF's LUF frame for GLB and the common 3DGS/OpenGL RUB frame for PLY, SOG, and SPZ, converting the data to Unity RUF.
UnitySplats chooses the fastest compatible sorting and rendering path at runtime.
| Platform | Graphics APIs | Sort/render path |
|---|---|---|
| Windows | Direct3D 12, Vulkan | GPU radix sort when wave/subgroup requirements are available; CPU fallback otherwise |
| Windows | Direct3D 11, OpenGL Core | Asynchronous CPU counting sort with instanced GPU rendering |
| Linux | Vulkan, OpenGL Core | GPU radix sort on compatible Vulkan devices; CPU fallback otherwise |
| Android | Vulkan | GPU radix sort when supported; CPU fallback otherwise |
| Android | OpenGL ES 3.1 | Asynchronous CPU sort and portable sampled-texture draw path |
| macOS, iOS | Metal | GPU radix sort when supported; CPU fallback otherwise |
| Web | WebGL 2 | Main-thread CPU sort and portable sampled-texture draw path |
The OpenGL ES path uses RGBA8 byte-packed and floating-point sampled textures instead of vertex-stage storage buffers. This avoids driver failures seen when some mobile GPUs report SSBO support but reject Unity's generated BufferBlock bindings. OpenGL ES 3.1 is the minimum supported Android OpenGL version.
Maintainer testing has covered multiple Android and Apple devices using OpenGL ES, Vulkan, and Metal, including Samsung and HONOR Android hardware and Meta Quest 3 and Meta Quest 3S headsets. Samsung and HONOR devices were also used to validate the GLES compatibility path. Device drivers still vary, so a listed API is a supported target rather than a guarantee for every GPU/OS combination. Hardware reports are welcome through GitHub Issues.
The WebGL 2 path does not create compute or structured graphics buffers. It stores splat data and draw order in sampled textures and runs the counting sort on Unity's main thread. Use Spark compression and moderate splat counts for Web builds: browser memory limits and synchronous sorting make large uncompressed assets substantially more expensive than on native platforms. Global merge and compute cutouts are unavailable on WebGL.
The GPU radix path requires wave/subgroup operations and compatible compute workgroup limits. The CPU fallback retains instanced GPU drawing, but disables global multi-renderer merge and compute cutouts. It keeps one sort order per renderer and prioritizes a game camera, so substantially different simultaneous camera viewpoints share that order.
Cross-renderer sorting is enabled by default. It globally depth-orders splats from overlapping renderers and draws them as one merged scene when all active renderers are fully uploaded, Spark-packed, use the same GameObject layer, keep the default render order, and fit the packed renderer/index limits. Configure it from Project Settings > Gsplat. Other configurations fall back to separate draw calls.
- Unity 6000.0 or newer. The included development project uses Unity 6000.3.9f1.
com.unity.mathematics1.3.2 or newer.com.netpyoung.webp0.3.22 for SOG image decoding.- A supported graphics API from the table above.
UnitySplats already declares Unity.WebP 0.3.22 as a package dependency. To let Unity resolve it automatically, add the OpenUPM registry for the com.netpyoung scope and the UnitySplats Git URL to the target project's Packages/manifest.json:
{
"scopedRegistries": [
{
"name": "OpenUPM",
"url": "https://package.openupm.com",
"scopes": [
"com.netpyoung"
]
}
],
"dependencies": {
"com.arloopa.unitysplats": "https://github.com/arloopa/UnitySplats.git"
}
}Merge these entries with any existing registries and dependencies. Unity then installs Unity.WebP automatically when it resolves UnitySplats.
Unity Package Manager cannot resolve one Git package as a transitive dependency of another Git package. Install Unity.WebP first:
-
Open
Window > Package Manager. -
Click
+and chooseInstall package from git URL.... -
Install Unity.WebP:
https://github.com/netpyoung/unity.webp.git?path=unity_project/Assets/unity.webp#0.3.22 -
Repeat the process for UnitySplats:
https://github.com/arloopa/UnitySplats.git
This installs the repository's current default branch.
Add both direct dependencies to the target project's Packages/manifest.json:
{
"dependencies": {
"com.netpyoung.webp": "https://github.com/netpyoung/unity.webp.git?path=unity_project/Assets/unity.webp#0.3.22",
"com.arloopa.unitysplats": "https://github.com/arloopa/UnitySplats.git"
}
}Keep the project's other dependencies in the same object.
Download the UnitySplats release ZIP and extract it outside the target project's Assets folder. Configure the OpenUPM registry above, install Unity.WebP using its Git URL, or add a separately downloaded Unity.WebP package. Then open Window > Package Manager, choose + > Install package from disk..., and select the UnitySplats package.json.
The UnitySplats source archive does not bundle Unity.WebP. Unity only accepts Git dependency URLs in the consuming project's Packages/manifest.json; package-to-package automatic resolution therefore requires a scoped registry such as OpenUPM.
- Built-in Render Pipeline: no additional render feature is required.
- URP: open the active Universal Renderer Data asset and add
Gsplat URP Feature. Unity 6 RenderGraph and compatibility mode are both supported. - HDRP: add a Custom Pass Volume and a
Gsplat HDRP Passat theBefore Transparentinjection point.
For maximum performance, prefer Vulkan on Android and Vulkan or Direct3D 12 on Windows. Direct3D 11 and OpenGL automatically select the portable CPU sorter. If Android uses OpenGL, require OpenGL ES 3.1 in Player Settings.
- Copy or drag a
.ply,.sog,.spz, or Gaussian-splat.glbfile into the project'sAssetsfolder. For GLB, select the file and chooseAssets > UnitySplats > Choose GLB Importer... > UnitySplats (Gaussian Splat). You can also chooseGsplatImporterfrom Unity's Importer dropdown in the file Inspector. UnitySplats is an optional GLB importer so it can coexist with glTFast and other packages that handle ordinary GLB models. If two other installed packages both register themselves as the default GLB importer, Unity will continue to report a conflict between those packages until one is disabled or changed to an override importer; this does not prevent explicitly selecting UnitySplats for the Gaussian GLB. - Select the imported
GsplatAsset.Sparkis the recommended packed representation; selectUncompressedwhen exact in-project values matter more than memory and upload speed. - Drag the imported asset from the Project window into the Hierarchy or Scene view. UnitySplats automatically creates a GameObject with
GsplatRenderer, assigns the asset, and sets its local Z rotation to 180 degrees.
You can also create a GameObject manually, add a Gsplat Renderer component, and assign the imported asset to its Gsplat Asset field.
In the Scene view, click anywhere inside a splat's transformed asset bounds to select its GameObject; a collider is not required. Unity's normal Shift/Ctrl selection modifiers continue to work. Selecting several GsplatRenderer GameObjects enables multi-object editing for their shared inspector properties and can fit all attached BoxCollider components in one action.
When two or more Spark renderers overlap, leave Enable Cross-Renderer Sorting enabled in Project Settings > Gsplat. On supported Vulkan, Direct3D 12, and Metal devices this creates one shared per-splat depth order, preventing whole captures from switching in front of one another as the camera moves. The portable CPU sorter used by OpenGL, WebGL, Direct3D 11, and unsupported GPU configurations retains separate draw calls and cannot provide the true merged order.
Most 3DGS content is trained in gamma space. Gamma To Linear is enabled by default on GsplatRenderer; disable it when the source colors are already authored for the project's linear workflow. Conversion before alpha blending can otherwise reduce visual accuracy.
Select the SOG meta.json, then choose Assets > UnitySplats > Import unpacked SOG (Spark). Keep all referenced files beside the metadata.
Runtime loaders return an in-memory GsplatAsset and must create/assign Unity objects on the main thread.
using Gsplat;
GsplatAsset asset = GsplatRuntimeLoader.LoadFile(
absolutePath,
CompressionMode.Spark);
GsplatRenderer renderer = GetComponent<GsplatRenderer>();
renderer.GsplatAsset = asset;
// When the renderer no longer uses the runtime asset:
renderer.GsplatAsset = null;
Destroy(asset);LoadFile accepts filesystem paths. Android APK StreamingAssets, HTTP(S), and other URI-based sources should be read with UnityWebRequest, then passed to GsplatRuntimeLoader.Load(byte[], ...). Use Load(Stream, ...) or LoadUnpackedSog(...) for other input forms.
The Package Manager includes an optional Runtime PLY Loading sample that demonstrates byte-array loading and runtime asset cleanup.
GsplatRenderer.SetActiveRanges selects an exact union of source-splat ranges without creating another asset. Ranges use half-open [Offset, Offset + Count) semantics and are normalized when they overlap or touch.
renderer.SetActiveRanges(new[]
{
new GsplatActiveRange(offset: 1000, count: 500),
new GsplatActiveRange(offset: 3000, count: 250)
});
uint configured = renderer.ActiveSplatCount;
uint resident = renderer.ResidentActiveSplatCount;
renderer.ClearActiveRanges();These methods update Unity GPU buffers and must run on the main thread. Compute cutouts are bypassed while explicit ranges are enabled.
- PLY input must be binary little-endian.
- SOG v1/v2 uses Unity.WebP and its platform libwebp binaries.
- SPZ files containing
SPZ_ADOBE_coordinate_systemuse that descriptor automatically. - GLB primitives must declare
KHR_gaussian_splattingand the required accessors. UnitySplats also recognizes the legacy logarithmic scale encoding written bysplat-transform2.6.0 and older. Scene graphs that instance splat meshes with several node transforms are not flattened into one asset.
| XR render mode | Built-in | URP | HDRP |
|---|---|---|---|
| Multi-pass | Yes | Yes | No |
| Single Pass Instanced | No | Yes | No |
UnitySplats is distributed under the MIT License.
- ARLOOPA modifications and packaging: Copyright (c) 2026 ARLOOPA.
- Original
gsplat-unitywork: Copyright (c) 2025 Yize Wu, MIT License. - PlayCanvas-derived portions: Copyright (c) 2011-2026 PlayCanvas Ltd, MIT License.
Additional source components retain their original notices. See Third Party Notices for the complete attribution list, including UnityGaussianSplatting, GPUSorting, Spark, SPZ, ZstdSharp, Unity.WebP, and libwebp.
