Extracción y Análisis de Recursos de Unity con AssetStudio: Guía Técnica Avanzada

  1. 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.

  1. 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 directorio assets/bin/Data/, incluyendo resources.assets, sharedassets0.assets y archivos .assetbundle.
  • Para assets.car de iOS, emplea el analizador del protocolo carmgr de 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_Version del Header para cargar la definición TypeTree correspondiente desde archivos JSON en AssetStudio/Types/.
  • TypeTree actúa como "plano de tipos" del serializador de Unity, describiendo campos, tipos y desplazamientos. Por ejemplo, Texture2D.m_Width tiene 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 desde assets/bin/Managed/ usando Tools → Extract Assembly.

No confíes ciegamente en "Auto Detect Version". Un campo m_Version modificado manualmente puede causar errores en el análisis de AnimationClip. 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 Info por Type ID: 21 para Texture2D, 95 para Shader, etc.
  • Los recursos empaquetados en AssetBundle pueden residir en archivos .ab separados, 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_ImageData y lo decodifica según m_TextureFormat (DXT5, ETC2_RGB, ASTC, etc.).
  • Mesh: Analiza m_VertexData.m_DataSize y m_SubMeshes para recomponer vértices, normales y UV en formatos OBJ o FBX.
  • AudioClip: m_AudioData suele ser PCM sin comprimir o ADPCM, guardado como WAV. Para Vorbis (.ogg), requiere libvorbis.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.

  1. 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 ffprobe que width/height coincidan con m_Width/m_Height.
  1. 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.

  1. 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.

  1. Flujo de Trabajo Estandarizado y Principios Clave

Flujo de 5 Pasos:

  1. Pre-análisis: Generar reporte resumen con -s.
  2. Carga: Especificar versión de Unity manualmente, habilitar mapeo de memoria.
  3. Exploración: Búsqueda global por palabras clave, filtrado por tipo, muestreo con "View Data".
  4. Exportación: Formatos duales (PNG+DDS, OBJ+FBX, WAV+raw).
  5. 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.

Etiquetas: AssetStudio Unity IngenieríaInversa ExtracciónRecursos AssetBundle

Publicado el 7-12 03:58