[C#] Codegen for Unity
Created by: iBicha
Description
This is an issue to discuss how a C# generator can be effectively useful in a Unity project. I've been told the C# codegen is under a refactor phase, so my suggestion is to consider the next few points, to maybe include in this refactor.
I don't know if Unity will require a separate template, but it's a possibility.
Related issues/PRs
This issue will extend the points discussed here, kindly consider taking a look at it before continuing: https://github.com/swagger-api/swagger-codegen/issues/8569
Suggest a fix/enhancement
Here's a list of things one might want to consider when supporting codegen for Unity:
- Using UnityWebRequest (see issue above): the usual way to call a UnityWebRequest and wait for a response is through Coroutines (example) or through the completed event.
Note that the response is returned on the main thread (and of course, the deserialization of the response should happen on a background thread).
Also, this can easily be made into an async/await
style by creating an Awaiter, maybe something like this:
//UnityWebRequestAsyncOperation is an AsyncOperation
public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOperation)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
asyncOperation.completed += operation => { taskCompletionSource.TrySetResult(true); };
return ((Task) taskCompletionSource.Task).GetAwaiter();
}
Which will bring me to the next point:
- Depending on the configuration of a Unity project, the .Net version running can be 3.5 or 4.x equivalent. For that reason, some C# features are not always accessible. Fortunately, Unity has define symbols allowing to identify the configuration, and have code to support it accordingly. For example:
public class API {
//
//APIs using Coroutines here, which is supported on both runtime versions
//
#if NET_4_6
//
//APIs using async/await here, only available in 4.6
//
#endif
}
-
As for Json serialization, the obvious choice would be Newtonsoft's, although it is known that there are few modifications needed for it to work correctly on different platforms. This asset could be of help.
-
The
IL2CPP
backend converts C# code into C++, for performance purposes. While this is a great feature, it has few limitations, including working with generic virtual methods (see the bottom of the page). In one of the cases (as an example), the deserialization fails because the converter tries to construct aCollectionWrapper<decimal?>
object, which was not generated. So what I had to do is to make a call to it somewhere, so the the IL2CPP backend would pick it up, and generate the C++ equivalent:
#if ENABLE_IL2CPP
//THIS IS NEEDED SO THAT IL2CPP CAN JSON DESERIALIZE List<decimal?>
void UsedOnlyForAOTCodeGeneration()
{
new CollectionWrapper<decimal?>((IList<decimal?>) new List<decimal?>());
}
#endif
}
Once the constructor is actually called anywhere in the code, the code converter picks it up and generate equivalent C++ code for it.
Note 1: When il2cpp backend is used, the symbol ENABLE_IL2CPP
is defined.
Note 2: in this case, CollectionWrapper
is internal, that's why I had to make it public, and recompile the Json.Net library. For this reason, any method generic virtual method needed for the correct deserialization can be generated accordingly, as needed (a work around for private/internal types might be needed)
-
Script compilation and assembly definition files Unity recompiles the project after every code change automatically. Assembly definition files can divide code into separate assemblies/projects, for faster compilation. An OpenAPI generated project can have it's own probably.
-
In my previous issue, I mention editor extensions to make it easier to generate code. This can be a separate project which makes a call to the C# generator (either through a CLI or a rest service). This is something I have implemented with the current C# generator of swagger, and it helped me iterate faster (after changing a json file containing my spec, I can regenerate the code with a click of a button, see image from previous issue)
-
Unity mostly doesn't need any build scripts, only raw C# files.
-
Supporting Unity Test Runner
Please feel free to ask questions, and discuss. But from my experience with codegen and Unity, these are the main points that would make working with REST APIs a seamless experience when using Unity.