Unity Client vs IClient

We have been using the Unity SDK and have been storing the Nakama client in a IClient client and not a Client client. Note the extra I. Is there any difference when calling all the SDK methods on the IClient instead of Client? The docs don’t seem to mention this at all. The only place where I see an API difference in our code is:

  • ListUserGroupsAsync
  • ListGroupUsersAsync

The IClient versions are trivial and only accept a session and user id, but the Client versions require more parameters. These don’t seem to be documented anywhere though.


The reference docs at .NET/Unity - Heroic Labs Documentation only mention the simple versions.

Or am I understanding this wrong and should be using all functionality via the IClient interface and all the details will be handled for me? The IClient version is:

    Task<IApiUserGroupList> ListUserGroupsAsync(
      ISession session,
      int? state = null,
      int limit = 1,
      string cursor = null,
      RetryConfiguration retryConfiguration = null,
      CancellationToken canceller = default (CancellationToken));

But do I then get any retry functionality at all? The sample code always uses:

var client = new Nakama.Client("http", "127.0.0.1", 7350, "defaultKey");

so it accesses all functionality via a Client instance. But in that case the ListUserGroupsAsync and ListGroupUsersAsync example code would not work, as it’s missing most parameters.

Hello,

IClient is an interface and Client is its only implementation so the methods available in both are identical. Whether you declare your client with type IClient or Client, the execution will be always that of Client . What you list as API difference ListUserGroupsAsync and ListGroupUsersAsync are different methods available in both the interface and the implementation.

As for overloads (simple vs more complex versions of the same function), again these are both available in the API, it’s just the documentation doesn’t give examples with all the variations.

Finally for retry behaviour you can pass new RetryConfiguration(100, 5) to either the method you’re calling or set it globally on your client with client.GlobalRetryConfiguration = …

Hi,

Yeah, I know the two methods are different, one for getting a user’s groups and then a group’s users. But those were the only ones that needed to be changed when called though a Client instance, the simple versions are not available. So for those case I need to understand what these parameters do:

      int? state = null,
      int limit = 1,
      string cursor = null,

The limit is probably the max number of results to fetch. A cursor could be related to pagination? But the state parameter is not clear.

Hm, I think the issue is that IClient has default values for all these undocumented parameters while Client has not. I can of course see that defaults IClient uses and copy those and then supply an own RetryConfiguration.

I’m confused @chakie - both the IClient and Client signatures are identical:

If you are asking for why they aren’t documented, we should look at improving this documentation (in the concept section - cc @sean plz);

In the meantime:

limit - is the number of records to return between 1 and 100.
cursor - is for pagination sakes, depending on how many records there are and the limit provided. If there is no more records, the returned results won’t have a cursor.
state - is for filtering purposes of the relations you are looking for - see this:

@Sean plz let’s reflect the state (for all APIs) in the concept docs, and also a general doc on how to do pagination and limit as they are the same across all APIs.

I’m most likely confused, or at least partially. But it seems the Client version does not have default values for everything, which is also shown in your snippets.

As there are no reference docs, my go to method is to check the decompiled sources:

vs

As all the samples seem to use Client I thought we should too to take advantage of the retry stuff as it has a public RetryConfiguration GlobalRetryConfiguration which I assume is used for everything unless I supply an own RetryConfiguration.

But yeah, the lack of correct documentation is what I have most troubles with, as well as the existing docs being pretty unorganized. But it seems the C# classes all have at least some API docs, why isn’t that on the homepage or at least included in the SDK? I’m pretty sure many that use Nakama aren’t even aware of the fact that everything is on GitHub. I didn’t even think to look. The SDK includes some Powerpoint slides and a 3 page PDF.

Yep understood. We are actively working on this.

As there are no reference docs, my go to method is to check the decompiled sources:

This link isn’t published but should be online soon:
https://dotnet.docs.heroiclabs.com/html/index.html

Also we are working on a v2 of our docs, I’m gonna leave a link here - but please note that this is super Alpha and things haven’t been polished or finalised yet:

https://heroiclabs.com/docs2/nakama/client-libraries/unity/
https://heroiclabs.com/docs2/nakama/concepts/groups/#list-a-users-groups

If you have feedback about the navigation and discoverability, I’m all ears to improve :slight_smile:

The API docs look fantastic, exactly what I want! Generated from the sources that are already documented instead of kept up to date separately. Great work!

The other docs also look clearer visually, but the same organizational issue still remains. You basically have two “table of contents” per page. One on the left side and one on the right. As some of the topics are huge a small subsection on the left can lead to a massive page with a long right side ToC. So searching for something means searching both the left and the right side ToC:s.

Having the tabs on the top of the page to split up the server, client, tutorials etc makes navigation easier and is a good change. I think you’re making the docs a lot better here.

The other docs also look clearer visually, but the same organizational issue still remains. You basically have two “table of contents” per page. One on the left side and one on the right. As some of the topics are huge a small subsection on the left can lead to a massive page with a long right side ToC. So searching for something means searching both the left and the right side ToC:s.

We’ve tried to reduce the content on the left sidebar, by dividing the content into subsections top-level.

Do you have a suggestion how to improve this further?

The Go function reference doesn’t really work right now: Go - Heroic Labs's Documentation

The Table of Contents on the right side does seem to bold functions as I scroll down, but the list itself doesn’t scroll. This is what it looks like after I scroll down a bit:

The ToC hasn’t scrolled at all and isn’t interactive in any way. It’s basically impossible to find anything without the browser’s own find functionality.

Right now I’m looking at the docs for StorageDelete and the return value is:

An optional error value if an error occurred.

That isn’t really helpful. What is considered an error? Which errors are “crash and burn” errors and which can be retried later and which can be ignored? If I delete something that doesn’t exist, is that an error? The object didn’t exist which means it could be an error, but after the call is done there is no such object anymore which is what I wanted and that’s not an error. Having to test things to figure out return values is not a nice developer experience.