-
Notifications
You must be signed in to change notification settings - Fork 781
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 support #1309
Comments
I want this to happen and I asked the Unity team about it here. Basically, the work required is in Unity. You should tell them that gRPC is important to you so they prioritize it. I don't know the best way to do that. Comment on Unity Future .NET Development Status? |
Thanks for the clear and detailed answer @JamesNK 🙏 |
Unity has released beta support for |
If anyone wants to try out Grpc.Net.Client on Unity, please go ahead and report back whether it works or not. I'm not a Unity developer and don't have an environment setup. |
I made a quick attempt. While I can get the project to compile, it seems that the SendAsync call simply hangs without error. The logs happily print It appears that the HttpClient in Unity's implementation does not actually support Http/2. For normal restful calls, you can reference and pass HttpVersion.Version20 but it seems that the response has version 1.1. I'm not sure if this is intended or a bug on Unity's end. |
Looks like http/2 is not supported. https://forum.unity.com/threads/unity-future-net-development-status.1092205/page-6#post-7422071 |
So Grpc.Net.Client.Web almost works. There is an issue with the referenced version of System.Buffers that makes it fail during runtime. But a rebuild linking to the correct assemblies should fix that issue as well. If I manage to build it I'll let you know. |
I looked into it in regards of the gRPC.net.client lib. It seems that unity adds their own version of system.memory which is way too old and you can not overwrite it. |
Right, so it does work at least in 2021 and up (haven't tried the older versions yet). The issue is you have to actually compile it IN unity, i.e. add it to your project. You also have to change a couple of files due to Unity's different style of includes. It should be possible to get it to compile against Unity's libraries without having to actually add it to your project each time somehow. I've verified that the client works with simple message formats at least using the generated source code from a different project via Grpc.Tools. Can't say it works for everything and also no guarantees about whether or not there might be hidden bugs. The main reason why you can't use the assemblies as is from nuget is because as others have stated the versions of System.Memory and other assemblies does differ, if you add them to the project as well you run into naming conflicts within Unity itself if you try to use any type from them. |
Alright, its actually even much simpler. You can use all the libraries targeting netstandard2.1 by default, the Grpc.Core.Api needs to be recompiled for netstandard2.1 instead of 2.0 else it won't link in Unity (the System.Memory issue). You don't even need to change any files that way. If you're using Google.Protobuf (which I guess a lot of you will be) you also need to recompile that for netstandard 2.1 (or include it in the project). You need to be careful there that it actually has a dependency set per target framework in the csproj:
where you need to add:
do note the Version 6.0.0 for System.Runtime.CompilerServices.Unsafe as that is the version that Unity apparently ships with. So in total you're going to need the following dlls for Grpc Web to work in Unity:
optionally:
You can then use any code generated clients in Unity. I have not tested server mode in any way and I don't think there is an easy way to get it to work. For code generated clients you can either add the source or just add any library that you built yourself targeting netstandard2.1. Maybe in the future Grpc will work without the Web intermediate form, but for now Grpc Web is as good as its going to get and its still faster than REST. |
This is insanely useful but I seem to have one lingering issue. Here's my code:
Error is: I have all the dll's in the project. It seems to have no problems compiling or finding all the relevant grpc code. I can replace that line with this instead and it compiles fine:
I can see both of these bits of code in the Grpc.Net.Client dll in the project, so I'm at a loss for why the first doesn't compile. Any ideas? I suspect I've gone wrong somewhere since I pretty just blindly added all the dll's to the unity project. EDIT: The documentation/tutorials are just out of date. Looking at the source code they made that constructor internal. So the correct usage is the factory method ForAddress like I had changed it to. Ignore me. |
Worth pointing out I also got this working simply by using the nuget package for unity. It downloaded the dll's correctly. Except for System.Runtime.CompilerServices.Unsafe which I got the dll for manually in the nuget package and added it to my Unity project. https://github.com/GlitchEnzo/NuGetForUnity I'm on Unity 2021.2.3. |
This seems like a Unity issue to me. If Unity supports .NET Standard 2.1 then it should support be able to use .NET Standard 2.0 targetted packages like Grpc.Core.Api and Google.Protobuf. Unity should fix itself so it is ok with running a package that is referencing a package that is using an older version of System.Memory, System.Buffers, System.Runtime.CompilerServices.Unsafe, or whatever. |
@bryding That's an internal constructor. You cannot access it. |
Interesting I tried the same thing on Unity 2021.2.0 and 2021.1 and it didn't work. Seems they are making progress regarding their compatbility. Google.Protobuf still won't load unfortunately due to the Unsafe part. This means however that you won't have to recompile any of the other libraries for netstandard2.1 if you are using 2021.2.3 and up it seems. @JamesNK You are of course correct that in a perfect world that is exactly what they should be doing. The reality is however that Unity has some idiosyncratic behaviour when it comes to assemblies. This is just some help how to work around that until it works out of the box :) |
I suppose I spoke too soon. Everything compiles, but I can't get a response back. I get this error:
There's very few instances of this exact error when I google it. My server and client code are pretty bare bones right now: Server:
Unity Client Code:
Error only shows up if I add that debug.log statement or otherwise try to interact with the response object at all. |
Are you using Grpc Web here? It seems you are missing that part in the creation of the channel. You need to set the HttpClientHandler to a GrpcWeb handler. You also need to enable GrpcWeb on the server side (or use Envoy as a proxy). Also client side streaming is not supported in Grpc Web, serverside streaming is. If you can share a minimal repro I can also take a look at it. |
@Blackclaws Thanks a bunch for helping me out with this, here's a minimal repo: https://github.com/bryding/mean-monsters-minimal I added the GrpcWebHandler, which now seems obvious in retrospect, but the error is the same (presumably because I'm not implementing the server correctly as well). |
I've pushed to a branch working-minimal that works. You need to use aspnetcore and not the raw Grpc Server as you actually need a webserver on the other side that transforms the grpc web requests. Also Grpc is usually over http so I've switched that over as well, certificate validation has been turned off because of the localhost dev certificate, you should turn that on in production. I've also used Grpc Codegeneration directly in csproj. That required a change in the relative import paths between the protobuf files. |
Hey everyone, just wanted to say that this works out of the box for me using: I'm using Unity LTS: 2020.3.23 My backend is as follows:
I generated my C# (and python) proto files using the latest protoc binaries: I then Installed NuGetForUnity: I used it to install the following Packages:
This provided the the following dlls
My client code is as follows: using System.Net.Http;
using System.Threading;
using Ai.Transforms.Grpcwebunity;
using Grpc.Net.Client;
using Grpc.Net.Client.Web;
using UnityEngine;
public class Spinner : MonoBehaviour
{
private int i = 0;
TestService.TestServiceClient client;
CancellationTokenSource cancellationTokenSource;
// Update is called once per frame
async void Awake()
{
var channel = GrpcChannel.ForAddress("http://localhost:8001", new GrpcChannelOptions
{
HttpHandler = new GrpcWebHandler(new HttpClientHandler()),
});
cancellationTokenSource = new CancellationTokenSource();
var token = cancellationTokenSource.Token;
client = new TestService.TestServiceClient(channel);
using var call = client.ServerStream(new Request { Data = "Streem" });
while (await call.ResponseStream.MoveNext(token))
{
var item = call.ResponseStream.Current;
Debug.Log("Success! " + item.Data);
}
}
private void Update()
{
if (i++ % 200 == 0)
{
PrintUnary();
}
transform.Rotate(Vector3.up, 1f);
}
private async void PrintUnary()
{
if (client == null) return;
using var call = client.UnaryAsync(new Request { Data = "Cheem " + i });
var response = await call;
Debug.Log(response.Data);
}
private void OnDestroy()
{
cancellationTokenSource.Cancel();
}
} Both Unary and server streaming calls worked fine: Congratulations!!! If there are compiling issues, I think it may have to do with DLL collisions with other packages/Assets. N.B. I've only tested this on windows editor and standalone.On an unrelated note, At the moment, I can't seem to get the calls to respond on a WebGL build. Currently, the calls get stuck waiting for awaits to resolve. I think this may have to do with the lack of thread support on Emscripten\WebGL. (how does blazor do it?) |
Yeah the issues I had with netstandard2.1 might have had to do with me using a preview of 2021.2 instead of the released build, my bad. Just glad that it works that easy now :) Blazorwasm ships with its own HttpClient implementation that uses XHR/fetch under the hood, I'm not sure what Unity does there. |
@MHDante @Blackclaws dod you get any closer to knowing if WebGL builds can support this? |
I've actually written a version of the client that can support it. It's here, but it requires a lot of work (regarding documentation and whatnot) : https://github.com/transformsai/UnityGrpcWeb You can install it in the package manager through OpenUPM: |
Looks interesting. Does it support streaming? |
I checked the operation using HTTP / 2 on Unity 2021.2.11f1 and found an error. I downloaded the package from the NuGet site. The following is the configuration.
Code for using HTTP/2:
The code that caused the error:
An error occurred in global :: Google.Protobuf.MessageExtensions.WriteTo (). The error log:
Was SerializeContext determined to be unimplemented? |
When I installed the package using NuGetForUnity, the error wording changed.
It can be executed even in this state, the following is the error log during communication:
It seems that the connection with the server is established, so is there an error related to Protobuf? |
The gRPC C# core library does not generate Protobuf related errors. It's working properly. |
Since it is an error related to Protobuf, I also reported it in Protobuf issues. I also reported on the Unity forum. |
@MHDante Can you please give some more details on the server side implementation? Is there any way right now to avoid using grpc-web with grpc-dotnet in Unity? |
@mandicLuka I had good luck putting this envoy configuration in front of my gRPC server to get grpc-web to work. Just change the ports/addresses to match: https://github.com/grpc/grpc-web/blob/8c5502186445e35002697f4bd8d1b820abdbed5d/net/grpc/gateway/examples/echo/envoy.yaml |
@ianlevesque Can you please give some more details? I tried to use this envoy.yaml, my grpc python server is using 0.0.0.0:9090 and my Unity client is using What did I missed, or did I misunderstood something? |
That error sounds like something from envoy, complaining about not reaching your real gRPC server. I can check my exact config later, I had that error first when not enabling http2 correctly in envoy and then again when trying to reach localhost from envoy inside docker on windows (there’s a special hostname docker requires to do that). Are you using docker to run envoy? |
There is a problem with unsupported HTTP/2 in Unity, so I posted information for supporting mac IL2CPP builds in gRPC Core issues in gRPC C # core-library. Build script for gRPC C# core-library for Apple M1 #29815 How to avoid Unity IL2CPP build errors on macOS #29817 |
@ianlevesque The server and client are not in docker, only the envoy proxy, but I fixed it, I had to change the socket address to 0.0.0.0 and change the url in the client to http://localhost:8080/echo_service and its working |
Having gone through this thread, is there any way using grpc-dotnet to implement client-side streaming on unity currently? |
@HannaGurwitzTT I ended up using old and deprecated Grpc.Core instead of grpc-dotnet and it works fine for both client and server implementation in Unity (tested with Unity 2021.3 LTS with grpc libs built for netstandard2.1, both on Windows and Linux). The API of both is pretty much the same and the transition from one to the other is not too much work. I hope when Unity transitions to .net5 or .net6 instead of their fork of netstandard, HTTP2 will be supported and gprc-dotnet will completely take over (at least for client side). This transition could happen in the following years, and by then there is not a standardized solution |
I did include this framework on my project and got it, at least, compiled well. I am targeting .net2 standard and made a simple call to a endpoint. I have no control over this endpoint but basically is giving me some TLS security errors:
When I configured channel I did this:
Do I need to specify I am using Unity2020.3.36. |
I have an error:
I have the error using Grpc.Net.Client.Web. Here is a code :
But, It works using Grpc.Core.
I don't know what is difference... :(( I'm afraid of using Grpc.Core cause It'll be gone. How can I avoid an error using Grpc.Net.Client.*? |
The problem might be that the server is using HTTP/2, which Unity doesn't support. See https://docs.microsoft.com/en-us/aspnet/core/grpc/browser?view=aspnetcore-6.0#http-protocol |
Some update from regarding http2 support
|
So I went down this rabbit hole too... I seem to have got Grpc.Core working talking to a server in Go, with normal requests and bidirectional streaming. (bidirectional streaming is a must for me, so Grpc-Web is not an option) It even works on my iOS device. BUT! It only works with insecure channel... If I try to add TLS, the C# client refuse to connect. I even tried to instantiate the server in C#, but still get the same error. (Just get "Unavailable" like it fails to connect at all)
Has anyone here had any luck getting Grpc.Core to work with TLS in Unity? Very sad to hear Unity is not prioritising http/2 and grpc-dotnet support... Grpc.Core is only in maintenance for one year more, and they have already dropped the Unity/Xamarin support (grpc/grpc#24236), so right now there seems to be zero support for any gRPC in Unity. Here's my test code... Using Insecure works fine both with C# Server and Golang server, and the certificates also work fine when I use a test client written in Golang to talk with my Golang server, so those should be fine too.
|
One possible solution is to use a plugin like this: https://assetstore.unity.com/packages/tools/network/best-http-2-155981 It has a built in handler that you could use as the HttpHandler on requests. The primary issue with this plugin is that it is not redistribution-friendly |
I started to implement support for grpc-dotnet using the asset store package which @MHDante mentioned (BestHTTP/2), which is an HTTP2 client written in C# (so no native libraries involved). You can find my work here: https://github.com/doctorseus/grpc-dotnet-unity
Another important note: BestHTTP does not support plaintext http2 aka "h2c with prior knowledge" (what is used if you use gRPC via an "Unsecured" channel). So you will need to use SSL on your gRPC server. |
Hopefully that new version of Unity with CoreCLR support drops this year... |
An alternative solution is to fallback to HTTP/1 (so-called grpc-web), if you are in control over server. There is an amazing documentation from Microsoft which explicitly mentions Unity: https://learn.microsoft.com/en-us/aspnet/core/grpc/netstandard?view=aspnetcore-7.0 and more general overview https://learn.microsoft.com/en-us/aspnet/core/grpc/supported-platforms?view=aspnetcore-7.0 In Asp.net the support can be added with few lines of code, while other servers will require a proxy. |
Today, we have released a preview of the HTTP/2 handler that enables the use of grpc-dotnet on Unity. This library provides an HttpMessageHandler for HTTP/2 communication, built on top of hyper. Although this project is still in its early stages and rough around the edges, we believe it is an important step forward in the Unity ecosystem. Please try out our library, and we look forward to receiving your feedback. |
Awesome, I love using your other libraries in Unity. As we are actively using GRPC in Unity using Grpc Web we'll try it out and report back if we find any issues! |
Hi, have tried using your library in Unity 2022.3.38 but, I am getting following error when I try to invoke gRPC service: IOException: client error (Connect) |
I know that Unity support isn't planned for
grpc-dotnet
(#710 and #1155).However, since Grpc.Core is going to be deprecated (see The future of gRPC in C# belongs to grpc-dotnet), what is the plan for Unity users? I haven't seen anything related in the blog post.
I know that Unity support was experimental, but are you 100% dropping it?
The text was updated successfully, but these errors were encountered: