Skip to content

Unity client sdk #1105

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

Open
wants to merge 76 commits into
base: master
Choose a base branch
from
Open

Conversation

Fellmonkey
Copy link
Contributor

What does this PR do?

This PR adds comprehensive Unity SDK support to the SDK generator by:

  1. Unity Language Implementation: Introduces a new Unity language class (src/SDK/Language/Unity.php) that extends the base Language class, providing Unity-specific type mappings, keywords, and code generation logic for C# in Unity environment.

  2. Unity Template System: Adds a complete set of Unity-specific templates under templates/unity/Assets/ including:

    • Runtime components (Client, Services, Models, Enums, etc.)
    • Editor tools (Setup Assistant, Setup Window)
    • Unity project files (assembly definitions, project settings)
    • Required .NET libraries for Unity compatibility
  3. Automated Testing Integration: Introduces Unity2021 test support with:

    • Unity2021Test.php test class that integrates with the existing test framework
    • Unity test source files (Tests.cs, Tests.asmdef) for comprehensive SDK testing
    • Docker-based Unity CI testing using unityci/editor:ubuntu-2021.3.45f1-base-3.1.0
  4. CI/CD Integration: Updates the GitHub Actions workflow to:

    • Include Unity2021 in the test matrix alongside other SDK platforms
    • Set up the UNITY_LICENSE environment variable for Unity Editor automation
    • Enable automated testing of the Unity SDK in the CI pipeline
  5. Unity Project Structure: Implements proper Unity package structure with:

    • Assets organized under Assets/Runtime/ and Assets/Editor/
    • Required Unity project settings and manifest files

Test Plan

The testing strategy includes:

  1. Unit Testing: The Unity2021Test.php runs comprehensive tests covering:

    • HTTP operations (GET, POST, PUT, PATCH, DELETE)
    • File upload functionality with different file types
    • Error handling and exception management
    • OAuth2 authentication flow
    • Query helper methods
    • Permission and role management
    • ID generation utilities
  2. Docker-based CI Testing: Tests run in a controlled Unity environment using:

    • Unity Editor 2021.3.45f1 in headless mode
    • Automated license activation using secrets
    • PlayMode test execution with filtered output
    • Integration with the existing mock API server

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

Yes

Moved Unity SDK template files from 'templates/unity/Runtime' and 'templates/unity/Editor' to 'templates/unity/Assets/Runtime' and 'templates/unity/Assets/Editor' for better alignment with Unity project conventions. Updated getFiles() in Unity.php to reflect new paths and added support for copying plugin DLLs and project settings. Improved file upload logic in Client.cs.twig to handle streams and byte arrays more robustly, and removed Unity-specific logging from Exception.cs.twig. Minor fixes in Realtime.cs.twig and Role.cs.twig for namespace and async handling.
Introduces Unity2021 test support by adding a Unity2021Test.php, Unity test source files, and updating the GitHub Actions workflow to include Unity2021 in the test matrix and set the UNITY_LICENSE environment variable. This enables automated testing for the Unity SDK within the CI pipeline.
@Fellmonkey
Copy link
Contributor Author

I am also attaching instructions on how to obtain a Unity license painlessly.
manual

@Fellmonkey
Copy link
Contributor Author

The basic functionality tested in the test is guaranteed to work, but I'm not sure about the rest. I will continue to refine it.

Also, a question: What to implement next for the client SDK?

@Fellmonkey
Copy link
Contributor Author

Fellmonkey commented Jul 11, 2025

The test failed because the secret is not configured in appwrite/sdk-generator.
{90B0C66F-3E43-439F-8158-11FB0AE9AA1C}

The successful test is here:
https://github.com/Comanda-A/sdk-generator-b/actions/runs/16206122996/job/45756699934
{B8C80D49-D1B7-481B-8359-B8378156B653}

@Fellmonkey
Copy link
Contributor Author

// Cookie support
client.SetCookie() / client.GetCookie()

// Real-time subscriptions  
realtime.Subscribe(channels, callback)

// Connection testing
await client.Ping()

The successful test is here:
https://github.com/Comanda-A/sdk-generator-b/actions/runs/16240261125/job/45855715029

Copy link
Member

@abnegate abnegate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, first of all, awesome work! Really appreciate the effort and attention to detail here. A couple more comments:

  • We have lots of duplication with the server-side .NET SDK, can we extend that instead?

  • We are targeting Unity 2021, which is now end-of-life. Can we move to 2022 LTS or even 6.0 LTS?

  • I couldn't see any code that handles navigating back into the game and storing the cookie from the OAuth path, can you point me to it?

  • Bit confused on how to set up the license. The instructions linked mention that it needs to be generated on the same machine that will run the tests, but that won't be the case if we generate with the linked action, set a repo secret, then run tests in a different action.

Comment on lines 144 to 168
/// <summary>
/// Initialize OAuth2 authentication flow
/// </summary>
/// <param name="provider">OAuth provider name</param>
/// <param name="success">Success callback URL</param>
/// <param name="failure">Failure callback URL</param>
/// <param name="scopes">OAuth scopes</param>
/// <returns>OAuth URL for authentication</returns>
public string PrepareOAuth2(string provider, string? success = null, string? failure = null, List<string>? scopes = null)
{
var parameters = new Dictionary<string, object?>
{
["provider"] = provider,
["success"] = success ?? $"{_endpoint}/auth/oauth2/success",
["failure"] = failure ?? $"{_endpoint}/auth/oauth2/failure"
};

if (scopes is { Count: > 0 })
{
parameters["scopes"] = scopes;
}

var queryString = parameters.ToQueryString();
return $"{_endpoint}/auth/oauth2/{provider}?{queryString}";
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we abstract OAuth from the client into a WebAuthComponent, for consistency with Android/Apple SDKs

Comment on lines 170 to 186
/// <summary>
/// Get the current session from config
/// </summary>
/// <returns>Current session token or null</returns>
public string GetSession()
{
return _config.GetValueOrDefault("session");
}

/// <summary>
/// Get the current JWT from config
/// </summary>
/// <returns>Current JWT token or null</returns>
public string GetJWT()
{
return _config.GetValueOrDefault("jwt");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these values persisted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, yes, but I'm not sure it's worth keeping jwt

Comment on lines +98 to +115
#if UNI_TASK
/// <summary>
/// Sends a "ping" request to {{ spec.title | caseUcfirst }} to verify connectivity.
/// </summary>
/// <returns>Ping response as string</returns>
public async UniTask<string> Ping()
{
var headers = new Dictionary<string, string>
{
["content-type"] = "application/json"
};

var parameters = new Dictionary<string, object?>();

return await Call<string>("GET", "/ping", headers, parameters,
response => (response.TryGetValue("result", out var result) ? result?.ToString() : null) ?? string.Empty);
}
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a non-unitask implementation too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I tried to use tools that don't limit work on different platforms right away. Now Unity has an analogue of Awaitable from version 2023, but I know that many people are still using 2021 and 2022, so I decided to do it this way.

Comment on lines 32 to 33
case JsonTokenType.StartArray:
return JsonSerializer.Deserialize<object[]>(ref reader, options)!;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to recurse to handle array sub-types?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but I have already created a PR to improve the converter. #1138

@abnegate abnegate self-assigned this Aug 1, 2025
Added support for saving, loading, and deleting cookies using PlayerPrefs and JSON serialization. Improved domain and path matching logic, expanded Set-Cookie header parsing to handle SameSite and Max-Age attributes, and ensured expired cookies are cleaned automatically. The Cookie class now includes a SameSite property, and cookie management methods trigger persistence updates.
Implements saving, loading, and deleting session and JWT tokens using PlayerPrefs for persistent storage. Session data is now automatically loaded on Client initialization and saved/cleared when relevant headers are set or removed. Refactored request creation logic for JSON requests into a dedicated method.
@Fellmonkey
Copy link
Contributor Author

Hello, @abnegate

  • We have lots of duplication with the server-side .NET SDK, can we extend that instead?

Converters enum models extensions can be taken directly from dotnet (I don't think I changed anything). The rest of the files Id, Roles, etc.
The services can also be taken, but there is one difference with(Task -- UniTask). I don't have any ideas yet on how this could be implemented.

  • We are targeting Unity 2021, which is now end-of-life. Can we move to 2022 LTS or even 6.0 LTS?

As I said in my reply to UniTask, I was developing a general solution, which also applies to Unity versions. It is possible to change the CI, but there is no point. I work with the SDK on Unity version 6 and there are no errors or warnings about using old methods.

  • I couldn't see any code that handles navigating back into the game and storing the cookie from the OAuth path, can you point me to it?

I have a code locally, but I haven't tested it yet.

  • Bit confused on how to set up the license. The instructions linked mention that it needs to be generated on the same machine that will run the tests, but that won't be the case if we generate with the linked action, set a repo secret, then run tests in a different action.

Yes, it's quite confusing. I found the official answer, which is easier to understand. The main thing is to run the script in any repository, get the .alf file (follow the instructions to get the .ulf file) and put the .ulf file in secret.

{069A79A5-D29A-4C55-97B2-7C27529B2A05}

@Fellmonkey
Copy link
Contributor Author

Hey, first of all, awesome work! Really appreciate the effort and attention to detail here. A couple more comments:

  • We have lots of duplication with the server-side .NET SDK, can we extend that instead?

The Unity and DotNet SDKs use common elements from shared. The only difference is that each SDK has its own client. Also, necessary items for the client SDK.

I think I'll send this branch to PR when PR unity is accepted or in the near future (if dotnet is going to be changed, it will be done in shared).
Fellmonkey#9

[
'scope' => 'default',
'destination' => 'Assets/Runtime/Core/ID.cs',
'template' => 'unity/Assets/Runtime/Core/ID.cs.twig',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Fellmonkey ,
Really great work here.
Just wanted to point out an easy fix for these files that can be shared with the .NET SDKs, for these files that have no changes, you can directly use the template from .Net SDKs if they have no changes in them. That way you don't need to duplicate or do any massive refactor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can implement the change you’re suggesting, but in my opinion it loses the generated project’s structure clarity.
The current “structural stubs + shared includes” approach makes it easy to see where each file belongs and to expand the structure for other C# frameworks in the future.
If this structural visibility is indeed not important for the project, I can switch to the direct referencing approach — but personally, I find the current pattern more maintainable and extendable.

Introduces OAuth2 authentication flow and deep link handling for Unity (Editor, WebGL, iOS, Android) via a new WebAuthComponent. Adds cookie management with persistent storage and WebGL credentials support. Updates code generation templates to support new authentication, cookie handling, and platform-specific logic. Adds AndroidManifest.xml for OAuth deep link support and WebGLCookies.jslib for WebGL credential patching.
Extended the Unity service template to include 'general' services for extension imports. Removed OAuth2 related test cases and responses from Unity2021Test.php and Tests.cs, reflecting changes in service requirements.
stable

Introduces OAuth2 authentication flow and deep link handling for Unity (Editor, WebGL, iOS, Android) via a new WebAuthComponent. Adds cookie management with persistent storage and WebGL credentials support. Updates code generation templates to support new authentication, cookie handling, and platform-specific logic. Adds AndroidManifest.xml for OAuth deep link support and WebGLCookies.jslib for WebGL credential patching.
@Fellmonkey
Copy link
Contributor Author

OAuth functionality has been added and tested on Web and Android platforms.

While implementing this feature, I accidentally ended up creating a small Unity Playground, so you can now try out the functionality directly in your browser.

Repositories:

@Fellmonkey Fellmonkey requested a review from abnegate August 9, 2025 19:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants