Tuanjie Plugin Integration Guide

Tutorial

Prerequisite

Installing Tuanjie

GamePix Tuanjie Plugin officially supports the following versions of Tuanjie:

  • 1.0 - 1.10

It is recommended to use the latest supported release.

To publish your game on GamePix portal you need to install Tuanjie with WebGL Build support:

Tuanjie plugin add version

Obtaining the project

Download our sample project from here

This is a fully functional game designed to help you getting started with Tuanjie and GamePix plugin.

Installing GamePix plugin

  • Download latest version of GamePix plugin for:
  • Tuanjie 1.0 - 1.10
  • Extract the contents of this archive inside the sample project's Assets folder.

At the end, the plugin should be in the Assets/Plugins/GamePix directory.

Using the Plugin

Building the project

Open the project in Tuanjie and then switch the platform to WebGL in "Build Settings".

Tuanjie plugin switch platform

IMPORTANT: Ensure that there are no errors in Tuanjie console. If you have some, please fix them before going forward.

It's also recommended to update all your packages to their recent versions.

Set default canvas width and height for the game (Menu "Edit" -> Project Settings -> Player -> Resolution and Presentation).

Resolution and presentation

Default canvas width and height will be used to calculate the game aspect ratio.

IMPORTANT: In browser the size of the game canvas will change automatically depending on the screen size, but the aspect ratio value will remain constant.

If GamePix plugin was correctly installed, then the Tuanjie Editor will show the GamePix menu item.

Tuanjie plugin GamePix menu

IMPORTANT: Recommended to make a backup copy of the project or use a version control system.

IMPORTANT: Before build make sure that there are no important data in the folder html5. It will be cleared.

Gamepix plugin will change texture and sound settings for WebGL platform to ensure their maximum quality. All previous settings for all textures and sounds for WebGL platform will be lost.

Overridable settings for other platforms will remain unchanged.

Press Build and Run from the menu.

Tuanjie plugin build and run

If needs to save your texture and sound settings for WebGL, select for build:

  • GamePix>Safe builds->Build and Run (No override textures\sounds)

However this is not recommended, because the quality of the game may be insufficient.

You should wait until the build process is finished. It may take a long time. However, at the end of the build process Tuanjie will automatically start the browser with your game. Please check that the game works correctly in the browser.

Tuanjie plugin build result

Publishing the project

After a successful build, the archive with the game will be placed in the folder html5 and will have a name like CompanyName_GameName_GameVersion.gpx.

Open the GamePix dashboard and follow the instructions to publish gpx archive. Don't worry that the file is very big, the game will be optimized and minified by GamePix publishing system.

Integrating GamePix SDK

The GamePix game SDK provides a series of utility methods needed for running your game in the GamePix ecosystem. They enhance the user experience of your game and complete the integration with our ads network and revenues system. We assume that you already read the SDK Documentation.

Automatic integration

GamePix Tuanjie plugin will try to automate everything as much as possible. The below features will be automatically integrated, do not try to integrate them manually:

  • Build will already have the latest SDK linked to it
  • Game lifecycle is managed by the plugin: it configures window.GamePixConfig and reports loading progress (GamePix.lifecycle.loading), readiness (GamePix.lifecycle.loaded) and gameplay start (GamePix.lifecycle.gameStart). No developer action is required.
  • pause and resume events (GamePix.events.on('pause' | 'resume')) are handled by the plugin, see Pause.

Manual integration (Optional)

Inside the plugin SDK features are logically structured and put inside Gpx global object. You may need to manually integrate:

  • Gpx.CurrentLanguage - gets the current preferred language by the player
  • Gpx.Ads.InterstitialAd - request to show interstitial advertisement
  • Gpx.Ads.RewardAd - request to show reward advertisement
  • Gpx.Events.UpdateScore - deprecated, kept for existing games only; new games should not use it
  • Gpx.Events.HappyMoment - should be called on a positive moment: high score, achievement, boss defeat, big win
  • Gpx.Events.SadMoment - should be called on a negative moment: death, failure, timeout
  • Gpx.User - player login with Xsolla ID, see User

The sample project already uses some of this features in Assets/Scripts/Gameplay/PlayerEnteredVictoryZone.cs

Pause

Interstitial and reward ads require the game to be paused, but browsers can't completely block the main thread, like on other platforms.

The plugin pauses Tuanjie time-dependent event (animations, time-dependent moves, coroutines, etc) and sounds internally.

If needs to pause time-independent functions, you can use bool value (read-only):

Code
Gpx.IsGamePaused

which shows that an ad is being displayed.

For example, the following code pauses the rotation while an ad is running:

Code
public class SampleScript : MonoBehaviour
{
    [SerializeField] private float tilt;

    private void Update()
    {
        if (Gpx.IsGamePaused)
        {
            return;
        }

        transform.Rotate(Vector3.up * tilt);
    }
}

Interstitial Advertising

The Interstitial ad should be shown periodically, for example: you can show this ad when the player finishes the level.

The InterstitialAd method has two optional arguments: onSuccess callback, called when the ad was shown, and onFail callback, called in all other cases. You can omit them and use it like this:

Code
Gpx.Ads.InterstitialAd();

Another example with callback:

Code
using GamePix;
using Platformer.Core;
using Platformer.Mechanics;
using Platformer.Model;

namespace Platformer.Gameplay
{
  // <summary>
  // This event is triggered when the player character enters a trigger with a VictoryZone component.
  // </summary>
  // <typeparam name="PlayerEnteredVictoryZone"></typeparam>
  public class PlayerEnteredVictoryZone : Simulation.Event<PlayerEnteredVictoryZone>
  {
      public VictoryZone victoryZone;

      PlatformerModel model = Simulation.GetModel<PlatformerModel>();

      public override void Execute()
      {
          // show interstital ads
          Gpx.Ads.InterstitialAd(OnInterstitalAdSuccess);

          model.player.animator.SetTrigger("victory");
          model.player.controlEnabled = false;
      }

      private void OnInterstitalAdSuccess()
      {
          Gpx.Log("Interstitial advertising was shown successfully");
      }
  }
}

IMPORTANT: If the message "[GPX] Interstitial ad already called" is displayed, the function is called multiple times before the ad is displayed. This needs to be fixed.

Reward Advertising

The Reward ad should be used when you want to reward the player after watching an ad. The RewardAd method takes onSuccess callback and optional onFail callback. onSuccess is called when the ad is watched to the end and onFail is called in all other cases. Grant the reward only in onSuccess.

The optional third argument prompt (default false) shows a confirmation popup ("Want to see the video to get rewarded?") before the ad is requested. If the player chooses No, the ad is not requested and onFail is called.

Use prompt only when the reward ad is started without an explicit player choice. If the game already has its own "Watch ad for reward" button, keep prompt as false.

Code
Gpx.Ads.RewardAd(OnRewardAdSuccess, OnRewardAdFail, prompt: true);

Example of using RewardAd:

Code
public void ShowRewardAd()
{
    Gpx.Ads.RewardAd(OnRewardAdSuccess, OnRewardAdFail);
}

private void OnRewardAdSuccess()
{
    Debug.Log("Reward received");
    GiveReward();
}

private void OnRewardAdFail()
{
    Debug.Log("Reward not available. Try again later.");
}

IMPORTANT: If the message "[GPX] Reward ad already called" is displayed, the function is called multiple times before the ad is displayed. This needs to be fixed.

Happy and Sad moments

Call HappyMoment when something good happens to the player (high score, achievement, boss defeat, big win) and SadMoment when something bad happens (death, failure, timeout):

Code
Gpx.Events.HappyMoment();
Gpx.Events.SadMoment();

User

GamePix authenticates players with Xsolla ID. user.id is unique and stable, use it as the player key on your own backend. A guest must always be able to play.

  • GetUser - returns the current user and Xsolla ID token. Never shows UI, safe at startup. A guest gets code 401.
Code
Gpx.User.GetUser(auth =>
{
    if (auth.success)
    {
        ShowPlayerName(auth.user.name);
    }
});
  • RequestLogin - opens the GamePix login window. Call it only from a click or tap handler (browsers block windows not opened by a user action). Code 200 when logged in, 401 when cancelled.
Code
public void OnLoginButtonClicked()
{
    Gpx.User.RequestLogin(auth => { /* same result as GetUser */ });
}
  • ShowBackpack - opens the player's Xsolla Backpack (the same card as in the GamePix user menu). Call it from a player action, for example an "Inventory" button. It does not show the login: a guest gets code 401, call RequestLogin first and then ShowBackpack again. The card does not pause the game (pause it yourself if needed), and there is no event when the player closes it. Code 200 when the Backpack is open (or was already open), 404 when it is not available (outside GamePix, on a partner site, or not enabled).
Code
public void OnInventoryButtonClicked()
{
    Gpx.User.ShowBackpack(result =>
    {
        if (result.code == 401)
        {
            Gpx.User.RequestLogin(auth =>
            {
                if (auth.success) Gpx.User.ShowBackpack(OnBackpackResult);
            });
            return;
        }
        OnBackpackResult(result);
    });
}

void OnBackpackResult(BackpackResult result)
{
    if (!result.success) ShowMessage("Inventory not available");
}
  • OnAuthChanged - fires when the token was renewed or the player logged in/out outside of your calls.
Code
Gpx.User.OnAuthChanged += auth => { if (!auth.success) SwitchToGuestMode(); };

Codes: 200 authenticated, 401 guest / cancelled, 404 not inside the GamePix Player, 408 the Player did not answer in time.

Testing in the Tuanjie Editor. The Editor simulates the GamePix Player: the player starts as a guest (401), RequestLogin opens a login window where you can edit the test account (name, nickname, username, id, guest) and press Log in (Enter) or Cancel (Esc). The game keeps running while the window is open, like in the real Player. The token is fake and expires in 30 minutes. Set GamePix.User.UnityUser.IsLoggedIn = true to start logged in, or change UnityUser.TestUser from code. ShowBackpack always returns 404 in the Editor.

IMPORTANT: The token is a credential: send it only to Xsolla APIs or your own backend over HTTPS, never log it or save it to PlayerPrefs. Call GetUser every time you need it, the SDK caches and renews the token.

Troubleshooting

Too large WebGL data file

Use for build:

  • GamePix>Safe builds->Build and Run (Compressed textures\sounds)

All textures (except NPOT) and sounds will be lossy compressed. NPOT textures can be compressed after the scale to power-of-two option is selected in Tuanjie Editor.

This will reduce quality, but may help build the game. However this is not recommended, because the quality of the game may be insufficient.

If nothing helps, you can ask GamePix support to help build your game.

Freeze

If game freezes in browser without any error in browser console, it likely run into infinite loop. You should check the code and avoid any infinite loops. Like this:

Code
if (UseOnlineTime)
{
    WWW www = new WWW(OnlineTimeUrl);
    while (!www.isDone)  {  }
}

Best Practices

Take in account that our target environment is a default mobile browser (Safari, Android Webview, etc).

Do not expect that environment will support very recent desktop related technologies.

Most common environment will be WebGL 1 without any extension. Please try to use this basic stack only.

Another important thing - target environment is Single Threaded, do not run any long-running background task.

However, all this tips are optional you should follow them to create most optimized and minified version of game.

Assets and packages

Delete all unused assets and packages.

It is highly desirable that everything not used in the game be deleted from both Assets and Packages folders.

Packages

Do not use any additional packages.

Fonts

Do not use fonts and fonts assets or fonts packages.

Exceptions

Do not use. Using "try-catch" block slows down the game a lot. This is especially noticeable in JavaScript.