Perfare / AssetStudio

AssetStudio is a tool for exploring, extracting and exporting assets and assetbundles.
MIT License
13.14k stars 2.53k forks source link

In loading assets of serializable class, some field of serializable enum type is not add on TypeTree. #985

Closed asin83 closed 2 years ago

asin83 commented 2 years ago

Look at the image, and TimelineClip class have these fields;

    [Serializable]
    public class TimelineClip : ITimelineItem, ISerializationCallbackReceiver
    {
        ...
        [SerializeField] 
        private AnimationCurve m_MixOutCurve;
        [SerializeField] 
        private BlendCurveMode m_BlendInCurveMode; 
        [SerializeField]
        private BlendCurveMode m_BlendOutCurveMode;
        [SerializeField] 
        private List<string> m_ExposedParameterNames; 
        ...
        public enum BlendCurveMode
        {
            Auto = 0,
            Manual = 1
        }

The TypeTreeNode of BlendCurveMode should be added.

blendcurvemode

On debugging the assets, TypeReference.IsValueType returned false.

enum-value-type

I think type.CheckedResolve() needs on checking value type.

Unity.CecilTools.Extensions.TypeReferenceExtensions (AssetStudioUtility).

        public static bool IsEnum(this TypeReference type)
        {
            return type.IsValueType && !type.IsPrimitive && type.CheckedResolve().IsEnum;
        }
asin83 commented 2 years ago

I wrote a simple test.

using System;
using System.Linq;
using AssetStudio;
using NUnit.Framework;
using Unity.CecilTools.Extensions;

namespace AssetStudioTest
{
    public class TimelineClipLoadTest
    {
        [Test]
        public void TestTimelineClipLoding()
        {
            var assemblyLoader = new AssemblyLoader();
            assemblyLoader.Load(@"M:\TimelineClipAssemblies");
            var helper = new SerializedTypeHelper(new[] { 2017, 4, 30, 1, 2 });
            var typeDef = assemblyLoader.GetTypeDefinition("UnityEngine.Timeline.dll", "UnityEngine.Timeline.TimelineClip");
            var field = typeDef.Fields.FirstOrDefault(definition => definition.Name.Contains("m_BlendInCurveMode"));
            Console.WriteLine($"Found: {field.FullName}");
            Console.WriteLine($"Reference ValueType: {field.FieldType.IsValueType}");
            Console.WriteLine($"Resolved ValueType: {field.FieldType.CheckedResolve().IsValueType}");
            Console.WriteLine($"Enum: {field.FieldType.IsEnum()}");
            var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, helper, 1);
            var treeNodes = typeDefinitionConverter.ConvertToTypeTreeNodes();
            var targetIndex = treeNodes.FindIndex(node => node.m_Name == "m_BlendInCurveMode");
            Assert.True(targetIndex >= 0);
        }
    }
}

UnityEngine.Timeline.dll.zip

asin83 commented 2 years ago

Sorry, when I use original dll which is inside Unity Editor directory, this test worked. I will pay attention to difference with this dumped dll.

Perfare commented 2 years ago

I noticed that your dll is generated by Il2CppInspector, through debugging, I found that it is generating wrong information for all Nested types, causing cecil to read errors, and finally causing IsValueType here to return false. https://github.com/Perfare/AssetStudio/blob/dc9429feac6d991fb5f02c746dacbbabce5a50ed/AssetStudioUtility/Unity.SerializationLogic/UnitySerializationLogic.cs#L258 Also I noticed that you are working on Genshin Impact, I think you can try this il2cppdumper modified by others https://github.com/khang06/Il2CppDumper-YuanShen At least for this type, Il2CppDumper works well.

asin83 commented 2 years ago

I also noticed the problem that nested class use parent class signature, and i'm trying to fix Il2CppInspector. I will try Il2CppDumper-YuanShen later.

Thank you.

asin83 commented 2 years ago

I gave up on fixing Il2CppInspector... It's working good on Il2CppDumper-YuanShen.