[Huawei Developers] shikkerimath:
View attachment 5299217

Introduction​

If you are not coming to this article from the Part 1 of the series, you can read here. This is the second part of our HMS Unity Plugin 2.0 integration guide. As you know, I wanted to talk about a part of GameService here because it requires a bit more work, not because of the plugin but because of its intrinsic nature. Adding products, managing behaviors, configuring achievements etc. take a bit more time in the AGC side. I will try to give as many details as I can give in this article; but since some of the topics are not directly related with the plugin, you may further research on how to do the tasks that I do not extensively talk about here.

I will be talking about just the Achievements parts of the GameService. However, it also has the capabilities of SaveGame and Leaderboard. You can read more about them in other articles and believe me, they are as easy to integrate as the ones I talk about, thanks to the HMS Unity Plugin 2.0.

This article also assumes that you have completed the steps in Part 1, at least the ones that are essential. GameService is already dependent on Account Kit you must check Account Kit as well from the Kit Settings menu, even if you will not use it directly in your game. (Plugin should automatically tick it for you once you tick GameService)

You do not have to integrate other kits to integrate these two kits, but some AGC side requirements are standard for all kits. I will talk about the specific parts that are about GameService here and IAP (In-app purchases) in part 3.

Without further ado, let’s get started.

GameService​

After enabling GameService in HMS Settings (aka Kit Settings) menu, a “Game Service” tab will be automatically added to the settings menu, as can be seen below in the screenshots. Now, I walk you through GameService step by step for those who want a bit of additional information.

Sign-In Function Implementation​

As I have warned in part 1, for the use of GameService, sign-in is required. This must be either done through Account Kit by yourself, or through GameService.

The easiest way to the do this is to just to check the box at the bottom of GameService tab. When you tick “Initialize On Start”, whenever users start your game, your game will try to log the user in immediately and they will see the “Welcome *username*” greeting message immediately if they logged in at least once in your game.

View attachment 5299219

In the first-ever login in your game, they will be directed to the Huawei login page automatically, which will be done at the very first opening of your app. If you choose to do this, you do not even have to implement Account Kit. That’s it, login is done and you are ready to continue with just one click.

If you opt for not checking the box because this is not a desirable in-app behavior for you, then you must initialize the GameService manually and use the Account Kit in your own logic to log the user in.

It requires a bit of code but is not hard at all. Let’s assume that you sign-in at the Start() function of your app using Account Kit. What you have to do is to implement the SignInSuccess callback. If login is successful, success callback will be automatically executed and in there, you must initialize the GameService with just one line of code.

void Start()
{
HMSAccountManager.Instance.SignIn(); //sign the user in HMSAccountManager.Instance.OnSignInSuccess = OnSignInSuccess;

//implement callback on Start()
}

private void OnSignInSuccess(AuthAccount obj)
{
HMSGameManager.Instance.Init();
}

That’s it for the manual control. Now, you control where you want to sign your users in and also initialize the GameManager so that you can use Achievements, Leaderboards and SaveGame features.

I suggest that whichever way you choose, you do this at the first scene of the app (like a main menu etc.) and not inside the game itself, so users will not be bothered by sign-in process in-game.

Achievements​

I want to add achievements to my app so when the user has done certain actions, I will reward them by unlocking some achievements. There are mainly two actions required to be done by you, the developer: First, add achievements to your app in AGC and get their ID. And second, enter the IDs to Achievements part of the plugin and implement in-game logic. That means, you need to determine where you will grant your users an achievement in your game. What kind of actions are needed to be carried out to get them?

In my case, this process is very simple. I have “Beginner, Medium and Master Scorer” achievements defined and I grant them whenever the user completes a certain score in my game. Since my game is very simple, the score is the utmost indicator of a “skilled” player, so I thought, why not?

First, let’s go to AGC (AppGallery Connect) together to add some achievements. You can go to AGC by using this link. Sign in to your developer account, click “My apps” and choose your game from the list. You will be directed to “Distribute” tab. From the left-upper bar, choose “Operate” tab instead. There, you will have “Product Management” tab opened at first from the left navigation menu, which I will use it for IAP later. Now, move to the Achievements tab to add some achievements to your game. Click Create on right to create an achievement.

View attachment 5299223

You enter a name and a description to remember what this achievement is for. You can leave “incremental achievement” unchecked because I do not need it for this simple game. Also for the “revealed, hidden” option, what I did was to make the BeginnerScorer achievement revealed and the other two are hidden. So user will see them in achievements list but will not know what they are before achieving the previous achievement. You can configure them however you like. Make sure they are fitting to your game content, so users will try to play longer to achieve them. Also, I set the same logo for every one of them but I suggest you design different icons for each and every one of your achievements.

After you are done, it should look like something like this:

View attachment 5299225

Do not release your achievements so you can test them. If you release them, they will be checked by AGC and be approved if they are proper. However, then, you cannot reset their progress even if you did not publish your game yet. Thus, to make sure that the development side works correctly, I will leave them as it is. Whenever you achieve them in your own game testing, you can just reset the progress and keep testing if you want to change something you do not like.

Now that I am done creating them, you can click “Obtain Resources” above and copy their IDs one by one. Then, paste them to our HMS Settings menu. After you copied them all, click “Create Constant Classes”, so HMS Unity Plugin can create a constant class for you.

View attachment 5299227

The constant class will be called HMSAchievementConstants. Now let’s see how can I use them. I will need the “state”s of these achievements for my game implementation because I will check the states to grant the achievements one by one. Imagine a scenario where BeginnerScorer needs 15 points and MediumScorer needs 25 points to unlock. If the user surpasses 25 points in the first game, then the game would grant them consecutively in one run. This is not what I want, so I will access the achievement states and that requires Achievement objects. You do not have to use Achievement objects, you can just use the constant class to retrieve the IDs and immediately reveal and/or unlock them.

public void TakeDamage(int damageAmount)
{
//...
if (health <= 0)
{
//...
//Player is dead
losePanel.SetActive(true);
HMSAchievementsManager.Instance.GetAchievementsList();
}
}

Remember my TakeDamage function shown above. Since I will be unlocking achievements when the game is done, I will call my GetAchievementsList() function after the player dies. This function is necessary because it has several callbacks that which I will use. You should decide to call this function depending on your game logic and code structure. As I always do, I tell my structure in detail so you can project where you should put yours.

void Start()
{
//... HMSAchievementsManager.Instance.OnGetAchievementsListSuccess = OnGetAchievemenListSuccess;

HMSAchievementsManager.Instance.OnGetAchievementsListFailure = OnGetAchievementsListFailure; //optional
}

In the Start() function of wherever you will call GetAchievementsList() function, do as above. Basically, you are registering the these callbacks so when getting the achievements list is successful, the OnGetAchievemenListSuccess that you will write will be triggered. Failure callback is optional, you can track the errors and add some user warning if you like.

using System.Linq;
private void OnGetAchievemenListSuccess(IList<Achievement> achievementList)
{
//Implement your own achievement system here...
//Achievement beginnerScorer = achievementList[3]; -> Same thing as the line below
Achievement beginnerScorer = achievementList.First(ach => ach.Id == HMSAchievementConstants.BeginnerScorer); //Score of 15 is needed
Achievement mediumScorer = achievementList[4]; //Score of 25 is needed
Achievement masterScorer = achievementList[5]; //Score of 50 is needed
if (score >= 15 && beginnerScorer.State != 3)
{
HMSAchievementsManager.Instance.UnlockAchievement(beginnerScorer.Id);
//HMSAchievementsManager.Instance.UnlockAchievement(HMSAchievementConstants.BeginnerScorer); -> same as above
HMSAchievementsManager.Instance.RevealAchievement(mediumScorer.Id);
}
else if (score >= 25 && beginnerScorer.State == 3 && mediumScorer.State != 3)
{
HMSAchievementsManager.Instance.UnlockAchievement(mediumScorer.Id);
HMSAchievementsManager.Instance.RevealAchievement(masterScorer.Id);
}
else if (score >= 50 && mediumScorer.State == 3 && masterScorer.State != 3)
{
HMSAchievementsManager.Instance.UnlockAchievement(masterScorer.Id);
}
}

private void OnGetAchievementsListFailure(HMSException obj)
{
Debug.Log("OnGetAchievementsListFailure with code: " + obj.ErrorCode);
}

Let me explain the code above. It may look a bit complicated but it is not hard to understand. Since I registered to my callbacks, I need to implement them now. You need to implement the this callback yourself, so users can unlock achievements.

As I said, since I need the states, I use the objects of Achievement class. Normally, if I were not to care about the states, I would not even need them. I would just do:

HMSAchievementsManager.Instance.UnlockAchievement(HMSAchievementConstants.BeginnerScorer);

So, if you do not need states or other properties of Achievement class, you can also do the same. Your development cost is much less this way, thanks to the plugin. As you see, you do not even need to copy the long IDs to wherever you want to use them, you can just call constants class and use the IDs by the name you gave to them.

In the following part of the code, I get my achievements one by one from the callback parameter. A list already returned to me and I can pick what I want. Since I previously added 3 more achievements that I did not show you, my ordinal numbers start from 4. (you can check AGC console screenshot above)

Achievement beginnerScorer = achievementList.First(ach => ach.Id == HMSAchievementConstants.BeginnerScorer); //15 score is needed

Achievement mediumScorer = achievementList[4]; //25 score is needed

What I do is to get to the (4–1)rd index to get my beginner achievement. You can always match the indices of the achievements from the AGC console ordinals. There is also another way. If you import System.Linq, you can also use First function to get the achievements without using index numbers. Example is shown above. This is just to provide some alternatives for you.

In the rest of the code, I check the states and if they are not unlocked yet, or surely unlocked in the next step, I unlock my achievements. Since I made the other two achievements hidden, I also reveal them when the user unlocks the previous achievement. It is all under my control, so you can code your own logic however you like.

Also notice that I use the instance of HMSAchievementsManager when revealing and unlocking achievements. No further code required to call this because plugin handles the other cumbersome processes for you.

Achievements are done. You can see how I have become the master of my own game.

View attachment 5299229

One little thing is left though. Users should be able to see what kind of achievements are there even if they are hidden. (It will be shown as hidden)

View attachment 5299231

AppGallery already provides an interface for this, thus, if you want to implement this functionality you can just call one line function.

public void ShowAchievements()
{
HMSAchievementsManager.Instance.ShowAchievements();
}

Since I use a button click to call this function, I put the code in another local function. Depending on your requirements, you can call it directly.

Tips & Tricks​

There are certain other callbacks related to the kits that you use through plugin. I did not talk about them because they were irrelevant for my use case. You can always check them with IntelliSense suggesting while coding. It should suggest available callbacks after Instance.

Conclusion​

I have integrated simple achievements to my game so that users could spend more time in my game. You can adjust the details I provided for your use case and devise a scenario that works for you.

I hope that this article has been helpful for you. You can always ask questions below, if you have anything unanswered in your mind.

The only remaining kit is IAP and it will talked about here, the part 3.

See you there!

References​

HMS Unity Plugin 2.0 Branch (Github Page)

Documentation of every single kit in Huawei Docs (Links are present in the GitHub readme)

Checkout in forum