Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 3 commits into from
Jan 4, 2025

Conversation

aceman1209
Copy link
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
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
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
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
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.

@ds5678 ds5678 merged commit 3f97933 into BepInEx:master Jan 4, 2025
2 checks passed
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