thejinchao / turbolink

TurboLink is an unreal engine plugin enables Google gRPC work with Unreal Engine using C++ and Blueprint
MIT License
129 stars 32 forks source link

gRPC server support? #8

Closed swiftysix closed 1 year ago

swiftysix commented 1 year ago

Hi,

You're plugin looks very nice. However, I need a gRPC server in Unreal Engine. From the description it looks like this plugin only supports client side in UE. Is that correct?

thejinchao commented 1 year ago

Yes, this plugin currently only supports client-side functionality, and I have no plans to support server-side functionality. According to my experience, to support the grpc server function in UE, the first thing to solve is the cross-platform problem. In order to realize the grpc client function on multiple platforms (including windows, android, ios and ps5), I modified the code of grpc and several other open source libraries (abseil, protobuf and re2) it depends on. The code involves io, network and multi-threading, especially ps5, it is very troublesome to debug. If server functions are to be implemented, I believe more code may need to be modified. The second difficulty I think should be the need to implement a reasonable multi-threaded task processing mechanism. Because as a grpc server, it is obviously necessary to handle multiple task requests. In this case, you need to implement a multi-thread pool and also need to cooperate with the main thread of UE (such as blueprints). I think this will be a very complicated thing.

WilSimpson commented 1 year ago

I would also question why you would want to do this. I can't think of any use-case where having the gRPC server in the UE process would be better or even a good option. What use case are you looking at?

swiftysix commented 1 year ago

@thejinchao Oh, I didn't realize that this plugin supports all these platform. The project I'm working on is more of a proof of concept for my employer, so platform compatibility is not of great concern for now. It's also non-gamedev so PS5 would probably not be in scope. The threading issue is a bigger problem I guess. I'd only need connect one or a couple of clients, so I guess the problem is also not that hard compared to a server which needs to support thousands of connections. Still, you might be right and hacking something myself might be out of my reach for now.

swiftysix commented 1 year ago

@WilSimpson Good question :). There's a desktop application which uses 3D positioning of various sensors. I'd like to write a component for that application which simulates a 3D world. So the idea is to have the desktop application as a gRPC client and query 3D data from the server (Unreal Engine). So far, I read that gRPC works best with unary rpc requests from client to server. Hence, the goal of moving the server to Unreal Engine (desktop application will query Unreal Engine for 3D points).

I know that gRPC also supports streaming, so I guess I could also do something with a long-running stream that would notify the client that new data is waiting on the server, which it should request. In that case I could potentially implement the server in the desktop application and keep the client in Unreal Engine. However, this feels a bit backward compared to doing straightforward unary rpc calls from client to server. This approach would also be easier if I could use oneof, however this is not supported in TurboLink either due to issues with Blueprint compatibility.

To be honest, I'm not fixated on gRPC, I could also imagine using another technology. I also considered MQTT, which would be good because UE has an official plugin available already. Plus, the brocker would be a separate application (e.g. Mosquitto) so any hard-core threading work would probably already be taken care of by that application. However, MQTT is probably going to be too slow in the long run - regarding data transfer speed. Something else I considered is using websockets directly. However, then I don't get the nice serialization for different languages that protobuf gives me (also no rpcs out of the box). I could of course also still use protobuf and use websockets - but then it feels a bit like I'm trying to re-implement gRPC lol.

@thejinchao sorry for hijacking this issue for my personal matters. I just wanted to give WilSimpson a proper answer. You can close the issue if you wish, since you already answered my initial questions. Thank you :) (Of course I'd be very grateful if you still have some suggestions. I'm pretty stuck right now 😅 )

WilSimpson commented 1 year ago

@swiftysix Here are some quick thoughts:

  1. If you're the developer of the 3d application, make that application the gRPC server.
  2. If the host (or only client) is on the same computer as the desktop app: write the data points to a file and read from that file in unreal. Aka memory-mapped file.
  3. Make a sidecar/proxy gRPC server. Have two endpoints: one which accepts a data point input stream and saves it in memory queue (desktop app inputs). Have another endpoint that reads from the queue and outputs (game client reads). If you need lower latency between the exchange of data you could do something like go channels.

As an aside multi-threading shouldn't be an obstacle. Create a runnable thread for each stream unreal is taking. If it's multiplayer, then only the dedicated server (or host) receives the data from the application and let unreal handle networking to the connected players.

I don't think 3 is the best option.

thejinchao commented 1 year ago

Since your server (unreal engine program) runs on some single operating system and does not need to consider cross-platform, and the number of clients is small, then I think it is still possible to implement the grpc server in UE. My suggestion is not to consider blueprints, try to implement all operations with grpc in c++, and minimize the coupling between server logic and grpc library。