-
-
Notifications
You must be signed in to change notification settings - Fork 54
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
Unity IL2CPP Guide outdated? #56
Comments
Good feedback, the guide is definitely in need of an update. As for the attributes: are you using the newest version from the v5 branch? For all development for you own projects you should be using the master (v4) branch |
I downloaded the packages from appveyor where it says 4.0.41. I've tried both the net4.5 and net4.7 versions. I just saw that the compiled AotGenerator.exe is on appveyor as well (packaged with a bunch of dlls). Does this need to be placed in the same Assets/Plugins/Ceras/ folder? Or can it be placed anywhere? Would the link.xml prevent unused dlls from being stripped when placing it into the Plugin folder? At 28.5MB it would increase the build size quite a bit. |
The aotgenerator only generates source code files (cs files). |
Hey, we're also (still) looking to integrate Ceras into our Unity project and I saw that you updated both wiki pages last month. The instructions on the "Usage with Unity" page seem to work now. However, the "[CerasAutoGenFormatter]" attribute mentioned on the "Unity IL2CPP (iOS and AOT)" page still does not seem to exist, leading to the same problem OP described above. Without it we get this error message when trying to serialize an instance of our MapTile class:
Without setting the "config.Advanced.AotMode = AotMode.Enabled;" from the first step the Unity Editor even crashes (without any error message) as soon as the program reaches the part where the "CerasSerializer.Serialize" method is called. Since it may be relevant: As per the instructions on the first wiki page, we're on the latest commit 02c3dcc from the master branch. |
This is the attribute you're looking for:
I will fix the guide, thanks for the reminder! edit: Guide was updated to mention the correct names to the attributes (they have been renamed recently) |
That is strange. You should be getting an exception from the .NET runtime (well, the IL2CPP compiled parts of it...) telling you about not being able to create new/dynamic code at runtime. That could be related to the IL2CPP code stripper that removes unused code (at least what that tool perceives to be unused! 😉 ) I'll investigate that when I have some more time. |
Thanks, this part seems to work now. It may be good to also mention the namespace on the wiki page though (as well as the "Ceras.GeneratedFormatters" namespace necessary for the "GeneratedFormatters.UseFormatters(config);" line in step 3) ;) However, there appear to be some problems with the "SourceFormatterGenerator" class which generates the "CerasAotFormattersGenerated.cs" file:
|
Hey, thanks for the reports, I will take care of them when I get home today! :)
In your specific scenario - which is AOT - there is no way to do this, nor can there be any serializer that can solve this (as far as I'm aware). Because hidden backing fields are an implementation detail, overwriting them is not possible in a reliable way. But for a serializer you need some guarantees. Stable and deterministic names, and/or order. I'll link an issue later that describes the issue with serializing lambda closures. The part about backing fields is closely related to the issue here. My advice:
I'll reply to the remaining things when I'm at home :) |
Sorry for the confusion, this is what I meant; basically we have all member variables set to private and if another class needs access to them we expose them through properties which contain an explicit getter. We do not use any auto-properties. |
I see. Dynamically generated code has no access restrictions whatsoever for internal/private fields. Since the AotGenerator generates C# source code, it has to obey the language rules :/ Well, there's reflection, but that's a special case. With reflection you're looking at a something like a ~100x slowdown to read/write a field/property plus the allocations that causes. For loading some application settings it won't matter, because the difference between 10 nanoseconds and even 1000 nanoseconds isn't perceivable by the user. |
Would it maybe be possible to solve this through a constructor? In our use case the objects we need to serialize / deserialize are rather large (because they contain various Lists and other Collections*) and have a lifetime of undefined length (so far they are needed through the entire time our tool runs and even when we add functionality in the future which would allow them to be replaced I'd much rather just delete them to free memory because of their size). Because of this they are not really reusable anyway which is why we're already using the overload of the "Deserialize" method which does not take a ref object but constructs a new one instead. *) We even have a few classes which just act as wrappers for some Lists or Collections which then get exposed through a property with an explicit getter; I suppose those could be turned into public readonly fields and be set by a constructor? |
@rcFMS Hm, the construction methods are incredibly flexible. Chances are that something can be done that way. I think it would help if we could come up a specific example. class BigObject
{
readonly int _someInt;
public int SomeInt => _someInt;
} And all of this is in AoT mode as well, right? Take a look at this file, I marked one example here: There are other examples in the same file as well (just CTRL+F for Let me know if that example captures the main issues here. And also let me know if you think that any of the ConstructBy methods could be of any help. Maybe one of them works pretty well for you (or is getting close and only needs a few little changes) 😄 |
Almost, we're using fully manual properties instead of expression-bodied members (since we're still on C# 6):
Yes, we're using the IL2CPP Scripting Backend (if that's the question) which is why I posted in this issue in the first place before we got a bit off-topic ;)
So if I create a constructor like below it will be used automatically? This would probably be the easiest way for me to do this then. I'm guessing if I'm not calling this constructor anywhere else I'll need to prevent code-stripping from removing it via a link.xml? I might give this a try if I have some time tomorrow.
|
Yes that constructor should work, but I'm not sure if it will be used automatically. You can either configure it manually like in the example, Also, as long as ceras knows what function or constructor to use, the parameter matching is pretty lenient. It doesn't care about uppercase/lowercase. And you probably don't even have to add the The aot code generator should write the exact same code the DynamicFormatter creates. Let me know how it goes or if there is anything unclear :) |
You shouldn't need to add anything to the link xml, as the constructor will be referenced by the generated code. |
@rcFMS The old version ( The new version ( Can you try the v5 beta instead of master? |
@rcFMS I'm not sure how this can be solved without support from Unity. |
Would it be not possible to just drop those dlls into Unity? |
Yes that's the idea of building it. It will copy the correct version to the output directory. But that's more work than just opening Ceras.sln and pressing F5 :) I'm aware that it's a bad solution :( But I don't think there is much I can do. Hmm, maybe I can modify the CI build script to package all dependency .dlls into a new archive. That should make it a little easier. |
Hi again,
I've recently started implementing some new systems for my Unity game (custom sprite renderer/animator) and wanted to try building a first executable version. After receiving a blank screen in it I turned on "Development Build" and "Autoconnect Profiler" in the Build Settings and discovered a few exceptions being thrown related to Ceras.
So I started reading your guide for IL2CPP but I'm guessing some of the steps are a bit outdated?
In step 1 I found the setting in question under "config.Advanced.AotMode". So far so good.
However, in step 2 the
[CerasAutoGenFormatter]
attribute seems to have changed? If I add it to myTile
struct I get these errors:Step 3 is a bit unclear: "Compile your assembly". Which assembly? Usually Unity compiles everything automatically so if there's anything extra needed in this case a more indepth step-by-step explanation would be helpful ;)
About the
AotGenerator.exe
: Is it included somewhere already or do I need to build this myself (is this what you mean by "Compile your assembly")?In step 4
GeneratedFormatters.UseFormatters(config);
doesn't seem to work. However,CerasUnityFormatters.ApplyToConfig(config);
from here does work. Is this the new/renamed version of that method?And is the
Extension.cs
file still needed? I think I remember you saying something about rebuilding some stuff to handle the Unity types automatically?Including the
link.xml
from step 5 is easy enough.Any help with this would be much appreciated!
Cheers :)
The text was updated successfully, but these errors were encountered: