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
Support for Unity's various file formats including serialized assets, compressed bundles, and web-optimized files. Each file type provides specialized loading, parsing, and compression handling.
Unity's primary asset storage format containing serialized object data with metadata and type information.
class SerializedFile:
"""
Unity serialized asset file (.assets) containing object data.
"""
@property
def unity_version(self):
"""
Unity version that created this file.
Returns:
str: Unity version string (e.g., "2020.3.1f1")
"""
@property
def version(self):
"""
Serialized file format version.
Returns:
int: Format version number
"""
@property
def target_platform(self):
"""
Target build platform.
Returns:
BuildTarget: Platform enumeration
"""
@property
def objects(self):
"""
Dictionary of all objects in this file.
Returns:
Dict[int, ObjectReader]: Mapping of path_id to objects
"""
@property
def container(self):
"""
Container path mapping for assets.
Returns:
Dict[str, ObjectReader]: Asset path to object mapping
"""
def save(self, packer="none"):
"""
Serialize file data back to bytes.
Parameters:
- packer: Compression method ("none", "lz4")
Returns:
bytes: Serialized file data
"""Unity's bundle format for packaging multiple asset files with compression and dependency management.
class BundleFile:
"""
Unity asset bundle file (.bundle, .unity3d) containing multiple assets.
"""
@property
def signature(self):
"""
Bundle signature string.
Returns:
str: Bundle format identifier
"""
@property
def version(self):
"""
Bundle format version.
Returns:
int: Format version number
"""
@property
def unity_version(self):
"""
Unity version that created this bundle.
Returns:
str: Unity version string
"""
@property
def files(self):
"""
Dictionary of files contained in this bundle.
Returns:
Dict[str, Union[SerializedFile, File]]: File name to file object mapping
"""
def save(self):
"""
Serialize bundle data back to bytes.
Returns:
bytes: Bundle file data
"""Unity's web-optimized format for streaming assets with compression.
class WebFile:
"""
Unity web file (.unityweb) for streaming deployment.
"""
@property
def files(self):
"""
Dictionary of files contained in this web archive.
Returns:
Dict[str, File]: File name to file object mapping
"""
def save(self):
"""
Serialize web file data back to bytes.
Returns:
bytes: Web file data
"""Interface for reading individual Unity objects within files.
class ObjectReader:
"""
Reader for individual Unity objects within asset files.
"""
@property
def assets_file(self):
"""
Parent asset file containing this object.
Returns:
SerializedFile: Parent serialized file
"""
@property
def path_id(self):
"""
Unique identifier for this object within its file.
Returns:
int: Object path ID
"""
@property
def type(self):
"""
Unity class type of this object.
Returns:
ClassIDType: Object type enumeration
"""
@property
def type_id(self):
"""
Numeric type identifier.
Returns:
int: Unity class ID number
"""
@property
def serialized_type(self):
"""
Serialization type information.
Returns:
SerializedType: Type metadata for serialization
"""
def read(self):
"""
Read object as parsed Unity class instance.
Returns:
Object: Parsed object with typed properties
"""
def read_typetree(self):
"""
Read object as raw dictionary using typetree.
Returns:
dict: Raw object data
"""
def save(self, obj):
"""
Save modified parsed object.
Parameters:
- obj: Modified object instance
"""
def save_typetree(self, obj):
"""
Save modified raw object data.
Parameters:
- obj: Modified object dictionary
"""Base classes and utilities for file handling.
class File:
"""
Base class for Unity file objects.
"""
@property
def name(self):
"""
File name.
Returns:
str: File name or path
"""
@property
def parent(self):
"""
Parent container file.
Returns:
File: Parent file object
"""
class DirectoryInfo:
"""
Directory information structure for file metadata.
"""
@property
def path(self):
"""
Directory path.
Returns:
str: Directory path string
"""
@property
def name(self):
"""
Directory name.
Returns:
str: Directory name
"""import UnityPy
env = UnityPy.load("game_data.assets")
# Access the serialized file directly
serialized_file = list(env.files.values())[0]
print(f"Unity Version: {serialized_file.unity_version}")
print(f"Target Platform: {serialized_file.target_platform}")
print(f"Objects: {len(serialized_file.objects)}")
# Access objects in the file
for path_id, obj_reader in serialized_file.objects.items():
print(f"Object {path_id}: {obj_reader.type.name}")
# Use container mapping
container = serialized_file.container
for asset_path, obj_reader in container.items():
print(f"Asset: {asset_path} -> {obj_reader.type.name}")import UnityPy
env = UnityPy.load("level1.bundle")
# Access the bundle file
bundle_file = list(env.files.values())[0]
print(f"Bundle Signature: {bundle_file.signature}")
print(f"Bundle Version: {bundle_file.version}")
print(f"Unity Version: {bundle_file.unity_version}")
# List files in the bundle
print("Files in bundle:")
for filename, file_obj in bundle_file.files.items():
print(f" {filename}: {type(file_obj).__name__}")
# If it's a serialized file, show objects
if hasattr(file_obj, 'objects'):
print(f" Objects: {len(file_obj.objects)}")import UnityPy
env = UnityPy.load("webplayer.unityweb")
# Access the web file
web_file = list(env.files.values())[0]
print("Files in web archive:")
for filename, file_obj in web_file.files.items():
print(f" {filename}: {type(file_obj).__name__}")import UnityPy
env = UnityPy.load("assets/")
for obj_reader in env.objects:
print(f"Object ID: {obj_reader.path_id}")
print(f"Type: {obj_reader.type.name} (ID: {obj_reader.type_id})")
print(f"File: {obj_reader.assets_file.name}")
# Read as parsed object
if obj_reader.type.name == "Texture2D":
texture = obj_reader.read()
print(f"Texture Name: {texture.name}")
print(f"Size: {texture.m_Width}x{texture.m_Height}")
# Read as raw data
raw_data = obj_reader.read_typetree()
if "m_Name" in raw_data:
print(f"Raw Name: {raw_data['m_Name']}")import UnityPy
env = UnityPy.load("original.assets")
# Modify objects
for obj in env.objects:
if obj.type.name == "Texture2D":
texture = obj.read()
texture.name = f"Modified_{texture.name}"
obj.save(texture)
# Save individual files with compression
for filename, file_obj in env.files.items():
if hasattr(file_obj, 'save') and getattr(file_obj, 'is_changed', False):
# Save with LZ4 compression
data = file_obj.save(packer="lz4")
with open(f"modified_{filename}", "wb") as f:
f.write(data)
# Or save entire environment
env.save(pack="lz4", out_path="modified_assets/")import UnityPy
from UnityPy.helpers.ImportHelper import check_file_type
from UnityPy.enums.FileType import FileType
# Check file type before loading
with open("unknown_file.dat", "rb") as f:
file_type, reader = check_file_type(f)
if file_type == FileType.BundleFile:
print("This is an asset bundle")
elif file_type == FileType.AssetsFile:
print("This is a serialized assets file")
elif file_type == FileType.WebFile:
print("This is a web file")
# Load based on detected type
env = UnityPy.load(f)import UnityPy
# UnityPy automatically handles split files
# If you have: large_asset.split0, large_asset.split1, large_asset.split2
# Just load the first one:
env = UnityPy.load("large_asset.split0")
# Or let UnityPy find and merge them:
env = UnityPy.load("directory_with_splits/")
print("Split files merged automatically")
for obj in env.objects:
print(f"Object: {obj.type.name}")Install with Tessl CLI
npx tessl i tessl/pypi-unitypy