<br />

With this wrapper you can access the [YouTube Playables SDK](https://developers.google.com/youtube/gaming/playables/reference/sdk) in Unity
C#. The wrapper has a .jslib plug-in and a C# file to help speed up your
development. There is also a sample project that shows how you can use these in
your project.

Unity Packages can be downloaded from our Playables [sample repo](https://developers.google.com/youtube/gaming/playables/samples/oss_samples).

## Usage

1. Verify your Unity project Platform is set to `WebGL`. This setting can is found in `Build Settings`.
2. Either use the `WebGLTemplate` to build your game for web, or follow the [Use your own index.html file](https://developers.google.com/youtube/gaming/playables/samples/unity_wrapper#use_your_own_indexhtml_file) section and verify you have [setup and initialize the web SDK](https://developers.google.com/youtube/gaming/playables/reference/sdk) in your `index.html` file.
   - `WebGLTemplate` can be found in the package `Google-WebGLTemplate-only.unitypackage` or `GoogleYTGameWrapper-with-sample.unitypackage`. To set and use this template up follow the steps in the [WebGL Template](https://developers.google.com/youtube/gaming/playables/samples/unity_wrapper#webgl_template) section.
   - To use your own Web and `index.html` file, you will need to add two lines to your `index.html` Unity creation script, see [Use your own index.html file](https://developers.google.com/youtube/gaming/playables/samples/unity_wrapper#use_your_own_indexhtml_file) section for integration.
3. Open your project in Unity, then open and import either package into your project.
   - `GoogleYTGameWrapper.unitypackage`: Contains JS Plugin for connecting the YouTube Playables SDK and a C# wrapper to help connect this to your product.
   - `GoogleYTGameWrapper-with-sample.unitypackage`: Contains the same files content as those found in GoogleYTGameWrapper package and a sample showing how to use YouTube Playables SDK in C#.
4. **IMPORTANT:** In your main scene create a new gameobject and name it `YTGameWrapper`. This game object is used to communicate with the JS bridge.
5. **IMPORTANT:** Add the imported `YTGameWrapper.cs` code as a script component to the `YTGameWrapper` GameObject.
6. If your project has multiple scenes make sure to add `DontDestroyOnLoad` to
   the `YTGameWrapper.cs` script (note: new versions of the script have a
   `DontDestroyOnSceneChange` toggle which is on by default). This will make
   sure the script and GameObject sticks around throughout your game.

       GameObject.DontDestroyOnLoad(this.gameObject);

7. The `YTGameWrapper.cs` component and `YTGameWrapper` GameObject are used to
   connect to the YouTube Playables SDK. Use these to connect to YouTube.
   Either using Script to find the object and component or manually add these
   to your game code through the Unity Editor.

8. Verify you are following [technical requirements](https://developers.google.com/youtube/gaming/playables/certification/requirements_integration) for your
   project.

## Use your own index.html file

If you don't use the `index.html` example provided you will need to add two
lines of code to your `index.html` Unity creation script.

First, add this line in the same place your project sets up variables for the
Unity container, canvas, etc.

        var container = document.querySelector("#unity-container");
        var canvas = document.querySelector("#unity-canvas");

        var unityGameInstance = null; // <-- Add this line >

        ...

Second, inside the `createUnityInstance` function add this line.

        createUnityInstance(canvas, config, (progress) => {
            progressBarFull.style.width = 100 * progress + "%";
        }).then((unityInstance) => {

            unityGameInstance = unityInstance; // <-- Add this line >

        ...

## Examples

This section has some examples of how to use the C# wrapper, it is not the full
list of available APIs. For the full list of available APIs, refer to the
[YouTube Playables SDK](https://developers.google.com/youtube/gaming/playables/reference/sdk).

### `sendScore`

This example shows an implementation of `sendScore(int points)` in C#:

    ...
    using YTGameSDK;
    ...

    public YTGameWrapper ytGameWrapper;
    public int battleScore = 0;

    ...

    // Update the total score and send this to the YouTube Game Wrapper.
    public void UpdateScores(int scoreAmt)
    {
        battleScore += scoreAmt;
        // ytGameWrapper should be a reference to your YTGameWrapper component.
        ytGameWrapper.SendGameScore(battleScore);
    }

### `onPause`

This is an example of how a game can listen to `Pause` events coming from YT
Playables, to pause its engine when needed:

    ...
    using YTGameSDK;
    ...

    public YTGameWrapper ytGameWrapper;
    public bool gameIsPaused = false;

    ...
    void Start()
    {
        // Sets the OnPause callback with the YT Playables SDK
        ytGameWrapper.SetOnPauseCallback(PauseTheGameCallback);
    }

    // Pause game callback, will pause the game when called.
    public void PauseTheGameCallback()
    {
        gameIsPaused = true;
    }

### `saveData`

This is an example of how to use `saveData`, sending it to YT Playables SDK:

    ...
    using YTGameSDK;
    ...

    public YTGameWrapper ytGameWrapper;

    ...

    // Saves the current score of the game and converts it to a JSON format.
    public void SaveScore(int scoreAmt)
    {
        SaveGameData("{\"BestScore\": \"" + scoreAmt.ToString() + "\"}");
    }

    public void SaveGameData(string saveString)
    {
        if (string.IsNullOrEmpty(saveString)) return;

        // Sends save data to the YT Playables SDK
        ytGameWrapper.SendGameSaveData(saveString);
    }

### `loadData`

This is an example of how to use `loadData`, sending it to YT Playables SDK:

    ...
    using UnityEngine;
    using YTGameSDK;
    ...

    [Serializable]
    public class LoadedScores
    {
        public int BestScore;
        public float BestTime;
    }

    public YTGameWrapper ytGameWrapper;

    ...

    void Start()
    {
        ytGameWrapper.LoadGameSaveData(LoadSaveGameDataReturned);
    }

    public void LoadSaveGameDataReturned(string data)
    {
        if (!string.IsNullOrEmpty(data))
        {
            LoadedScores loadedScores = JsonUtility.FromJson<LoadedScores>(data);
            Debug.Log("LoadSaveGameDataReturned > Score <" + loadedScores.BestScore.ToString()
                      +   "> Time <" + loadedScores.BestTime.ToString("0.00"));
        }
    }

### `requestInterstitialAd`

This is an example of how to use `requestInterstitialAd`, indicating it is a
good time to show an interstitial Ad, if available. For the best results, make
this call during a break in gameplay, for example, at the end of a level.

    ...
    using YTGameSDK;
    ...

    public YTGameWrapper ytGameWrapper;

    ...

    // At the end of a round send a request to show an interstitial Ad, if one is
    //  available an Ad will be shown and Pause Game Callback should be called.

    // EXAMPLE: send and forget
    public void RequestInterstitialAd()
    {
        ytGameWrapper.RequestInterstitialAd();
    }

    // EXAMPLE: send and react to if an Ad was shown
    public void RequestInterstitialAd()
    {
        int status = ytGameWrapper.RequestInterstitialAd();
        if (status == 0)
        {
            // Ad request was successful, do some action.
        }
    }

### `requestRewardedAd`

This is an example of how to use `requestRewardedAd`. This is used when a user
has selected to view a rewarded Ad in exchange for some reward in your game. If
an Ad is available one will be presented to the user.

    ...
    using YTGameSDK;
    ...

    public YTGameWrapper ytGameWrapper;

    ...

    public void RequestRewardedAd()
    {
        // Register callback for Rewarded Ads. If an Ad is available one will be
        //  shown. Pause Game Callback should be called. Any ID is fine as long as
        //  its identifyable for your game.
        ytGameWrapper.RequestRewardedAd("my-reward-ad-id-123", (rewardEarned) => {
            if (rewardEarned) {
                // Rewarded Ad is earned, reward the user.
            } else {
                // Rewarded Ad not earned, take the appropriate action
            }
        });
    }

## How to use YouTube's example WebGL Template

Unless you have a very heavy Unity project your built `.wasm` and `.data` files
should be under our individual [file size](https://developers.google.com/youtube/gaming/playables/certification/requirements_stability) limit. If
this is the case no extra compression should be done on your end for these files
as they will be automatically compressed on submission of your Playable files.
This automatic compression will also verify that your .wasm file fits into the
[initial bundle size](https://developers.google.com/youtube/gaming/playables/certification/requirements_stability) requirement. As an example, a \~25
MiB `.wasm` file will compress to \~7 MiB.

If for some reason your files are over the maximum individual file size limit,
it is best to use ZIP compression to verify they fit into this limit. Playable
compression won't re-compress these files.

> [!NOTE]
> **Note:** At this time there is no support for Unity projects built with Unity's gzip or brotli compression. All projects should be built without compression then if compression is needed, it should be done after the initial build.

### WebGL Template

1. Follow the [Unity package instructions above](https://developers.google.com/youtube/gaming/playables/samples/unity_wrapper#usage) for initial setup. Make sure to use `Google-WebGLTemplate-only.unitypackage` or `GoogleYTGameWrapper-with-sample.unitypackage` and import all files under `WebGLTemplates/YTGameWrapperTemplate/` folder.
   - Note: if you have not already imported `YTGameWrapper.cs` and `UnityYTGameSDKLib.jslib` you should import those as well.
2. Set your WebGL Template to use `YTGameWrapperTemplate`. This setting is in `Edit` -\> `Project settings` -\> `Player` -\> `WebGL` tab -\> `Resolution and Presentation` section.
   - Note: Default Canvas Width and Height are set to 100% in the template so these Unity settings won't adjust anything.
3. Make sure your `Compression Format` is set to Disabled. This setting is in `Project settings` -\> `Player` -\> `WebGL` tab -\> `Publishing Settings` section.
4. Build for `WebGL` in the `Build Settings` window then go to step 7 or 5 based on your projects needs.
5. **Only follow steps 5 \& 6 if compression is used** : After your project is built navigate to your build folder location and open the `Build` folder. Find your projects `.wasm` or `.data` files that need compression to fit into the individual [file size](https://developers.google.com/youtube/gaming/playables/certification/requirements_stability) limits and zip these files. Make sure to delete the original `.wasm`/`.data` files that were compressed as you will be submitting the `*.wasm.zip` and `*.data.zip` files instead.
   - Note: if you are using a Mac you can right-click the file and select "Compress \*". On PC you can right-click the file and select "Compress to ZIP file".
6. **Only follow if you did step 5** : Update the `index.html` file built from `YTGameWrapperTemplate` to load zipped files and decompress them.
   - Near the end of the `index.html` files you will find `Path 1` and comment out the following line `InitUnitySection();`.
   - Near the end of the `index.html` files you will find `Path 2` and comment out the following line `loadResources(InitUnitySection);`.
7. When submitting your project for Certification you will need to send all files built from Unity to your build location from Step 4. If steps 5 + 6 were followed, include these files as well.

## Upgrade the provided samples to use Universal Render Pipeline (URP)

One of the latest advancements with newer versions of Unity is that they use
Universal Render Pipeline (URP). To upgrade the sample so everything renders
correctly.

1. Start by importing the `GoogleYTGameWrapper-with-sample.unitypackage` package into a new or existing project.
2. Navigate to the `Render Pipeline Converter` window: `Window` -\> `Rendering` -\> `Render Pipeline Converter`.
3. Select `Rendering Settings`, `Material Upgrade`, and `Readonly Material Converter`.
4. Next select `Initialize and Convert`, wait for this to finish and the sample should be ready for URP.

## How to break up assets in your Unity project (Lazy Loading)

One of the main problems developers have highlighted when using Unity is staying
under the individual [file size](https://developers.google.com/youtube/gaming/playables/certification/requirements_stability) requirements and the
total [bundle size](https://developers.google.com/youtube/gaming/playables/certification/requirements_stability) requirements.

Lazy loading of assets is a great optimization you can make for your project as
you can load assets, levels, and data as they are needed. Our certification team
may waive the overall file size restrictions if this is properly done, as your
full game won't be loaded up front, but as a user navigates your product.

To help with proper loading, Unity has a number of ways to split up your assets
verifying that your individual asset groups are under the size limits and that
you load content over time. We suggest using either Addressables or Asset
Bundles.

### Addressables

Addressables allow you to identify different files that should be loaded
together and Unity will handle most of the packaging for you. Unity also
provides some tools to manage file sizes and help make sure you are not
duplicating assets.

To use Addressables you will need to import the Addressables package through the
Package Manager in Unity then tag your assets into Addressable Groups. More
details can be found through [Unity documentation](https://docs.unity3d.com/Manual/com.unity.addressables.html).

### Asset Bundles

Asset Bundles are helpful as you can split up your project and load elements on
the fly. These are helpful for DLC, levels packs, new characters, and more.
Asset Bundles are great for self managed content loading and bundling. These can
be used by tagging your assets into specific bundles, then loading bundles as
you need them. More details can be found in [Unity's Asset Bundle
documentation](https://docs.unity3d.com/Manual/AssetBundlesIntro.html).

See the full [YT Playables API reference](https://developers.google.com/youtube/gaming/playables/reference/sdk#ytgame).