feat: add Unity asset export via optional agentdecompile[unity] extra - #158
Merged
Conversation
ilspycmd is ILSpy's .NET global tool (dotnet tool install -g ilspycmd), not a PyPI package -- it cannot be expressed as a pip dependency, and adding it to optional-dependencies would break `pip install agentdecompile[all]` for everyone (confirmed: pip/uv cannot resolve it under any name). Added an [all] extra bundling the real pip-installable optional features (currently `semantic`) and documented ilspycmd installation separately in the README as an external prerequisite. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ros3797gzvmswnJudQ1Znk
New `unity-export` CLI subcommand (agentdecompile-recover unity-export
--install-root <dir> --out-dir <dir>) and src/agentdecompile_recovery/
unity_assets.py, adapted from a bounded-memory UnityPy-based export script
proven out on a large real-world title where AssetRipper's whole-graph
loading OOM'd (heavy Mesh/BlendShapeData).
Exports textures, sprites, audio clips, text assets, and fonts one object
at a time (freeing each immediately), so peak memory stays roughly
constant regardless of asset file size on disk -- unlike full
project-reconstruction tools that load the entire asset graph before
writing anything out. Deliberately does not attempt meshes/materials/
scene-prefab structure; that needs the fuller project-graph tooling this
module is not trying to replace.
UnityPy is optional (`pip install agentdecompile[unity]`, or via the
`[all]` extra) and imported lazily -- importing unity_assets never
requires it to be installed; a clear ImportError names the extra to
install if the CLI command is invoked without it.
Also fixed, discovered while running the test suite on this branch:
- tests/test_rewrite_queue.py's two multiprocessing concurrency tests
failed under Python 3.14 even on Linux (PicklingError on a locally-
nested function target) -- Python 3.14 changed the default
multiprocessing start method away from fork on Linux too (previously
only macOS defaulted away from fork). Forced multiprocessing.get_context
("fork") explicitly, same fix already shipped for the macOS-only case.
- source_parity_synthesize.py: removed an unused `.state.now` import
(ruff F401), pre-existing and unrelated, blocking the lint CI step.
610 unit tests pass; ruff clean.
# Conflicts: # pyproject.toml # tests/test_rewrite_queue.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #154, which GitHub auto-closed when its base branch (docs/ilspycmd-optional-dependency, from #150) was deleted after #150's squash-merge. Same content, retargeted to master.
Summary
New
unity-exportCLI subcommand andsrc/agentdecompile_recovery/unity_assets.py, adapted from a bounded-memory UnityPy-based export script proven out on a large real-world Unity title where AssetRipper's whole-graph loading OOM'd on heavy Mesh/BlendShapeData.UnityPyis optional (pip install agentdecompile[unity], or via[all]) and imported lazily -- importingunity_assetsnever requires it installed; invoking the CLI command without it raises a clearImportErrornaming the extra.Test plan