Last active
October 31, 2024 02:09
-
-
Save jesliwang/6bc582bbc310e4eff58814577b4118d1 to your computer and use it in GitHub Desktop.
Unpack Assets For Unity Games From Apks or assetbundles
This file contains 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
#!/Users/Jesli/opt/anaconda3/bin/python | |
# -*- coding: UTF-8 -*- | |
import io, os | |
import UnityPy | |
import sys, getopt | |
import traceback | |
import json | |
class UnPackUnityAsset: | |
def __init__(self, inFile, outDir): | |
self.inFile = inFile | |
self.outDir = outDir | |
def GetOutDirByType(self, typeName): | |
return os.path.join(self.outDir, typeName) | |
def SaveTexture2D(self, data): | |
targetDir = self.GetOutDirByType('Texture2D') | |
isExist = os.path.exists(targetDir) | |
if not isExist: | |
os.makedirs(targetDir) | |
if data.m_Width != 0: | |
outPath = os.path.join(targetDir, data.name + ".png") | |
try: | |
data.image.save(outPath) | |
except Exception as e: | |
print(traceback.format_exc()) | |
pass | |
else: | |
print(data.name, "Can't be processed") | |
def SaveSprite(self, data): | |
targetDir = self.GetOutDirByType('Sprite') | |
isExist = os.path.exists(targetDir) | |
if not isExist: | |
os.makedirs(targetDir) | |
outPath = os.path.join(targetDir, data.name + ".png") | |
try: | |
data.image.save(outPath) | |
except: | |
pass | |
def SaveMesh(self, mesh): | |
targetDir = self.GetOutDirByType('Mesh') | |
isExist = os.path.exists(targetDir) | |
if not isExist: | |
os.makedirs(targetDir) | |
outPath = os.path.join(targetDir, mesh.name + ".obj") | |
with open(outPath, "wt", newline = "") as f: | |
exportData = mesh.export() | |
if isinstance(exportData, str): | |
f.write(mesh.export()) | |
else: | |
print(mesh.name, 'is not a mesh') | |
def SaveText(self, text): | |
targetDir = self.GetOutDirByType('TextAsset') | |
isExist = os.path.exists(targetDir) | |
if not isExist: | |
os.makedirs(targetDir) | |
outPath = os.path.join(targetDir, text.name + ".txt") | |
with open(outPath, "wb") as f: | |
f.write(bytes(text.script)) | |
def SaveMono(self, mono): | |
targetDir = self.GetOutDirByType('MonoBehaviour') | |
isExist = os.path.exists(targetDir) | |
if not isExist: | |
os.makedirs(targetDir) | |
outPath = os.path.join(targetDir, mono.name + ".txt") | |
if mono.script: | |
with open(outPath, "wt", encoding="utf8") as f: | |
try: | |
print(type(mono.script)) | |
f.write(json.dump(mono.script.read().to_dict(), f, ensure_ascii = False, indent=4)) | |
except Exception as e: | |
print(traceback.format_exc()) | |
pass | |
def SaveShader(self, shader): | |
targetDir = self.GetOutDirByType('Shaders') | |
isExist = os.path.exists(targetDir) | |
if not isExist: | |
os.makedirs(targetDir) | |
showName = shader.m_ParsedForm.m_Name | |
showName = showName.replace(' ', '_') | |
showName = showName.replace('/', '_') | |
print(shader.m_ParsedForm.m_Name, showName) | |
outPath = os.path.join(targetDir, showName + ".txt") | |
with open(outPath, "wt", encoding="utf8") as f: | |
f.write(shader.export()) | |
def UnPack(self, *args): | |
self.env = UnityPy.load(self.inFile) | |
all = True if len(args) == 0 else False | |
for obj in self.env.objects: | |
if all or (obj.type in args): | |
if obj.type == "Texture2D": | |
data = obj.read() | |
self.SaveTexture2D(data) | |
elif obj.type == "Sprite": | |
data = obj.read() | |
self.SaveSprite(data) | |
elif obj.type == "Mesh": | |
mesh = obj.read() | |
self.SaveMesh(mesh) | |
elif obj.type == "TextAsset": | |
text = obj.read() | |
self.SaveText(text) | |
elif obj.type == "MonoBehaviour": | |
mono = obj.read() | |
self.SaveMono(mono) | |
elif obj.type == "Shader": | |
shader = obj.read() | |
print(type(shader)) | |
self.SaveShader(shader) | |
#else: | |
#print(obj.type) | |
def Usage(argv): | |
UsageMessage = os.path.basename(__file__) + ' -i <input> -o <outputpath>' | |
inp = '' | |
outDir = '' | |
filterConfig = None | |
try: | |
opts, args = getopt.getopt(argv, "hi:o:f:") | |
except getopt.GetoptError: | |
print(UsageMessage) | |
sys.exit(2) | |
for opt, arg in opts: | |
if opt == "-h": | |
print(UsageMessage) | |
sys.exit() | |
elif opt in ("-i"): | |
inp = arg | |
elif opt in ("-o"): | |
outDir = arg | |
elif opt in ("-f"): | |
filterConfig = arg | |
if '' == inp or '' == outDir: | |
print(UsageMessage) | |
sys.exit(2) | |
unpacker = UnPackUnityAsset(inp, outDir) | |
if filterConfig == None: | |
unpacker.UnPack() | |
else: | |
unpacker.UnPack(filterConfig) | |
if __name__ == "__main__": | |
Usage(sys.argv[1:]) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment