[Currently In Beta]
Generate valid networking code for Unity3D that takes advantage of Unity's Web Request object instead of something like RestSharp. This project was both made for and is used by Recolude's Unity Plugin. Lots of cute unity things you can do here that wouldn't make sense sitting in original swagger codegen repo.
PRs + Issues Welcome.
Built and tested with golang 1.14, but should probably work on versions as far back as 1.10 (when string builder was introduced).
git clone https://github.com/recolude/swagger-unity-codegen.git
cd swagger-unity-codegen
go install ./cmd/swag3d
The code produced from this tool will depend on two external DLLs. Trust me I tried my best to use just the builtin Unity Serializer at first, but it's just not powerful enough to take into account all the different types of definitions a swagger file can have 😓.
The two DLLs are:
Make sure that the DLLs you grab from the packages both target the same version of .NET
If you don't want to download them through nuget, you can checkout the dlls folder in this repository. I haven't tested them with most versions of Unity though.
NAME:
swag3d - swagger and Unity3D meet
USAGE:
swag3d [global options] command [command options] [arguments...]
VERSION:
0.1.0
DESCRIPTION:
Generate C# code specifically for Unity3D from a swagger file
AUTHOR:
Elijah C Davis
COMMANDS:
generate, g Generate c# code from a swagger file
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help (default: false)
--version, -v print the version (default: false)
Command used to generate Recolude's code.
swag3d generate \
--file api/openapi-spec/swagger.json \
--config-name="RecoludeConfig" \
--config-menu="Recolude/Config" \
--tags "RecordingService" \
--namespace Recolude.API \
--out "Scripts" \
--scriptable-object-config=false
The swagger tool will generate a Scriptable Object that can be used to store different keys found in your security definitions.
You don't need a swagger file to generate your own unity code! This allows you to generate c# code as part of something like custom build pipelines that use in-house API definitions.
package main
import (
"fmt"
"net/http"
"os"
"github.com/recolude/swagger-unity-codegen/unitygen"
"github.com/recolude/swagger-unity-codegen/unitygen/model"
"github.com/recolude/swagger-unity-codegen/unitygen/model/property"
"github.com/recolude/swagger-unity-codegen/unitygen/path"
)
func main() {
// Create a new file
f, err := os.Create("api.cs")
if err != nil {
panic(err)
}
// What we want our succesful response to be
responseDefinition := model.NewObject(
"EchoResponse",
[]model.Property{
property.NewString("response", ""),
property.NewString("serverTime", "date-time"),
},
)
service := unitygen.NewService(
"ExampleService",
[]path.Path{
path.NewPath(
"api/echo", // The URL endpoint, ex: example.com/api/echo
"Echo", // Name of the function that gets generated
http.MethodGet, // Get Rquest
nil, // Different tags
nil, // Security Definitions (Like API Keys)
// Different responses that can be sent to the function
map[string]path.Response{
"200": path.NewDefinitionResponse("", responseDefinition),
},
// Paramters to call the function
[]path.Parameter{
path.NewParameter(
path.QueryParameterLocation, // Where the parameter should be located
"whatToEcho", // name of the query param
true, // require the parameter
property.NewString("val", ""), // name of the variable in c#
),
},
),
},
)
// Write the service C# code to api.cs
fmt.Fprint(f, responseDefinition.ToCSharp())
fmt.Fprint(f, service.ToCSharp(nil, "ServiceConfig"))
}
When the above code executes, it will generate the following C# code:
[System.Serializable]
public class EchoResponse
{
public string response;
[SerializeField]
private string serverTime;
public System.DateTime ServerTime { get => System.DateTime.Parse(serverTime); }
}
public class ExampleService
{
public ServiceConfig Config { get; }
public ExampleService(ServiceConfig Config)
{
this.Config = Config;
}
public class EchoUnityWebRequest
{
public EchoResponse success;
public UnityWebRequest UnderlyingRequest { get; }
public EchoUnityWebRequest(UnityWebRequest req)
{
this.UnderlyingRequest = req;
}
public IEnumerator Run()
{
yield return this.UnderlyingRequest.SendWebRequest();
Interpret(this.UnderlyingRequest);
}
public void Interpret(UnityWebRequest req)
{
if (req.responseCode == 200)
{
success = JsonConvert.DeserializeObject<EchoResponse>(req.downloadHandler.text);
}
}
}
public class EchoRequestParams
{
private bool whatToEchoSet = false;
private string whatToEcho;
public string WhatToEcho { get { return whatToEcho; } set { whatToEchoSet = true; whatToEcho = value; } }
public void UnsetWhatToEcho() { whatToEcho = null; whatToEchoSet = false; }
public UnityWebRequest BuildUnityWebRequest(string baseURL)
{
var finalPath = baseURL + "api/echo";
var queryAdded = false;
if (whatToEchoSet)
{
finalPath += (queryAdded ? "&" : "?") + "whatToEcho=";
queryAdded = true;
finalPath += UnityWebRequest.EscapeURL(whatToEcho.ToString());
}
return new UnityWebRequest(finalPath, UnityWebRequest.kHttpVerbGET);
}
}
public EchoUnityWebRequest Echo(EchoRequestParams requestParams)
{
var unityNetworkReq = requestParams.BuildUnityWebRequest(this.Config.BasePath);
unityNetworkReq.downloadHandler = new DownloadHandlerBuffer();
return new EchoUnityWebRequest(unityNetworkReq);
}
public EchoUnityWebRequest Echo(string whatToEcho)
{
return Echo(new EchoRequestParams()
{
WhatToEcho = whatToEcho,
});
}
}
Ordered by priority (to me)!
- Scriptable Object For Configuration.
- Easier Request Building.
- Prune unused definitions.
- Support for System.DateTime.
- Support Serializing Bodies.
- Polymorphism
- Implement Fluent Interface Pattern For Creating Requests.
- Optional Parameters In Request Body.
- Required Fields
- Embedded object definitions.
- Embedded array object definitions.
- Generate a scriptable object for any definition found in the swagger file.
- Ability to generate
a package recognizable by the unity package manager.*.unitypackage
- YAML support.
- Oauth security definition.