- AssetStudio como Herramienta Fundamental para la Ingeniería Inversa de Unity
Al trabajar con proyectos de Unity donde los archivos fuente originales se han perdido o cuando se necesita acceder a recursos empaquetados en un APK o EXE, AssetStudio se convierte en una herramienta esencial. Su valor no reside en su interfaz gráfica, sino en su capacidad para analizar directamente el protocolo de serialización binaria de Unity (SerializedFile) y las bases de datos de recursos (AssetBundle/Assets File) sin depender del Editor de Unity ni de sus APIs.
AssetStudio interpreta la estructura de memoria de los archivos binarios de Unity: desde la identificación de versiones mediante el Magic Number del Header, hasta la tabla de mapeo Class ID para localizar estructuras MonoBehaviour, y el seguimiento de la cadena Object Info Offset para leer bloques de datos reales. Este enfoque "byte-level" permite procesar versiones de Unity desde 2017.4 hasta 2023.3, incluyendo LTS y Beta, con soporte extensible para recursos cifrados mediante interfaces de desencriptación.
En una ocasión, al diagnosticar un problema de carga de recursos en un proyecto iOS, AssetStudio reveló rápidamente que dos TextAsset tenían el campo m_Bytes vacío, identificando la causa raíz del error Resources.Load<TextAsset> sin necesidad de descompilar IL2CPP. Esta capacidad de diagnóstico rápido convierte a AssetStudio en infraestructura crítica para programadores Unity, artistas técnicos y equipos de control de calidad.
AssetStudio es una herramienta de solo lectura que no modifica recursos, no inyecta código en tiempo de ejecución y no se conecta a servidores remotos, lo que lo hace compatible con políticas de seguridad corporativa.
- Flujo de Datos Interno: Cadena de Análisis en Cuatro Capas
La interfaz de AssetStudio oculta un proceso de análisis en cuatro capas. Comprender cada capa es crucial para evitar errores comunes como carpetas de exportación vacías. Tomemos como ejemplo un APK de Android compilado con Unity 2020.3.41f1.
2.1 Capa 1: Identificación y Desempaquetado del Contenedor de Archivos
Al arrastrar un APK, AssetStudio realiza una descomposición del contenedor:
- Verifica el número mágico (
PK\x03\x04) y utiliza su motor Zip interno para extraer archivos del directorioassets/bin/Data/, incluyendoresources.assets,sharedassets0.assetsy archivos.assetbundle. - Para
assets.carde iOS, emplea el analizador del protocolocarmgrde Apple. - En construcciones WebGL con
data.unityweb, detecta y descomprime automáticamente el encabezado gzip.
Los fallos en esta etapa suelen ocurrir cuando el APK está endurecido (ej. con 360加固) o cuando la versión de Unity es superior a 2022.3, añadiendo un campo EncryptionKey al header. La solución consiste en actualizar a la versión v0.16.20+ de AssetStudio o modificar manualmente el byte 0x18 del archivo a 01 00 00 00 con un editor hexadecimal.
2.2 Capa 2: Análisis del SerializedFile y Reconstrucción del TypeTree
Tras el desempaquetado, AssetStudio analiza la estructura SerializedFile de cada archivo .assets:
- Lee el campo
m_Versiondel Header para cargar la definición TypeTree correspondiente desde archivos JSON enAssetStudio/Types/. - TypeTree actúa como "plano de tipos" del serializador de Unity, describiendo campos, tipos y desplazamientos. Por ejemplo,
Texture2D.m_Widthtiene desplazamiento 0x38 en Unity 2018.4 y 0x40 en 2021.3. - Para ScriptableObjects personalizados, si falta
Assembly-CSharp.dll, se mostrará como "Unknown Type". Se puede extraer el DLL desdeassets/bin/Managed/usandoTools → Extract Assembly.
No confíes ciegamente en "Auto Detect Version". Un campo
m_Versionmodificado manualmente puede causar errores en el análisis deAnimationClip. Verifica siempre el campo "Unity Version" en las propiedades del archivo.
2.3 Capa 3: Análisis de Object Info e Indexación de Recursos
Tras analizar el SerializedFile, AssetStudio construye el árbol de indexación:
- Cada recurso (ej. una textura PNG) se almacena como
Object Info(con ID, Type ID, Size, Offset) +Data Block(datos binarios reales). - El árbol de recursos izquierda agrupa
Object InfoporType ID: 21 paraTexture2D, 95 paraShader, etc. - Los recursos empaquetados en AssetBundle pueden residir en archivos
.abseparados, requiriendo cambiar el selector "Current File" en la parte superior.
2.4 Capa 4: Decodificación de Recursos y Conversión de Formato
La exportación final utiliza estrategias de decodificación específicas por tipo:
- Texture2D: Lee el campo
m_ImageDatay lo decodifica segúnm_TextureFormat(DXT5, ETC2_RGB, ASTC, etc.). - Mesh: Analiza
m_VertexData.m_DataSizeym_SubMeshespara recomponer vértices, normales y UV en formatos OBJ o FBX. - AudioClip:
m_AudioDatasuele ser PCM sin comprimir o ADPCM, guardado como WAV. Para Vorbis (.ogg), requierelibvorbis.dll.
Esta cadena de cuatro capas es interdependiente: errores en capas inferiores invalidan las superiores, causando árboles vacíos, parámetros Shader en cero o texturas negras.
- Proceso de Exportación: De una Textura UI a un PSD Utilizable
Exportar una textura UI como bg_login.png requiere siete pasos precisos:
3.1 Paso 1: Localizar el Recurso
Los PNG no existen directamente en el APK. Busca "bg_login" en el árbol de recursos. Si no aparece, el recurso podría estar en un AssetBundle como loginpanel.ab.
3.2 Paso 2: Verifiacr Integridad
Con "View Data", comprueba que m_Width y m_Height sean enteros positivos, m_TextureFormat sea correcto, y el tamaño de m_ImageData sea coherente.
3.3 Paso 3: Configurar Opciones de Exportación
- Selecciona formato PNG (no BMP) para preservar canales Alpha.
- Activa "Include Alpha".
- Desactiva "Resize to Power of Two" para mantener el diseño original.
3.4 Paso 4: Manejar Texturas Comprimidas
Para DXT5 o BC7, exporta como datos crudos .dds y convierte con herramientas como Paint.NET o GIMP.
3.5 Paso 5: Exportar Recursos Asociados
Los sprites (Type ID=27) asociados a la textura deben exportarse por separado. Exportar un Sprite recorta automáticamente al área del rect.
3.6 Paso 6: Reconstruir Capas PSD
AssetStudio no exporta PSD directamente. Se puede usar un script para dividir la textura según el campo border (nine-slice) y ensamblar capas en Photoshop:
# Script para dividir imagen según parámetros border
from PIL import Image
import sys
def dividir_por_borde(ruta_imagen, bordes):
img = Image.open(ruta_imagen)
ancho, alto = img.size
izq, inf, der, sup = bordes # left, bottom, right, top
regiones = [
(0, 0, izq, sup),
(izq, 0, ancho-der, sup),
(ancho-der, 0, ancho, sup),
(0, sup, izq, alto-inf),
(izq, sup, ancho-der, alto-inf),
(ancho-der, sup, ancho, alto-inf),
(0, alto-inf, izq, alto),
(izq, alto-inf, ancho-der, alto),
(ancho-der, alto-inf, ancho, alto),
]
for indice, caja in enumerate(regiones):
region = img.crop(caja)
region.save(f"{ruta_imagen[:-4]}_capa_{indice}.png")
if __name__ == "__main__":
dividir_por_borde(sys.argv[1], [10,10,10,10])
3.7 Paso 7: Validación Triple
- Píxel a píxel: Comparar con la vista previa del Editor de Unity.
- Canal Alpha: Superponer sobre fondos negro/blanco en Photoshop.
- Dimensiones: Verificar con
ffprobequewidth/heightcoincidan conm_Width/m_Height.
- Técnicas Avanzadas para Resolver Problemas Crónicos
4.1 Carga Lenta del Árbol de Recursos (>30s)
Para archivos >2GB, habilita Memory-Mapped Files editando AssetStudio.exe.config:
<appSettings>
<add key="MapeoMemoriaActivo" value="true"/>
<add key="TamanoMapeoMemoria" value="4294967296"/> <!-- 4GB -->
</appSettings>
Esto reduce tiempos de 47s a ~6s al evitar copias de buffer entre modo kernel/usuario.
4.2 ScriptableObject Personalizado como "Unknown Type"
Cuando falta el DLL del ensamblado, inyecta manualmente la definición TypeTree como JSON en AssetStudio/Types/:
{
"MiConfiguracion": {
"m_Script": "PPtr<MonoScript>",
"m_Version": 2,
"m_Name": "string",
"elementos": {
"Array": "PPtr<MiTipo>",
"size": "int"
}
}
}
4.3 Exportación Masiva por Línea de Comandos
Para automatizar la exportación de 1000+ recursos:
AssetStudioCLI.exe -i "C:\juego\*.assets" -o "C:\exportacion" -t "Texture2D,Mesh" -f "png,obj" --incluir-alpha
Combinado con PowerShell para filtrado avanzado:
# Exportar texturas con "icono" en el nombre y tamaño >512px
$archivos = Get-ChildItem "C:\juego\*.assets"
foreach ($archivo in $archivos) {
& "AssetStudioCLI.exe" "-i" $archivo.FullName "-o" "C:\exportacion" "-t" "Texture2D" "-f" "png" "--filtro" "nombre:icono,ancho:>512"
}
4.4 Comparación de Recursos entre Versiones
Exporta metadatos JSON con -j y usa herramientas diff para identificar cambios en m_TextureFormat, m_Width, etc.
- Casos Reales de Fallos y Diagnósticos
5.1 Árbol de Recursos Vacío pese a Carga Exitosa
Causa: Archivos TypeTree JSON eliminados por software antivirus. Solución: Restaurar desde el repositorio GitHub de AssetStudio.
5.2 Exportación de Texture2D como PNG Negro
Causa: Formato BC7 sin soporte de decodificación en versiones antiguas. Solución: Actualizar a v0.16.20+ o exportar como .dds y convertir externamente.
5.3 Sprite con Dimensiones Incorrectas (-1px)
Causa: Errores de precisión flotante en m_Rect (ej. 799.9999). Solución: Ajustar manualmente el ancho en el diálogo de exportación.
5.4 Recursos Duplicados en Árbol
Causa: Empaquetado incorrecto de AssetBundle sin DeterministicAssetBundle, generando PathID distintos para el mismo recurso.
5.5 Normales Invertidas en Mesh OBJ
Causa: Compresión de Mesh de Unity invierte normales. Solución: Recalcular normales en Blender con "Recalculate Outside".
5.6 Búsqueda por Nombre Sin Resultados
Causa: El campo m_Name puede estar vacío en Texture2D. Solución: Usar "Show All Objects", filtrar por tipo y buscar en m_StreamData.
- Flujo de Trabajo Estandarizado y Principios Clave
Flujo de 5 Pasos:
- Pre-análisis: Generar reporte resumen con
-s. - Carga: Especificar versión de Unity manualmente, habilitar mapeo de memoria.
- Exploración: Búsqueda global por palabras clave, filtrado por tipo, muestreo con "View Data".
- Exportación: Formatos duales (PNG+DDS, OBJ+FBX, WAV+raw).
- Validación: Verificación con ImageMagick, ffprobe, meshlab.
Tres Principios Inquebrantables:
- 1. Nunca confiar ciegamente en "exportación exitosa": Siempre triple verificación (píxeles, metadatos, renderizado).
- 2. Toda operación debe ser rastreable: Calcular hash SHA256 antes de cargar, añadir sufijos de versión a archivos exportados.
- 3. Preferir CLI sobre GUI: Los scripts automatizados garantizan reproducibilidad al 100%.
Este flujo transforma la incertidumbre de los recursos Unity en resultados deterministas, permitiendo entrega de recursos en minutos en lugar de horas.