UniRx
UniRx copied to clipboard
Add support for .net standard to project
Unity recently mentioned in an article on .net update that ideally libraries for unity should be targetting .net standard profile:
The .NET Standard 2.0 profile matches the profile of the same name published by the .NET Foundation. This is a great profile to choose for a new Unity project. It is smaller than .NET 4.x and we recommend it for size-constrained platforms such as mobiles. In addition, weβll make sure this profile works on all platforms Unity supports. If you are a developer of libraries used with Unity, this is the profile you want to target.
Given the nuget version of the project is out of date, and unity are going to be slowly phasing out the old runtime now would be a good time to update the nuget project and add .net standard support in. I would probably also suggest dropping support for anything < unity 2017 as you have older releases for that, it would make the code base simpler to maintain and build.
If it helps I have made a branch which is a large re-work of the codebase which is still not entirely finished but supports .net standard, has full test coverage with xUnit and has split the projects into a purely .net layer and a unity layer:
https://github.com/grofit/unirx/tree/pure-dotnet-and-namespaces
Nice work !
It would be nice to know if @neuecc gives you the greenlight π
Tbh the fork is just a proof of concept I think it is more something that could be used as a basis, ultimately not much needs to change I think to support .net standard in unity, the main issue is getting unirx to consumable as a .net standard dll which would make it consumable on any .net platform (also why I have some appetite to resurrect the nuget package version). I think Unity allows this via those assembly definition things but its all a bit woolly at the moment and going forward I think there is some appetite from unity to move shared libs to pure C# projects that expose dlls rather than C# files in unity, the problem then becomes how to manage the myriad of different versions needed for different platforms etc (i.e AoT) which are currently handled via pragmas.
With Unity 2018 supporting .NET Standard 2.0, I wonder if we could just use the official dotnet/reactive along with the UnityEngineBridge or not?
This was discussed in the channel a bit, problem is:
- System.Reactive v3.* dont seem to work in unity and version 4 is on hiatus at the moment, see their issue log for more info
- Performance and GC is a lot worse in System.Reactive code (I have not seen this for myself but this is one thing a lot of people mention when it comes up in conversation
- I dont think its simple to extend
Observable
so UniRx would have to have some otherUnityObservable
or something, I had to solve this in the branch I created above but even then its not ideal
I would love for this to be the case as then the amount of maintainable code shrinks, and I think it was even mentioned in another issue on here, but at the moment we are just waiting for UniRx to update or System.Reactive.
Things seem to be working nicely using System.Reactive, although I do have some issues with AOT and System.Reactive.Linq which I assume are due to this static var: https://github.com/dotnet/reactive/blob/master/Rx.NET/Source/src/System.Reactive/Linq/Observable_.cs
Also, I discussed briefly with the devs of RxNET, and here are some things worth mentioning:
- System.Reactive 4.0 is out, and the community has finally gathered back up
- According to them, performance and GC shouldn't be any worse. As a matter of fact, UniRx was based on old System.Reactive structure, along with their old architecture which has improved a lot since then.
- System.Reactive 4.1 is the next version they'll be pushing out, with the goal of further improving performance.
Well if you at happy enough with the new rx.net 4.* working on most devices I have a partial rework into pure .net that I can convert into some sort of rx.net for unity or something, the main task would be:
- Remove anything that already exists in rx.net
- Isolate Scheduler related functionality for unity
- Make sure all unity specific functionality consumes
System.Reactive
based classes - Make sure extension methods target
System.Reactive
classes wherever needed
There is one thing I think most people would like to keep and that is an Observable
instance that basically exposes the common System.Reactive
and unity specific methods in one place, i.e Observable.EveryFrame
. This was a hassle when I was trying to map over to a pure .net version as in unirx Observable
was a static partial which was basically getting appended to all over the shop, and I expect something similar in rx.net. To work around this in mine I converted the unirx version to a class with static methods and just inherited a new Observable
in the unity namespace which added the custom bits in, although in this scenario it may need to be more of a facade, where we create it like that but just wrap all the underlying calls to system.reactive.
Anyway I am happy to put in some of the work on a prototype if there is some appetite for it based on my .net standard port, but in terms of testing etc I could do with some of you guys to help out there.
I would also say that it may be worth splitting out certain things into other packages, like ReactiveProperty
, ReactiveCollection
, ReactiveDictionary
, IMessageBroker
etc all of these structures are great and would help people doing game dev in regular .net (i.e monogame, godot etc) so maybe that could go into some other package separate to the unity one.
I think it would be best to start with System.Reactive rather than basing on UniRx. And afterwards port the unity specific functions, which should be pretty easy.
Like I said, if AOT fails compiling certain functions such as Linq namespace ( which contains a lot of necessary functions like SkipUntil
TakeUntil
) then there's a high chance it will also fail compiling on various platforms, like WebGL in my case.
When I say failing to compile, I actually mean that the functions aren't parsed. So what I end up with, are some errors the moment SkipUntil
, Repeat
or any of those Linq functions are executed. It's worth pointing out that even with errors, it still compiles but with missing functions.
Sounds good, keep us up to date with progress as I would love to just rely upon rx.net and just bolt on this unity stuff!
Making System.Reactive
AOT compatible appears to be quite challenging, especially when I'm lacking a huge portion of knowledge and experience with AOT/IL2CPP. I'll seek some help on the official rxnet slack channel.
Hi, I try to understand what you are talking here about but I'm not much wiser after I read all. So simple question any ETA for Netstandard 2.0 support?
Unless @neuecc himself gives you an ETA there isnt one, currently @Xerios is investigating if we even need Unirx any more as we can potentially use rx.net as the basis then add the unity specific stuff on in a new library (or this one if the maintainer decides to go that route and add more maintainers)
There's no ETA on standard 2.0 support since neuecc lost motivation to continue working on this ( according to his blogpost ). Although he may come back, it's hard to tell, UniRx isn't his only project and it's understandable.
We might not get any additional changes anytime soon. You might've noticed that there were no proper updates for months! UniRx already works with Netstandard 2.0, so I don't see what you can get out of it.
I've tried porting Rx.NET over few days to something AOT-compatible, but every time I would end up having to remove or modify more and more features that made Rx.NET better than UniRx, eventually ending up rewriting a lot of features. Issue is mostly related to the AOT compiler that Unity currently uses, hopefully Unity devs will switch to CoreRT for their AOT compiler, which would fix most issues and allow Rx.NET to be compiled to IL2CPP properly.
Porting Rx.NET to AOT-friendly version is definitely not a one man task, and the effort will completely go to waste once AOT improvements have been implemented.
For now, the best thing to do if you need to use IL2CPP-restricted build, is to continue using UniRx. It is functional and has most Rx functions implemented. If you're building for non-IL2CPP platforms such as standalone builds, then you can use RxNET directly without any issues.
Do you really mean it "UniRx already works with Netstandard 2.0"? When I switch to NET 4.x backend and Netstandard 2.0 I get few errors. How should I understand what you stated above?
Thanks, Marek.
I've just tried it with an empty project and I don't. I've been developing using NET 4.x + netstandard 2.0 + UniRx for months now and I've never encountered any issues.
You could fork this repo and fix your specific issues yourself, but seeing the lack of activity in the Pull Requests section, I doubt anything would be merged back into this repo anytime soon.
Hi, I had to add on few places NET_STANDARD_2_0 preprocessor. Especially there where there was defined NET_4_6 or NETFX_CORE. Can anyone fix it in repository please? Marek.
To be precise it is in files FromCoroutine, TaskObservableExtensions, Tuble, IProgress, IObserver, IObservable, AsyncSubject, CancellationDisposable. Hope it helps, Marek.
Create a new issue describing your bug with a way to reproduce, then wait forever in despair because no-one will come to rescue you π
There hasn't been a single update since December... Your best luck would be to see if one of the 25 pull requests or any of the 390 forks actually contains the fix.
In any case, as for me, I moved on to pure RxNET, so godspeed brave soul, godspeed.
Well just compiled Built Unity Android and all works :-) So no issue with that only that perprocessors NET_STANDARD_2_0. I fixed my version and I guess I wonβt be updating long time.
You have workable RxNET? with that Unity extensions on top of it?
Can you share?
On Jun 17, 2018, at 10:14 PM, Sam Megidov [email protected] wrote:
Create a new issue describing your bug with a way to reproduce, then wait forever in despair because no-one will come to rescue you π
There hasn't been a single update since December... Your best luck would be to see if one of the 25 pull requests or any of the 390 forks actually contains the fix.
In any case, as for me, I moved on to pure RxNET, so godspeed brave soul, godspeed.
β You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/neuecc/UniRx/issues/300#issuecomment-397885447, or mute the thread https://github.com/notifications/unsubscribe-auth/AcnLooDnhttt09c6soSoRbx8Ws3k6f5lks5t9nJDgaJpZM4TEkeM.
Rx.NET works with Unity, read my comments. Any build that requires IL2CPP, doesn't.
I see then I stick to UniRx since it is compilable after my fix also with il2cpp. :-)
Cheers.
On Jun 17, 2018, at 10:20 PM, Sam Megidov [email protected] wrote:
Rx.NET works with Unity, read my comments. Any build that requires IL2CPP, doesn't.
β You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/neuecc/UniRx/issues/300#issuecomment-397885890, or mute the thread https://github.com/notifications/unsubscribe-auth/AcnLoqjoBzkAlm9V1L7kCtkl6SnjTZXQks5t9nOtgaJpZM4TEkeM.
@Xerios Any further news on this? and is there any issue on the rx.net board around anything they can do to improve this use case?
Current Rx.NET bases on a lot of features that aren't supported with AOT, and making it AOT compatible means that you'll have to rework on almost half of the codebase. No wonder why neuecc started from scratch, converting the whole library is not an easy task, and keeping it up-to-date will be even harder.
Me personally, I'd wait until Unity team improves their AOT compiler.
Is this something on the roadmap (unitys), and if it is will this hopefully mitigate the problem?
I am in a tricky spot as at the moment I need to support users of unirx and rx.net within the same codebase, and atm I am having to create a tiny rx implementation to satisfy the basic internal stuff and let the consumer pick which one they want to use, but its getting more and more painful to add new features without access to one of the given libs.
@Xerios , could you point some exact classes in Rx.NET
(preferably core classes) which work bad with AOT?
- Reflection Emit - totally disallowed
- Expression LINQ - possible in AOT, but better to avoid because interpreted
- Reflection MethodInfo Delegate.Create should work fine with
link.xml
. Still may try to avoid reflection.
I did https://github.com/Xerios/AdvancedCameraControls targeting Android IL2CPP. Seems link.xml
may help. Does not looks like code generation is used, just some delegate invocation(which should work, or this is a Unity runtime issue).
11-19 15:16:33.711 6589 6608 E Unity : ExecutionEngineException: Attempting to call method 'System.Reactive.Linq.QueryLanguage::Multicast<UnityEngine.Vector2, UnityEngine.Vector2>' for which no ahead of time (AOT) code was generated.
11-19 15:16:33.711 6589 6608 E Unity : at InputManager.OnEnable () [0x00000] in <00000000000000000000000000000000>:0
11-19 15:16:33.711 6589 6608 E Unity :
11-19 15:16:33.711 6589 6608 E Unity : (Filename: currently not available on il2cpp Line: -1)
11-19 15:16:33.711 6589 6608 E Unity :
11-19 15:16:33.714 6589 6608 E Unity : ArgumentNullException: Value cannot be null.
11-19 15:16:33.714 6589 6608 E Unity : Parameter name: source
11-19 15:16:33.714 6589 6608 E Unity : at CameraController.OnEnable () [0x00000] in <00000000000000000000000000000000>:0
11-19 15:16:33.714 6589 6608 E Unity :
11-19 15:16:33.714 6589 6608 E Unity : (Filename: currently not available on il2cpp Line: -1)
11-19 15:16:33.714 6589 6608 E Unity :
Similar error https://forum.unity.com/threads/unity-5-0-3f2-il2cpp-problem-attempting-to-call-method-system-reflection-monoproperty-getteradapt.332335/
Been a while since I dived into this, but as far as I remember, a lot of code related to schedulers wasn't compatible, lots of auto-generated LINQ wasn't compatible and some other things. There were some totally readable code that didn't get compiled to AOT which made things even more confusing for me. Neuecc found some rather weird but working solutions to those problems, and there were many of those around, to a point that justifies UniRx existence.
I've seen that AsyncRx.NET has been shaping itself up quite nicely, has anyone tried it with AOT ?
Rx.NET has some interesting directive, which seems used to close generics:
#if CRIPPLED_REFLECTION
InfoOf(() => And<TLeft, TRight>(default, default)),
#else
((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TLeft), typeof(TRight)),
#endif
I have pinged in the rx.net thread too but did either of you get rx.net working in unity IL2CPP (with link.xml or whatever other stuff is needed)? @Xerios @dzmitry-lahoda
Nope, given up on this long time ago. I've been moving away from reactive extensions recently, in favor of pure C# and DOTS ( Unity's ECS ).
Once async streams (C# 8.0) lands in Unity, I can only imagine this library becoming redundant.