Extend Service Extension codegen for Unity

Hi folks,

I’m getting set up with Extend Service Extensions and have been working through the documentation and samples. I have a working Service Extension based on the demo showed in the docs, and I’d like to hook it up to my Unity project using the AB Extend service extension codegen utility. Has anyone done this?

I followed the instructions here using the working example from the rest of the docs and it generates a Unity package, but the generated code appears to be entirely missing the actual message classes:

Packages\com.AccelByte.SDK.Custom\Runtime\Api\ClientServices.cs(41,28): error CS0246: The type or namespace name 'AccelByteClientServicesGuildCreateOrUpdateGuildProgressResponse' could not be found (are you missing a using directive or an assembly reference?)

Indeed, there’s no AccelByteClientServicesGuildCreateOrUpdateGuildProgressResponse anywhere in the generated code.

Has anyone tried this utility? What am I missing?

Thanks,
Chris

Hello there, I’m from the Extend team. Any chance you could post the exact make command you are using and the folder structure you are working with?

For example:

.
├── MyAwesomeGame
│   ├── Assembly-CSharp.csproj
│   ├── Assets
│   ├── Library
│   ├── Logs
│   ├── MyAwesomeGame.sln
│   ├── Packages
│   │   ├── manifest.json
│   │   └── packages-lock.json
│   ├── ProjectSettings
│   ├── UserSettings
│   ├── com.AccelByte.SDK.Custom
│   │   ├── Editor
│   │   ├── README.md
│   │   ├── Runtime
│   │   │   ├── Api
│   │   │   │   ├── Guild.cs
│   │   │   │   └── GuildApi.cs
│   │   │   ├── Core
│   │   │   │   ├── AccelByteCustomPlugin.cs
│   │   │   │   ├── AccelByteServerCustomPlugin.cs
│   │   │   │   ├── CustomClientConfig.cs
│   │   │   │   └── ServerCustomClientConfig.cs
│   │   │   ├── Models
│   │   │   │   └── AccelByteGuildModels.cs
│   │   │   ├── Server
│   │   │   │   ├── ServerGuild.cs
│   │   │   │   └── ServerGuildApi.cs
│   │   │   └── com.accelbyte.unitysdk.custom.asmdef
│   │   ├── package-lock.json
│   │   ├── package.json
│   │   └── version.json
│   └── com.accelbyte.UnitySDK.custom.csproj
├── accelbyte-codegen-linux_amd64
├── accelbyte-unity-sdk-template-pack
│   ├── Makefile
│   ├── res
│   └── templates
└── spec
    ├── Client
    │   └── guild.json
    ├── GameServer
    │   └── guild.json
    └── Models
        └── guild.json
cd accelbyte-unity-sdk-template-pack
make all \
CODEGEN_PATH=$(readlink -f ../accelbyte-codegen-linux_amd64) \
PROJECT_PATH=$(readlink -f ../MyAwesomeGame) \
SPEC_PATH=$(readlink -f ../spec)

edit: I’ve uploaded an example project here for you to compare.

1 Like

Hi,

I put all of my Extend Service Extension code in one folder next to the Unity project root folder.

Here are there respective layouts:

ExtendRoot
│   .env
│   commitlint.config.js
│   docker-compose.yml
│   Dockerfile
│   Jenkinsfile
│   Jenkinsfile.github
│   LICENSE.txt
│   Makefile
│   README.md
│   supervisord.conf
│          
├───codegen
│   │   accelbyte-codegen-windows_amd64.exe
│   │   fstab
│   │   
│   └───accelbyte-unity-sdk-template-pack
│    
├───gateway
│   │   go.mod
│   │   go.sum
│   │   guildService.swagger.json
│   │   main.go
│   │   permission.swagger.json
│   │   
│   ├───pkg
│   │   ├───common
│   │   │       config.go
│   │   │       gateway.go
│   │   │       tracerProvider.go
│   │   │       utils.go
│   │   │       
│   │   └───pb
│   │           guildService.pb.go
│   │           guildService.pb.gw.go
│   │           guildService_grpc.pb.go
│   │           permission.pb.go
│   │           
│   └───third_party
│               
└───src
    │                           
    └───AccelByte.PluginArch.ServiceExtension.Demo.Server
        │   AccelByte.PluginArch.ServiceExtension.Demo.Server.csproj
        │   appsettings.json
        │   Program.cs
        │                           
        ├───Classes
        │       AppSettingConfigRepository.cs
        │       AuthorizationInterceptor.cs
        │       DebugLoggerServerInterceptor.cs
        │       DefaultAccelByteServiceProvider.cs
        │       ExceptionHandlingInterceptor.cs
        │       IAccelByteServiceProvider.cs
        │       LocalPermissionItem.cs
        │       
        ├───Model
        │       GuildProgressData.cs
        │       
        ├───Properties
        │       launchSettings.json
        │       
        ├───Protos
        │   │   guildService.proto
        │   │   permission.proto
        │   │   
        │   ├───google
        │   │           
        │   └───protoc-gen-openapiv2
        │               
        └───Services
                SampleGuildService.cs

 

UnityRoot
├───Assets
├───DownloadedPackages
├───Library
├───Logs      
├───Packages
│   │   manifest.json
│   │   packages-lock.json
│   │   
│   ├───com.AccelByte.SDK.Custom
│   │   │   package-lock.json
│   │   │   package.json
│   │   │   README.md
│   │   │   version.json
│   │   │   
│   │   ├───Editor
│   │   │   └───Resources
│   │   │           ab-logo.png
│   │   │           
│   │   └───Runtime
│   │       │   com.accelbyte.unitysdk.custom.asmdef
│   │       │   
│   │       ├───Api
│   │       │       ClientServices.cs
│   │       │       ClientServicesApi.cs
│   │       │       
│   │       ├───Core
│   │       │       AccelByteCustomPlugin.cs
│   │       │       AccelByteServerCustomPlugin.cs
│   │       │       CustomClientConfig.cs
│   │       │       ServerCustomClientConfig.cs
│   │       │       
│   │       └───Server
│   │               ServerGameserverServices.cs
│   │               ServerGameserverServicesApi.cs
│   │               
│   ├───FMOD
│   │   ├───Desktop
│   │   │       Master.bank
│   │   │       Master.strings.bank
│   │   │       
│   │   └───Mobile
│   │           Master.bank
│   │           Master.strings.bank
│   │           
│   └───GuildSpec   
│       ├───Client
│       │       client_services.json
│       │       
│       ├───GameServer
│       │       gameserver_services.json
│       │       
│       └───Models
│               guildservice.swagger.json
│               
├───ProjectSettings
├───RewiredBackup
├───Temp
└───UserSettings

One of the differences I noticed with your com.AccelByte.SDK.Custom and mine: I don’t have the com.AccelByte.SDK.Custom/Runtime/Models folder or CS file. I’d bet quite a bit that the missing message class types are in that file. Now to figure out why it’s not building!

Another difference I noted:

Look at the name of my spec jsons in UnityRoot/Packages/GuildSpec/. Should Models/guildservice.swagger.json be named something specific?

Here’s why it isn’t: I couldn’t find what it should be named, so I left it the same as the base one.

I looked at Use Extend Codegen CLI to generate Unity SDK Plugin for Extend Service Extension | AccelByte Documentation - it says to make 3 copies of the .json file in subfolders below the source .json file. They are all named the same: guildService.json (in my case).

So I do this as instructed and continue to run the make all command. However, it fails with an error:

* copied ./res/com.AccelByte.SDK.Custom into com.AccelByte.SDK.Custom
* copied GuildSpec/Client into com.AccelByte.SDK.Custom/spec/Client
* copied GuildSpec/GameServer into com.AccelByte.SDK.Custom/spec/GameServer
* copied GuildSpec/Models into com.AccelByte.SDK.Custom/spec/Models
* generated package.json
* generated package-lock.json
* generated version.json
cat: client_services.json: No such file or directory

cat: gameserver_services.json: No such file or directory

This made me realize that the JSON filenames probably mattered after all, and I renamed the Client/ and GameServer/ jsons to their respective names. However, there was nothing suggesting what the model json name is expected to be. I tried a few variations on class names but nothing seemed to make a difference with the missing types.

Does this sound likely? What is the name scheme for the JSON file in Models?

Thanks,
Chris

Look at the name of my spec jsons in UnityRoot/Packages/GuildSpec/. Should Models/guildservice.swagger.json be named something specific?

it would ideally be all the same name, so if it is guild.json, you would have the following files:

  • UnityRoot/GuildSpec/Client/guild.json
  • UnityRoot/GuildSpec/GameServer/guild.json
  • UnityRoot/GuildSpec/Models/guild.json

The reason for this is the filename (without extension) is used in the filenames of the generated files.

  • from UnityRoot/GuildSpec/Client/guild.json it generates the following files:
    • UnityRoot/com.AccelByte.SDK.Custom/Runtime/Api/Guild.cs
    • UnityRoot/com.AccelByte.SDK.Custom/Runtime/Api/GuildApi.cs
  • from UnityRoot/GuildSpec/GameServer/guild.json it generates the following files:
    • UnityRoot/com.AccelByte.SDK.Custom/Runtime/Server/ServerGuild.cs
    • UnityRoot/com.AccelByte.SDK.Custom/Runtime/Server/ServerGuildApi.cs
  • and from UnityRoot/GuildSpec/Models/guild.json it generates the following file:
    • UnityRoot/com.AccelByte.SDK.Custom/Runtime/Model/AccelByteGuildModels.cs

renaming guild.json into foo.json would result in:

  • UnityRoot/com.AccelByte.SDK.Custom/Runtime/Api/Foo.cs
  • UnityRoot/com.AccelByte.SDK.Custom/Runtime/Api/FooApi.cs
  • UnityRoot/com.AccelByte.SDK.Custom/Runtime/Server/ServerFoo.cs
  • UnityRoot/com.AccelByte.SDK.Custom/Runtime/Server/ServerFooApi.cs
  • UnityRoot/com.AccelByte.SDK.Custom/Runtime/Model/AccelByteFooModels.cs

it’s structured this way so that in the event where there is more than 1 custom service each custom service would have it’s own file for Client, Server, Models.

.
├── MyAwesomeGame
│   ├── com.AccelByte.SDK.Custom
│   │   └── Runtime
│   │       ├── Api
│   │       │   ├── Foo.cs
│   │       │   ├── FooApi.cs
│   │       │   ├── Guild.cs
│   │       │   └── GuildApi.cs
│   │       ├── Models
│   │       │   ├── AccelByteFooModels.cs
│   │       │   └── AccelByteGuildModels.cs
│   │       └── Server
│   │           ├── ServerFoo.cs
│   │           ├── ServerFooApi.cs
│   │           ├── ServerGuild.cs
│   │           └── ServerGuildApi.cs
└── spec
    ├── Client
    |   ├── foo.json
    │   └── guild.json
    ├── GameServer
    |   ├── foo.json
    │   └── guild.json
    └── Models
        ├── foo.json
        └── guild.json

one thing I also noticed is that the folder com.AccelByte.SDK.Custom is placed under UnityRoot/Packages not just UnityRoot this maybe from the PROJECT_PATH set to /path/to/UnityRoot/Packages instead of just /path/to/UnityRoot.

it shouldn’t be a problem if the path in step 3 is adjusted accordingly.


This made me realize that the JSON filenames probably mattered after all, and I renamed the Client/ and GameServer/ jsons to their respective names. However, there was nothing suggesting what the model json name is expected to be. I tried a few variations on class names but nothing seemed to make a difference with the missing types.

After re-reading the statement above, it appears that the errors:

cat: client_services.json: No such file or directory
cat: gameserver_services.json: No such file or directory

caused confusion, they’re not what you need to name the files inside the spec folder (GuildSpec in your case), they are additional temporary files generated used to keep track all the services that appear inside the <spec>/Client (client_services.json) and the <spec>/GameServer (gameserver_services.json) directories, so they can be referenced in com.AccelByte.SDK.Custom/Runtime/Core/CustomClientConfig.cs and com.AccelByte.SDK.Custom/Runtime/Core/ServerCustomClientConfig.cs files respectively.


Does this sound likely? What is the name scheme for the JSON file in Models?

I’d name it similarly to the other 2 JSON files, unless there’s a specific reason not to.

edit: add section about multiple custom services
edit2: simplified example directory
edit3: add clarification regarding client_services.json and gameserver_services.json

Interesting! If I rename guildServices.swagger.json to guild.json, it works (including generating the Models CS file).


TEST 1
(my first attempt)

As for why I ended up with guildServices.swagger.json as the name, it was something I picked up in example code or docs and stuck with. I don’t remember where and can’t find it.

  • Rename the swagger file to gateway/guildServices.swagger.json
  • Copy this swagger file to the Spec folders
  • In Dockerfile: ARG SWAGGER_JSON=guildService.swagger.json
  • Delete any previous com.AccelByte.SDK.custom output folder

If you then run the make all command, you should get this error:

* copied ./res/com.AccelByte.SDK.Custom into com.AccelByte.SDK.Custom
* copied GuildSpec/Client into com.AccelByte.SDK.Custom/spec/Client
* copied GuildSpec/GameServer into com.AccelByte.SDK.Custom/spec/GameServer
* copied GuildSpec/Models into com.AccelByte.SDK.Custom/spec/Models
* generated package.json
* generated package-lock.json
* generated version.json
cat: client_services.json: No such file or directory

cat: gameserver_services.json: No such file or directory

Traceback (most recent call last):
  File "accelbyte-codegen.py", line 115, in <module>
  File "accelbyte_codegen\cli\__main__.py", line 42, in main
  File "click\core.py", line 1157, in __call__
  File "click\core.py", line 1078, in main
  File "click\core.py", line 1688, in invoke
  File "click\core.py", line 1434, in invoke
  File "click\core.py", line 783, in invoke
  File "click\decorators.py", line 33, in new_func
  File "accelbyte_codegen\cli\render\command.py", line 325, in renderc_command
  File "accelbyte_codegen\cli\render\command.py", line 106, in render     
  File "accelbyte_codegen\cli\render\processor.py", line 209, in __call__ 
  File "accelbyte_codegen\cli\render\processor.py", line 203, in __call__ 
  File "accelbyte_codegen\cli\render\processor.py", line 130, in __call__ 
  File "accelbyte_codegen\cli\render\processor.py", line 115, in __call__ 
AssertionError: 'C:\dev\Upshot\RPM-SuperMega\ExtendTest\extend-se-csharp\codegen\accelbyte-unity-sdk-template-pack\client_services.json' path does not exist
[7404] Failed to execute script 'accelbyte-codegen' due to unhandled exception!
make[1]: *** [Makefile:171: generate_settings] Error 1
make: *** [Makefile:195: generate_service_all] Error 255

This is why I thought that those files might need these specific names.


TEST 2
(what I had when I posted)

I used the previous errors as clues to the Spec filenames, and did the same steps as TEST 1 except:

  • Rename Spec/Client/guildService.swagger.json to Spec/Client/client_services.json
  • Rename Spec/GameServer/guildService.swagger.json to Spec/Client/gameserver_services.json

If you run the make all command again, it completes without error messages but the com.AccelByte.SDK.Custom/Runtime/Models folder is missing so the API has type errors:

com.AccelByte.SDK.Custom
├───Editor
│
└───Runtime
    ├───Api
    │       ClientServices.cs
    │       ClientServicesApi.cs
    │
    ├───Core
    │       AccelByteCustomPlugin.cs
    │       AccelByteServerCustomPlugin.cs
    │       CustomClientConfig.cs
    │       ServerCustomClientConfig.cs
    │
    └───Server
            ServerGameserverServices.cs
            ServerGameserverServicesApi.cs

and in Unity:

Packages\com.AccelByte.SDK.Custom\Runtime\Server\ServerGameserverServices.cs(41,28): error CS0246: The type or namespace name 'AccelByteGameserverServicesGuildCreateOrUpdateGuildProgressResponse' could not be found (are you missing a using directive or an assembly reference?)


TEST 3
(based on your reply)

  • Rename all Spec/*.json swagger files to Spec/Client/guild.json
  • In Dockerfile: ARG SWAGGER_JSON=guild.json
  • Delete any previous com.AccelByte.SDK.Custom output folder

This time, no error messages and the Models/ code file is there!

com.AccelByte.SDK.Custom
├───Editor
│
└───Runtime
    │
    ├───Api
    │       Guild.cs
    │       GuildApi.cs
    │
    ├───Core
    │       AccelByteCustomPlugin.cs
    │       AccelByteServerCustomPlugin.cs
    │       CustomClientConfig.cs
    │       ServerCustomClientConfig.cs
    │       
    ├───Models
    │       AccelByteGuildModels.cs
    │
    └───Server
            ServerGuild.cs
            ServerGuildApi.cs

My guess is perhaps something to do with file length, but more likely having two periods in the filename.

Hope this helps!

Chris

As for why I ended up with guildServices.swagger.json as the name, it was something I picked up in example code or docs and stuck with. I don’t remember where and can’t find it.

We’ll try to track that document down and update its wording to reduce confusion.

If you then run the make all command, you should get this error:

This is why I thought that those files might need these specific names.

Yes, I do agree, the error wording needs to be improved.

If you run the make all command again, it completes without error messages but the com.AccelByte.SDK.Custom/Runtime/Models folder is missing so the API has type errors:

This is something we need to investigate further, the desired behavior would be for it to fail loudly (during code-generation), there shouldn’t be a case where it only partially produces the correct files.

This time, no error messages and the Models/ code file is there!

We are glad we have finally unblocked you, feel free to reach out whenever you have concerns or feedback.

edit: wording