K0lb3 / UnityPy

UnityPy is python module that makes it possible to extract/unpack and edit Unity assets
MIT License
771 stars 114 forks source link

PPtr Not Found #143

Closed cruiseliu closed 1 year ago

cruiseliu commented 1 year ago

Loading the attached file (from game My Time at Sandrock) yields "PPtr Not Found". It can be normally loaded by AssetStudio.

Code

print(UnityPy.load('trialdungeon_wreck').container)

Error

{'Assets/Scene/Additive/TrialDungeon_Wreck.unity': <PPtr Not Found>}

To Reproduce

K0lb3 commented 1 year ago

AssetStudio can't resolve it either Screenshot 2022-10-19 003648

Just use Unity.load(fp).objects instead of the container. The pointer that is used for the container is invalid, it points to an object with the path id of 0, which just doesn't exist.

cruiseliu commented 1 year ago

Thanks for your help! How to get those names in AssetStudio?

>>> bundle = UnityPy.load('trialdungeon_wreck')
>>> obj = bundle.objects[-3].read()
>>> obj.path_id
35
>>> obj.name
''
cruiseliu commented 1 year ago

And I found two litter problems.

  1. UnityPy.load() does not accept pathlib.Path.
  2. Transform.__str__() raises exception.
    >>> str(bundle.objects[36].read())
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/home/lz/.local/lib/python3.10/site-packages/UnityPy/classes/Object.py", line 116, in __repr__
    return "<%s %s>" % (self.__class__.__name__, self.name)
    File "/home/lz/.local/lib/python3.10/site-packages/UnityPy/classes/Object.py", line 110, in __getattr__
    return getattr(self.type_tree, name)
    AttributeError: 'NodeHelper' object has no attribute 'name'
K0lb3 commented 1 year ago

How to get those names in AssetStudio?

obj.read().name, but mind that not all object types carry names.

UnityPy.load() does not accept pathlib.Path

I guess it's fair to say that most libs likely don't. For loading files via path a string, or a list of strings is required. Alternatively, for single-file loading file-objects and bytes/bytearrays can be passed.

Transform.str() raises exception

Tansforms are one of the object types without names. Looks like I have to patch the repr function accordingly, surprisingly, I never really used it myself.

cruiseliu commented 1 year ago

obj.read().name, but mind that not all object types carry names.

The code snippet I pasted above refers to "LightProbeFixer" in the screenshot (the 3rd last line). object.read().name returns empty string while AssetStudio gives a name.

I have two more questions.

Would you consider add fields like type and path_id to NodeHelper? It took me a while to realize its a wrapped object.

>>> reader = UnityPy.load('trialdungeon_wreck').objects[0]
>>> reader.path_id
1
>>> reader.type.name
'PreloadData'
>>> data = reader.read()
>>> data.path_id
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NodeHelper' object has no attribute 'path_id'
>>> data.type
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NodeHelper' object has no attribute 'type'

And sorry for being off topic, when an object references an external file, saying Couldn't find dependency CAB-522b..., is there a way to find which is the referred file? Maybe through someting like asset.cab_uuid? I checked all files' assets[i].cab_file but there was no match.

cruiseliu commented 1 year ago

Oh I found it. AssetStudio uses MonoBehaviour.Script.Name if MonoBehaviour.Name is empty. Seems this logic should be left to library user.

This issue can be closed now, if you don't plan to change NodeHelper API. Thanks for your help.