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

Can't get object's container in some case. #150

Closed timelic closed 1 year ago

timelic commented 1 year ago

Code A snippet of the code section that cases the bug or error.

import UnityPy
def test():
    env = UnityPy.load("./data.unity3d")
    for obj in env.objects:
        if obj.type.name in ["TextAsset"]:
            data = obj.read()
            print(obj.container, data.name, obj.path_id)
if __name__ == "__main__":
    test()

>>> None IDS_STRUCTURE_SELECT 2025
>>> None IDS_EVENT_NOTIFY 2026

Error No error.

Bug When I use the above code to try other Unity resource files, it can output the correct obj.container, but when I try the data.unity3d file, its output obj.container is None. I use Asset Studio to open the same data.unity3d file, and I can get the correct container. image

To Reproduce

K0lb3 commented 1 year ago

There is an additional way that container paths can be designated beside the already implemented option. I wasn't aware of this point until now, so thanks for opening the issue.

The container paths, in this case, have to be fetched from an object of the ResourceManager type, which assigns the container paths for all objects within the BundleFile. Implementing this in UnityPy would be a bit more work so I won't implement it any time soon. Maybe with the next major version, I hope to release around new year.

For now, you can use the following snippet to get the container path:

env = UnityPy.load("data.unity3d")
for obj in env.objects:
    if obj.type.name == 'ResourceManager':
        rm = obj.read()
        for key, ptr in rm.m_Container.items():
            print(key, ptr)
            data = ptr.read()
        break
timelic commented 1 year ago

Thanks for your detailed reply, which is very helpful for my project🫡