Skip to content

Fix issue #140 (AssetBundles cannot be loaded at runtime)#197

Merged
ds5678 merged 3 commits intoBepInEx:masterfrom
aceman1209:master
Jan 4, 2025
Merged

Fix issue #140 (AssetBundles cannot be loaded at runtime)#197
ds5678 merged 3 commits intoBepInEx:masterfrom
aceman1209:master

Conversation

@aceman1209
Copy link
Copy Markdown
Contributor

@aceman1209 aceman1209 commented Jan 3, 2025

Tested on Miside latest version (Unity 2021.3.35f1)

Fixed incorrect IL code

Field "Il2CppObjectBase.IsWrapped" is not static field

Fixed MethodInfo references

"Il2CppObjectBase.createGCHandle" and "Il2CppObjectBase.isWrapped" are marked as "internal". They are not public outside the current assembly and cannot be accessed as public methods (GetMethod by default returns public methods)

Fixed NullPointerException when trying get native class from Il2CppClassPointerStore.

As far as I understand, converting IL code to native CPP code does not affect absolutely all classes (judging by the libraries obtained from CPP2IL). For example, AssetBundle in UnityEngine.AssetBundleModule. Therefore, it is impossible to get a pointer to a native class, in fact, it does not exist in the context of Il2CppClassPointerStore.

@ds5678
Copy link
Copy Markdown
Collaborator

ds5678 commented Jan 3, 2025

As far as I understand, converting IL code to native CPP code does not affect absolutely all classes (judging by the libraries obtained from CPP2IL). For example, AssetBundle in UnityEngine.AssetBundleModule.

Can you elaborate on this?

@aceman1209
Copy link
Copy Markdown
Contributor Author

aceman1209 commented Jan 4, 2025

As far as I understand, converting IL code to native CPP code does not affect absolutely all classes (judging by the libraries obtained from CPP2IL). For example, AssetBundle in UnityEngine.AssetBundleModule.

Can you elaborate on this?

I will try.

I started my research with the reason why the else if-statement branch is used. After fixing the IL code and method references I still got NullPointerException. I assumed that the problem is in the AssetBundle class itself.

Next, in dotPeek I opened UnityEngine.AssetBundleModule from the interop folder, which I got from BepInEx. I checked the differences between UnityEngine.AssetBundleModule.AssetBundle and UnityEngine.GameObject. AssetBundle has no constructor, only a static one.

изображение

I thought this was incorrect and checked the library from Unity itself. In it, AssetBundle has a private constructor that is sent to the constructor of the parent UnityEngine.Object.

изображение

Assuming that the problem was in the generation, I started checking Il2CPPInterop.Generator. The search led me to the class Passes.Pass10CreateTypedefs. After checking what classes were present during generation, I found out that from the UnityEngine.AssetBundleModule module, only AssetBundleCreateRequest, AssetBundleRecompressOperation and AssetBundleRequest exist.

After tracking where gameAssembly comes from, I moved on to the CPP2IL files. In the generated files from GameAssembly.dll and metadata.dat, I checked UnityEngine.AssetBundleModule.

изображение

So, I assumed that Unity wasn't translating all of its classes into CPP code during compilation. After fixing the code to get the native class, NullPointerException went away and the asset loaded as expected.

I have 2 theories about this. And I'm not sure about both of them, because I've only studied how Il2CPP works superficially.

  1. Unity does not compile all of its code to CPP at all.
  2. Unity cuts out unused methods and classes when compiling to CPP.

Since I tested this on Miside, I can't say for sure that they don't use AssetBundle, but most likely not.

@ds5678
Copy link
Copy Markdown
Collaborator

ds5678 commented Jan 4, 2025

Unity cuts out unused methods and classes when compiling to CPP.

This is what's happening. It's called stripping. We unstrip Unity modules in the later passes of generation.

@aceman1209
Copy link
Copy Markdown
Contributor Author

aceman1209 commented Jan 4, 2025

Unity cuts out unused methods and classes when compiling to CPP.

This is what's happening. It's called stripping. We unstrip Unity modules in the later passes of generation.

In that case, there is no pointer to the IL2CPP class for AssetBundle because it is an unstripped type, right? Or have I misunderstood how this works? A little later I will check how it works if the class is used directly in the game assembly

The only thing that confuses me is GC Finalize. Could you please tell me how it works? I'm not sure AssetBundle shouldn't have it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants