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

Unity 2021.2 - IIl2CppProcessor' is obsolete #2

Closed
tayl0r opened this issue Nov 15, 2021 · 15 comments
Closed

Unity 2021.2 - IIl2CppProcessor' is obsolete #2

tayl0r opened this issue Nov 15, 2021 · 15 comments

Comments

@tayl0r
Copy link

tayl0r commented Nov 15, 2021

Packages\WebGLThreadingPatcher\ThreadingPatcher\Editor\WebGLThreadingPatcher.cs(13,37): error CS0619: 'IIl2CppProcessor' is obsolete: 'The IIl2CppProcessor interface has been removed from Unity. Use IPostBuildPlayerScriptDLLs if you need to access player assemblies before il2cpp runs.'

@tayl0r
Copy link
Author

tayl0r commented Nov 15, 2021

I spent some time researching this bug, wasn't able to solve it, but here are my findings:

You can change what ThreadingPatcher inherits from, and add a new method to make the code compile again:

public class ThreadingPatcher : IPostBuildPlayerScriptDLLs
{

        public void OnPostBuildPlayerScriptDLLs(BuildReport report) {
            this.OnBeforeConvertRun(report, report.summary.platform, Path.Combine(Application.dataPath, "../Temp/StagingArea/Data/Managed"));
        }

...

But, it still fails at build time due to .net being upgraded from version 4 to version 5. This has changed some of the classes that this code is trying to patch, so it fails doing the patching.

@VolodymyrBS
Copy link
Owner

VolodymyrBS commented Dec 7, 2021

Thanks for the feedback!
yeah, this code is pretty sensitive to changes in BCL. Looks like 2021.2 had is slightly different ThreadPool (easy to fix) and big changes in Timer.Scheduler (harder to fix). I have some work in progress that will fix it but it's not ready. Hope will have free time soon to finish it

@xucian
Copy link

xucian commented Jun 17, 2022

Hi. Any status for this?
Being able to use Task in our game is crucial, as we have several non-Unity libraries using it, and we can't easily recompile them all with non-async alternatives.
This plugin looks like a gold nugget for me, because, if you'd look on Unity forums, it's a highly requested future.

@MHDante
Copy link

MHDante commented Jun 19, 2022

You could use this script in the meantime: https://github.com/transformsai/UnityWebGLThreadingFix/blob/main/Runtime/WebGLThreadPoolPumper.cs

@PTC-sradlwimmer
Copy link

PTC-sradlwimmer commented Jun 20, 2022

@MHDante That script works really well, given its simplicity.

EDIT: my bad - reported crash was a bug on my side

@VolodymyrBS
Copy link
Owner

I have made changes to the plugin. now it will not use IIl2CppProcessor. also, some minor codegen changes to support newer Unity versions

@xucian
Copy link

xucian commented Jul 1, 2022

Hey. Sorry for bothering again. Thanks for looking into it, but have you tried with 2021.3.4f1, 2021.3.5f1, 2022.1.7f1, 2022.2.0a17?
I get "System.ArgumentException: Library/Bee/artifacts/csharpactions/DragonShift.framework.js.unityweb_pb96.info has already been registered with different file contents" when building with thread support for webgl.

I see you mention Unity 2021.2.0, so would you recommend downgrading to it to make this work? I'm currently using 2021.3.5

Also, would this work with UniTask (particularly the SwitchToThreadPool/SwitchToMainThread) and regular Task? If you could check this code sample and confirm, I'd be very grateful 🙏 :
example-unitask-async.txt

Update: I used 2021.2.19f1 and still can't get past the compilation part. Were you able to compile with 2021.2.x after you added the timer patch? I'm just looking to find any version that could build the project.

@VolodymyrBS
Copy link
Owner

I get "System.ArgumentException: Library/Bee/artifacts/csharpactions/DragonShift.framework.js.unityweb_pb96.info has already been registered with different file contents" when building with thread support for webgl.

it's interesting issue. I will try to reproduce it locally

I see you mention Unity 2021.2.0, so would you recommend downgrading to it to make this work? I'm currently using 2021.3.5

I mentioned 2021.2 just becouse it was version from issue title. but in fact I tested on latest 2021.2 and 2021.3. so I don't think that downgrade will help

@xucian
Copy link

xucian commented Jul 2, 2022

Thanks. Looking forward to it!

At this point, I downgraded all the way to 2020.1.0f1 (ofc, it's not a solution, because downgrading doesn't work in general, with the prefabs and all that). Compilation passes, but then I get this.
Just to make sure I understand, your library and MHDante's require us to set "PlayerSettings.WebGL.threadsSupport = true", right?

@MHDante
Copy link

MHDante commented Jul 2, 2022

Both my solution and Volodymyr's (use one, not both) are meant to allow short tasks that have been added to the thread pool to execute on the main thread. This is primarily because there are many c# libraries that assume the easy availability of a thread pool (like grpc). Neither solution allows for true concurrency on webgl.

The ,PlayerSettings.WebGL.threadsSupport flag is meant to activate emscripten's multithreaded mode. This allows you to use threads in c++ plugins.

Due to a bevy of issues involving memory sharing across threads, the emscripten memory model, the .Net threading/memory model and Il2cpp, it will be a while until unity can make use of emscripten threads to allow C# threads to function.

Due to this, unless you are writing c++ plugins and have a thorough understanding of emscripten's peculiarities. I would recommend leaving PlayerSettings.WebGL.threadsSupport = false

@xucian
Copy link

xucian commented Jul 2, 2022

Oh, that's so good to know! Then I don't have to worry about downgrading. Thanks a lot for clarifying it with such great detail! 🙏

What puzzles me is, with any of your 2 approaches (Unity 2021.3.5f1), the execution path just stops at this code:

		public async Task<(TConfig, string)> DownloadAsync()
		{
			string err;
			try
			{
				using (var wc = new WebClient())
				{
					var yaml = await wc.DownloadStringTaskAsync(ComposeURL());
					var cfg = TryRead(yaml, out err);

					if (cfg != null)
						return (cfg, null);
				}
			}
			catch (Exception e)
			{
				err = e.ToString();
			}

			return (null, err);
		}

The way I'm calling it is via:

		static async UniTask<string> PopulateDefaultEndpointsInternalAsync(EnvConfig newConfig)
		{
			(ServicesConfig svs, string err) = await ServicesConfig.DownloadAsync(newConfig.Stage);
			LogV($"SwitchToMainThread"); // not called
			...
		}

// The actual call
await PopulateDefaultEndpointsInternalAsync(...)

I'm using Tasks (and UniTask on Unity side) mainly because some libraries only offer Async APIS, including a library that uses .net Web requests and web clients, and some Google Auth/Storage libs (although on WebGL the Google APIs are not essential)

@VolodymyrBS
Copy link
Owner

the problem is not threading but WebClient itself.
WebClient internally uses sockets API, which is not available on WebGL. You need to change your code to use UnityWebRequest. Currently, it is the only available method to make network request from WebGL.

if you want to use UnityWebRequest in async/await manner, then you can add code like this to your project

    public struct AsyncOperationAwaiter : INotifyCompletion
    {
        private AsyncOperation _asyncOperation;

        public bool IsCompleted => _asyncOperation.isDone;

        public AsyncOperationAwaiter(AsyncOperation asyncOperation) => _asyncOperation = asyncOperation;

        public void GetResult() { }

        public void OnCompleted(Action continuation)
        {
            _asyncOperation.completed += _ => continuation();
        }
    }

    public static class AsyncOperationAwaitable
    {
        public static AsyncOperationAwaiter GetAwaiter(this AsyncOperation operation)
        {
            return new AsyncOperationAwaiter(operation);
        }
    }

it will allow you to write await request.SendWebRequest instead of using coroutines

@xucian
Copy link

xucian commented Jul 2, 2022

Oh, good, there's some light here. So after all threads would probably work fine, and I have to just hunt these points in the app that use WebClient/WebRequest. Still kind of a blocker for my project. Basically, I have to adapt my own libraries so that I pass them a "Downloader" interface that they'll use to download stuff, and for 3rd party libraries that I don't have control over - not sure if I can do something about it.
Anyway, I'll post my progress here in the following days, as I'm sure other users might encounter this.
And thanks again for support!

@MHDante
Copy link

MHDante commented Jul 3, 2022

This is out of the scope of this ticket, but I wrote an HTTPHandler for WebGL you can find here:

https://github.com/transformsai/UnityWebGLHttpHandler

It's undocumented and based on MonoWASM's Http web handler. It uses fetch for web requests. I would recommend using UnityWebRequest if you can, however.

@xucian
Copy link

xucian commented Aug 30, 2022

Following-up my previous message, I confirm all works well. So to clarify, there are no real threads (and please correct me if I'm wrong), but async/await works fine. I also posted this on a related thread on Unity forum.
Thanks again for putting the time into this!

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

No branches or pull requests

5 participants