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

Implement support for Unity (de)serializing fields of injected MonoBehaviors #53

Open
knah opened this issue Jun 16, 2021 · 0 comments
Open
Labels
class-injection For things concerning class injection/delegate conversion enhancement New feature or request

Comments

@knah
Copy link
Owner

knah commented Jun 16, 2021

Right now injected classes have no (extra) fields. This is largely due to the fact that field storage is allocated in the managed-side object, with the il2cpp side object only holding a gchandle to the managed one.
This presents an issue with cloning gameobjects with components of injected types, and loading them from assetbundles - Unity can't access managed fields, and, as such, they are not copied during instantiation/bundle load.

Preliminary research indicates that Unity uses field offsets and (optionally) il2cpp_gc_wbarrier_set_field to directly access fields on il2cpp objects - this means that the usual approach of "hook set_field so it redirects to the managed field" is likely non-viable.

This means that an alternative approach for handling fields on injected types is necessary. I have a few approaches that I'd consider viable:

  1. Create an annotation for auto-properties alongside the lines of RedirectToNativeField. When performing class injection, a field in il2cpp class would be created for every property marked with that attribute, and its getter and setter would be patched to access the field in native object.
    • This might take some effort to interop nicely with defining those components in the editor. SerializeField and FormerlySerializedAsAttribute attributes can be applied to auto-property backing fields to make them serialized and have the appropriate name. Alternatively, injected fields can be made to match property backing field name.
    • Alternatively, the separate editor version of the component can have plain fields with correct names - removing the { get; set; } block is relatively easy.
    • Patching property getter/setter might require special magic tricks on certain runtimes (see Harmony/netcore - I believe those issues are resolved currently).
  2. Create a wrapper type for native fields, such as NativeFieldWrapper<T>. Fields of this type can be declared in the injected class, and class injector would generate a matching field in the il2cpp class for every field of that type. The wrapper would provide access to those il2cpp fields.
    • It would have been nice if C# had property delegation like Kotlin - this would look way cleaner.
    • Interop with defining those fields in the editor would be even more challenging, unless the "separate script code" approach is used.
  3. Use ISerializationCallbackReceiver to manually serialize/deserialize state to a single hardcoded string/byte[] field. This would likely work fairly well with editor interop, but might not be compatible with older unity versions if they're missing this interface. Additionally, this would require interface implementation to be supported by class injection.
  4. Maybe something else I didn't think about?

A thing to consider for injected fields would be GC integration - IL2CPP can use either boehm (which requires no special GC magic), or something sgen-like which would likely require correct GC descriptors on classes to tell it where reference-typed fields are located in the object.

@knah knah added enhancement New feature or request class-injection For things concerning class injection/delegate conversion labels Jun 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
class-injection For things concerning class injection/delegate conversion enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant