A Unity asset extractor for Python based on AssetStudio that supports extraction, editing, and manipulation of Unity game assets.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive export capabilities for converting Unity assets to standard formats. Includes format conversion, compression options, and platform-specific optimizations for textures, audio, meshes, and other asset types.
Convert Unity textures to standard image formats with format detection and platform-specific handling.
class Texture2DConverter:
"""
Texture format conversion and export utilities.
"""
@staticmethod
def get_image_from_texture2d(texture_2d: Texture2D, flip: bool = True) -> Image.Image:
"""
Convert Unity texture to PIL Image.
Parameters:
- texture_2d: Texture2D object
- flip: Whether to flip image vertically
Returns:
PIL.Image.Image: Converted image
"""
@staticmethod
def image_to_texture2d(img: Image.Image, target_format: int, platform: int = 0, platform_blob: Optional[List[int]] = None) -> Tuple[bytes, int]:
"""
Convert PIL Image to Unity texture format.
Parameters:
- img: PIL Image to convert
- target_format: Target texture format ID
- platform: Target platform
- platform_blob: Platform-specific data
Returns:
Tuple[bytes, int]: Texture data bytes and actual format used
"""
@staticmethod
def parse_image_data(image_data: Union[bytes, bytearray, memoryview], width: int, height: int, texture_format: Union[TextureFormat, int], version: Tuple[int, int, int, int], platform: Union[BuildTarget, int], platform_blob: Optional[List[int]] = None, flip: bool = True) -> Image.Image:
"""
Parse raw image data bytes to PIL Image.
Parameters:
- image_data: Raw texture data
- width: Image width in pixels
- height: Image height in pixels
- texture_format: Unity texture format
- version: Unity version tuple
- platform: Build target platform
- platform_blob: Platform-specific data
- flip: Whether to flip image vertically
Returns:
PIL.Image.Image: Parsed image
"""Convert Unity audio clips to standard audio formats with support for various compression methods.
class AudioClipConverter:
"""
Audio format conversion and export utilities.
"""
@staticmethod
def extract_audioclip_samples(audio: AudioClip, convert_pcm_float: bool = True) -> Dict[str, bytes]:
"""
Extract audio samples from AudioClip as WAV data.
Parameters:
- audio: AudioClip object
- convert_pcm_float: Whether to convert PCM float to int16
Returns:
Dict[str, bytes]: Dictionary mapping sample names to WAV file bytes
"""
@staticmethod
def dump_samples(clip: AudioClip, audio_data: bytes, convert_pcm_float: bool = True) -> Dict[str, bytes]:
"""
Extract samples from raw audio data.
Parameters:
- clip: AudioClip object for metadata
- audio_data: Raw audio data bytes
- convert_pcm_float: Whether to convert PCM float to int16
Returns:
Dict[str, bytes]: Dictionary mapping sample names to WAV file bytes
"""
@staticmethod
def subsound_to_wav(subsound, convert_pcm_float: bool = True) -> bytes:
"""
Convert FMOD subsound to WAV format.
Parameters:
- subsound: FMOD subsound object
- convert_pcm_float: Whether to convert PCM float to int16
Returns:
bytes: WAV audio data
"""Export Unity mesh data to standard 3D formats.
class MeshExporter:
"""
Mesh export utilities for 3D formats.
"""
@staticmethod
def export_mesh(m_Mesh: Mesh, format: str = "obj") -> str:
"""
Export mesh in specified format.
Parameters:
- m_Mesh: Mesh object
- format: Output format ("obj" only currently supported)
Returns:
str: Mesh data in specified format
"""
@staticmethod
def export_mesh_obj(mesh: Mesh, material_names: Optional[List[str]] = None) -> str:
"""
Export mesh as Wavefront OBJ format.
Parameters:
- mesh: Mesh object
- material_names: Optional list of material names
Returns:
str: OBJ format text data
"""Export rendered meshes with material information.
class MeshRendererExporter:
"""
Export meshes with rendering information.
"""
@staticmethod
def export_mesh_renderer(renderer: Renderer, export_dir: str) -> None:
"""
Export mesh renderer with materials to directory.
Parameters:
- renderer: Renderer object (MeshRenderer, SkinnedMeshRenderer)
- export_dir: Directory to export files to
"""
@staticmethod
def get_mesh(meshR: Renderer) -> Optional[Mesh]:
"""
Get mesh from renderer component.
Parameters:
- meshR: Renderer object
Returns:
Optional[Mesh]: Associated mesh object if found
"""
@staticmethod
def export_material(mat: Material) -> str:
"""
Export material as text representation.
Parameters:
- mat: Material object
Returns:
str: Material data as string
"""Extract and process Unity sprite assets with texture atlas support.
class SpriteHelper:
"""
Sprite extraction and processing utilities.
"""
@staticmethod
def get_image_from_sprite(m_Sprite: Sprite) -> Image.Image:
"""
Extract sprite as PIL Image with alpha channel merging.
Parameters:
- m_Sprite: Sprite object
Returns:
PIL.Image.Image: Extracted sprite image with proper alpha
"""
@staticmethod
def get_image(sprite: Sprite, texture: PPtr[Texture2D], alpha_texture: Optional[PPtr[Texture2D]]) -> Image.Image:
"""
Get sprite image from texture with optional alpha texture.
Parameters:
- sprite: Sprite object
- texture: Main texture reference
- alpha_texture: Optional alpha texture reference
Returns:
PIL.Image.Image: Sprite image with alpha channel
"""
@staticmethod
def mask_sprite(m_Sprite: Sprite, mesh: MeshHandler, sprite_image: Image.Image) -> Image.Image:
"""
Apply mesh mask to sprite image.
Parameters:
- m_Sprite: Sprite object
- mesh: Mesh handler for masking
- sprite_image: Source sprite image
Returns:
PIL.Image.Image: Masked sprite image
"""Convert Unity shaders to readable formats.
class ShaderConverter:
"""
Shader code conversion and export utilities.
"""
@staticmethod
def export_shader_code(shader):
"""
Export shader source code.
Parameters:
- shader: Shader object
Returns:
str: Readable shader code
"""
@staticmethod
def export_shader_properties(shader):
"""
Export shader properties and parameters.
Parameters:
- shader: Shader object
Returns:
dict: Shader properties and metadata
"""import UnityPy
from UnityPy.export import Texture2DConverter
env = UnityPy.load("texture_assets/")
for obj in env.objects:
if obj.type.name == "Texture2D":
texture = obj.read()
# Method 1: Use built-in save method
texture.save(f"exports/{texture.name}.png")
# Method 2: Use converter for more control
image = Texture2DConverter.export_PIL(texture)
image.save(f"exports/{texture.name}_converted.png")
# Method 3: Export as bytes
png_data = Texture2DConverter.export_bytes(texture, "PNG")
with open(f"exports/{texture.name}.png", "wb") as f:
f.write(png_data)
# Export in different formats
jpeg_data = Texture2DConverter.export_bytes(texture, "JPEG")
with open(f"exports/{texture.name}.jpg", "wb") as f:
f.write(jpeg_data)import UnityPy
from UnityPy.export import AudioClipConverter
import numpy as np
env = UnityPy.load("audio_assets/")
for obj in env.objects:
if obj.type.name == "AudioClip":
audio = obj.read()
# Method 1: Use built-in save method
audio.save(f"exports/{audio.name}.wav")
# Method 2: Use converter
wav_data = AudioClipConverter.export_wav(audio)
with open(f"exports/{audio.name}_converted.wav", "wb") as f:
f.write(wav_data)
# Get raw audio samples for processing
samples = AudioClipConverter.get_samples(audio)
print(f"Audio samples shape: {samples.shape}")
print(f"Sample rate: {audio.m_Frequency}")
# Process samples (example: reduce volume)
processed_samples = samples * 0.5
# Export OGG format
try:
ogg_data = AudioClipConverter.export_ogg(audio)
with open(f"exports/{audio.name}.ogg", "wb") as f:
f.write(ogg_data)
except Exception as e:
print(f"OGG export failed: {e}")import UnityPy
from UnityPy.export import MeshExporter
env = UnityPy.load("mesh_assets/")
for obj in env.objects:
if obj.type.name == "Mesh":
mesh = obj.read()
# Export as OBJ format
obj_data = MeshExporter.export_obj(mesh)
with open(f"exports/{mesh.name}.obj", "w") as f:
f.write(obj_data)
# Export as PLY format
ply_data = MeshExporter.export_ply(mesh)
with open(f"exports/{mesh.name}.ply", "w") as f:
f.write(ply_data)
# Export just vertices for analysis
vertices = MeshExporter.export_vertices(mesh)
print(f"Mesh {mesh.name}: {len(vertices)} vertices")
# Export vertex data as CSV
import csv
with open(f"exports/{mesh.name}_vertices.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["x", "y", "z"])
writer.writerows(vertices)import UnityPy
from UnityPy.export import SpriteHelper
env = UnityPy.load("sprite_assets/")
sprites = []
textures = {}
# First, collect all textures
for obj in env.objects:
if obj.type.name == "Texture2D":
texture = obj.read()
textures[obj.path_id] = texture
elif obj.type.name == "Sprite":
sprites.append(obj)
# Export sprites
for sprite_obj in sprites:
sprite = sprite_obj.read()
# Method 1: Direct sprite export
sprite_image = SpriteHelper.export_sprite(sprite)
sprite_image.save(f"exports/{sprite.name}.png")
# Method 2: Manual cropping from texture
if sprite.texture.path_id in textures:
source_texture = textures[sprite.texture.path_id]
cropped = SpriteHelper.crop_sprite_from_texture(source_texture, sprite)
cropped.save(f"exports/{sprite.name}_cropped.png")
# Export as bytes
sprite_bytes = SpriteHelper.export_sprite_bytes(sprite, "PNG")
with open(f"exports/{sprite.name}_bytes.png", "wb") as f:
f.write(sprite_bytes)import UnityPy
import os
from pathlib import Path
def export_all_assets(asset_path, output_dir):
"""Export all supported assets from a Unity project."""
env = UnityPy.load(asset_path)
output_path = Path(output_dir)
# Create output directories
(output_path / "textures").mkdir(parents=True, exist_ok=True)
(output_path / "audio").mkdir(parents=True, exist_ok=True)
(output_path / "meshes").mkdir(parents=True, exist_ok=True)
(output_path / "sprites").mkdir(parents=True, exist_ok=True)
export_counts = {"textures": 0, "audio": 0, "meshes": 0, "sprites": 0}
for obj in env.objects:
try:
if obj.type.name == "Texture2D":
texture = obj.read()
safe_name = "".join(c for c in texture.name if c.isalnum() or c in "._-")
texture.save(output_path / "textures" / f"{safe_name}.png")
export_counts["textures"] += 1
elif obj.type.name == "AudioClip":
audio = obj.read()
safe_name = "".join(c for c in audio.name if c.isalnum() or c in "._-")
audio.save(output_path / "audio" / f"{safe_name}.wav")
export_counts["audio"] += 1
elif obj.type.name == "Mesh":
mesh = obj.read()
safe_name = "".join(c for c in mesh.name if c.isalnum() or c in "._-")
obj_data = MeshExporter.export_obj(mesh)
with open(output_path / "meshes" / f"{safe_name}.obj", "w") as f:
f.write(obj_data)
export_counts["meshes"] += 1
elif obj.type.name == "Sprite":
sprite = obj.read()
safe_name = "".join(c for c in sprite.name if c.isalnum() or c in "._-")
sprite_image = SpriteHelper.export_sprite(sprite)
sprite_image.save(output_path / "sprites" / f"{safe_name}.png")
export_counts["sprites"] += 1
except Exception as e:
print(f"Failed to export {obj.type.name}: {e}")
print(f"Export complete:")
for asset_type, count in export_counts.items():
print(f" {asset_type}: {count}")
# Usage
export_all_assets("game_assets/", "extracted_assets/")import UnityPy
from UnityPy.export import Texture2DConverter
from PIL import Image
env = UnityPy.load("texture_assets/")
for obj in env.objects:
if obj.type.name == "Texture2D":
texture = obj.read()
# Get original format info
print(f"Original format: {texture.m_TextureFormat}")
print(f"Size: {texture.m_Width}x{texture.m_Height}")
# Convert to PIL for processing
image = Texture2DConverter.export_PIL(texture)
# Apply processing
if image.mode == "RGBA":
# Convert RGBA to RGB with white background
rgb_image = Image.new("RGB", image.size, (255, 255, 255))
rgb_image.paste(image, mask=image.split()[-1]) # Use alpha as mask
# Save processed version
rgb_image.save(f"exports/{texture.name}_rgb.jpg", quality=95)
# Create thumbnail
thumbnail = image.copy()
thumbnail.thumbnail((128, 128), Image.LANCZOS)
thumbnail.save(f"exports/{texture.name}_thumb.png")
# Export multiple formats
formats = [
("PNG", "png"),
("JPEG", "jpg"),
("WEBP", "webp")
]
for format_name, ext in formats:
try:
converted_bytes = Texture2DConverter.export_bytes(texture, format_name)
with open(f"exports/{texture.name}.{ext}", "wb") as f:
f.write(converted_bytes)
except Exception as e:
print(f"Failed to convert to {format_name}: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-unitypy