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

Material typetree nodes changed on 2021.3.8f1 assetbundle #153

Closed WolfgangKurz closed 1 year ago

WolfgangKurz commented 1 year ago

Code

env = UnityPy.load(file) # load 2021.3.8f1 version asset bundle

for obj in env.objects:
    if obj.type.name != "MonoBehaviour":
        continue

    data = obj.read()
    mat = data.material.get_obj()
    path = mat.container

    mat = mat.read() # error here

Bug image classes/Material.py -> Wrong value

image image .serialized_type.nodes -> Nodes changed

TypeTree dump

Material Base
    string m_Name = "Battle"
    PPtr<Shader> m_Shader
        int m_FileID = 0
        SInt64 m_PathID = -4814203374122363260
    vector m_ValidKeywords
        Array Array
        int size = 0
    vector m_InvalidKeywords
        Array Array
        int size = 1
            [0]
            string data = "ETC1_EXTERNAL_ALPHA"
    unsigned int m_LightmapFlags = 4
    bool m_EnableInstancingVariants = False
    bool m_DoubleSidedGI = False
    int m_CustomRenderQueue = -1
    map stringTagMap
        Array Array
        int size = 0
    vector disabledShaderPasses
        Array Array
        int size = 0
    UnityPropertySheet m_SavedProperties
        map m_TexEnvs
            Array Array
            int size = 1
                [0]
                pair data
                    string first = "_MainTex"
                    UnityTexEnv second
                        PPtr<Texture> m_Texture
                            int m_FileID = 0
                            SInt64 m_PathID = -7558109285521748558
                        Vector2f m_Scale
                            float x = 1.0
                            float y = 1.0
                        Vector2f m_Offset
                            float x = 0.0
                            float y = 0.0
        map m_Ints
            Array Array
            int size = 0
        map m_Floats
            Array Array
            int size = 0
        map m_Colors
            Array Array
            int size = 0
    vector m_BuildTextureStacks
        Array Array
        int size = 0
  1. m_ShaderKeywords separated/replaced into m_ValidKeywords and m_InvalidKeywords array
  2. m_Ints added to m_SavedProperties

I don't know about when changed nodes, at least 2021 version has.

To Reproduce

Fixing I'm using below code about Material.py to fix right now (I'm using with 2021 version assets only)

# ...

class Material(NamedObject):
    def __init__(self, reader):
        super().__init__(reader=reader)
        version = self.version
        self.m_Shader = PPtr(reader)  # Shader

        if version >= (2021,): # 2021.0 and up
            validKeywordSize = reader.read_int()
            self.m_ValidKeywords = {}
            for i in range(validKeywordSize):
                self.m_ValidKeywords[i] = reader.read_aligned_string()

            invalidKeywordSize = reader.read_int()
            self.m_InvalidKeywords = {}
            for i in range(invalidKeywordSize):
                self.m_InvalidKeywords[i] = reader.read_aligned_string()

            self.m_LightmapFlags = reader.read_u_int()

        elif version >= (5,):  # 5.0 and up
            self.m_ShaderKeywords = reader.read_aligned_string()
            self.m_LightmapFlags = reader.read_u_int()

        elif version >= (4, 1): # 4.x
            self.m_ShaderKeywords = reader.read_string_array()

        if version >= (5, 6):  # 5.6 and up
            self.m_EnableInstancingVariants = reader.read_boolean()
            if version >= (2017,):
                self.m_DoubleSidedGI = reader.read_boolean()
            reader.align_stream()

        if version >= (4, 3):  # 4.3 and up
            self.m_CustomRenderQueue = reader.read_int()

        if version >= (5, 1):  # 5.1 and up
            stringTagMapSize = reader.read_int()
            self.stringTagMap = {}
            for _ in range(stringTagMapSize):
                first = reader.read_aligned_string()
                second = reader.read_aligned_string()
                self.stringTagMap[first] = second

        if version >= (5, 6):  # 5.6 and up
            self.disabledShaderPasses = reader.read_string_array()

        self.m_SavedProperties = UnityPropertySheet(reader)

# ...

class UnityPropertySheet:
    def __init__(self, reader):
        m_TexEnvsSize = reader.read_int()
        self.m_TexEnvs = {}
        for i in range(m_TexEnvsSize):
            key = reader.read_aligned_string()
            self.m_TexEnvs[key] = UnityTexEnv(reader)

        if reader.version >= (2021, 0):
            m_IntsSize = reader.read_int()
            self.m_Ints = {}
            for i in range(m_IntsSize):
                key = reader.read_aligned_string()
                self.m_Ints[key] = reader.read_int()

        m_FloatsSize = reader.read_int()
        self.m_Floats = {}
        for i in range(m_FloatsSize):
            key = reader.read_aligned_string()
            self.m_Floats[key] = reader.read_float()

        m_ColorsSize = reader.read_int()
        self.m_Colors = {}
        for i in range(m_ColorsSize):
            key = reader.read_aligned_string()
            self.m_Colors[key] = reader.read_color4()

But 2021 version checking seems not correct, so i post this as issue.

WolfgangKurz commented 1 year ago

I found correct code in AssetStudio repo, so i close this issue and will make PR