diff --git a/lib/rbx_loader/src/loader.rs b/lib/rbx_loader/src/loader.rs
index eb804ce..11a0448 100644
--- a/lib/rbx_loader/src/loader.rs
+++ b/lib/rbx_loader/src/loader.rs
@@ -60,7 +60,9 @@ pub enum MeshError{
 	RobloxAssetIdParse(RobloxAssetIdParseErr),
 	Mesh(crate::mesh::Error),
 	Union(crate::union::Error),
-
+	DecodeBinary(rbx_binary::DecodeError),
+	OneChildPolicy,
+	MissingInstance,
 }
 impl std::fmt::Display for MeshError{
 	fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
@@ -88,6 +90,11 @@ impl From<crate::union::Error> for MeshError{
 		Self::Union(value)
 	}
 }
+impl From<rbx_binary::DecodeError> for MeshError{
+	fn from(value:rbx_binary::DecodeError)->Self{
+		Self::DecodeBinary(value)
+	}
+}
 
 #[derive(Hash,Eq,PartialEq)]
 pub enum MeshType<'a>{
@@ -132,14 +139,41 @@ impl<'a> Loader for MeshLoader<'a>{
 	type Index=MeshIndex<'a>;
 	type Resource=Mesh;
 	fn load(&mut self,index:Self::Index)->Result<Self::Resource,Self::Error>{
-		let RobloxAssetId(asset_id)=index.content.parse()?;
-		let file_name=format!("meshes/{}",asset_id);
-		// reading the entire file is way faster than
-		// round tripping to disk every read from the parser
-		let data=read_entire_file(file_name)?;
 		let mesh=match index.mesh_type{
-			MeshType::FileMesh=>crate::mesh::convert(RobloxMeshBytes::new(data))?,
-			MeshType::Union{physics_data,mesh_data}=>crate::union::convert(physics_data,mesh_data)?,
+			MeshType::FileMesh=>{
+				let RobloxAssetId(asset_id)=index.content.parse()?;
+				let file_name=format!("meshes/{}",asset_id);
+				let data=read_entire_file(file_name)?;
+				crate::mesh::convert(RobloxMeshBytes::new(data))?
+			},
+			MeshType::Union{mut physics_data,mut mesh_data}=>{
+				// decode asset
+				if !index.content.is_empty()&&(physics_data.is_empty()||mesh_data.is_empty()){
+					let RobloxAssetId(asset_id)=index.content.parse()?;
+					let file_name=format!("unions/{}",asset_id);
+					let data=read_entire_file(file_name)?;
+					let dom=rbx_binary::from_reader(std::io::Cursor::new(data))?;
+					let &[referent]=dom.root().children()else{
+						return Err(MeshError::OneChildPolicy);
+					};
+					let Some(instance)=dom.get_by_ref(referent)else{
+						return Err(MeshError::MissingInstance);
+					};
+					if physics_data.is_empty(){
+						if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=instance.properties.get("PhysicsData"){
+							physics_data=data.as_ref();
+						}
+					}
+					if mesh_data.is_empty(){
+						if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=instance.properties.get("MeshData"){
+							mesh_data=data.as_ref();
+						}
+					}
+					crate::union::convert(physics_data,mesh_data)?
+				}else{
+					crate::union::convert(physics_data,mesh_data)?
+				}
+			},
 		};
 		Ok(mesh)
 	}