> For the complete documentation index, see [llms.txt](https://docs.ayetstudios.com/v/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ayetstudios.com/v/product-docs/offerwall/plugins-and-wrappers/unity.md).

# Unity

The ayeT-Studios Unity SDK allows you to easily monetize your app and reward your users with in-app currency. Your users get access to our offerwall, allowing them to earn virtual currency.

{% hint style="info" %}

### Updates History

**2022-04-25: v1.8** - Updated to latest Android & iOS SDKs, fixed some warnings, based on Unity&#x20;

**2021 2020-06-11: v1.7.1** - Updated documentation to introduce new parameters to differentiate chargebacks from conversions&#x20;

**2020-07-29: v1.7** - Updated to latest Android & iOS SDKs, based on Unity 2019 LTS **2019-07-19: v1.6** - Updated wrapper & SDKs with adslot changes, recompiled iOS SDK with Swift 5&#x20;

**2019-02-01: v1.5** - Fixed conversion tracking issues under certain conditions (application lifecycle monitoring improved)&#x20;

**2018-12-04: v1.4** - Updated to Android SDK 3.0 - support for API 26+ build targets, bugfixes & improved handling under poor network conditions&#x20;

**2018-09-29: v1.3** - Updated iOS SDK to Xcode 10 and Swift 4.2, stripped debug symbols&#x20;

**2018-07-09: v1.2** - Removed Simulator Code from iOS SDK, fixed iTunes validation issues with Xcode 9+&#x20;

**2018-07-02: v1.1** - Updated Unity SDK (iOS) to Unity 2018 / Swift 4.1 / XCode 9.4, added post-install script for automatic XCode configuration&#x20;

**2018-01-20: v1.0** - Initial Release of our Publisher SDK (Unity)
{% endhint %}

## Eligible Placement & AdSlot Combinations <a href="#eligible-placement-and-adslot-combinations" id="eligible-placement-and-adslot-combinations"></a>

The below table shows all Placement & AdSlot Type combinations that allow you to utilize the Unity SDK integration.

| Placement Type | AdSlot Type | Eligible Integration Type |
| -------------- | ----------- | ------------------------- |
| Android App    | Offerwall   | Unity SDK                 |
| iOS App        | Offerwall   | Unity SDK                 |

{% hint style="danger" %}
If you integrate the Unity SDK while using a different Placement & AdSlot combination in the ayeT-Studios dashboard, you won't be able to initialize the Offerwall.
{% endhint %}

## Getting Started

Before you start with the integration, make sure you have:

* [x] Created an Account
* [x] Added a Placement
* [x] Added an AdSlot

You will find more details here:

{% content-ref url="/pages/W7CE6bNya8L7RoaXXY21" %}
[Dashboard Setup](/v/product-docs/dashboard-setup.md)
{% endcontent-ref %}

{% hint style="success" %}
You have to create separate placements and AdSlots for each platform you intend to build on.

* Create one Placement and AdSlot for your Android App.
* Create one Placement and AdSlot for your iOS App.
  {% endhint %}

{% hint style="danger" %}
The minimum required OS version is iOS 11.0 (and Swift 5.x ABI) and Android 5.1+.
{% endhint %}

## Download the SDK

You can download the lastest version of our publisher package here:

{% file src="/files/r15pfKzLWS3VaNROXh6F" %}

## Add The Package To Your Unity Project <a href="#add-the-package-to-your-unity-project" id="add-the-package-to-your-unity-project"></a>

Open your Unity Project

1. Assets -> Import Package -> Custom Package
2. Select the AyetUnityPlugin\_vVersion.unitypackage file
3. Press the "Import" button to complete the process

## \*Android Specific: Update Or Create AndroidManifest.xml File <a href="#android-specific-update-or-create-androidmanifest.xml-file" id="android-specific-update-or-create-androidmanifest.xml-file"></a>

If you're planning to build against Android, please make sure you have an AndroidManifest.xml file in Assets/Plugins/Android/. If no AndroidManifest exists, you can check out the following template: [Appendix: AndroidManifest.xml Template.](#android-xml-template)&#x20;

Add these app permissions to the manifest:

```xml
<uses-permission android:name="android.permission.INTERNET" /> <!-- mandatory permission -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- optional -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- optional -->
```

Add our Offerwall activity to your scope:

```xml
<activity
    android:name="com.ayetstudios.publishersdk.OfferwallActivity"
    android:configChanges="orientation|screenSize">
    <intent-filter android:label="offer">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="offer" android:host="com.example.myapplication" /> <!-- Replace with your lower case package name -->
    </intent-filter>
</activity>
<activity android:name="com.ayetstudios.publishersdk.VideoActivity" android:configChanges="orientation|screenSize" />	    
```

## Initialize The SDK & Managed User Balances <a href="#initialize-the-sdk-and-managed-user-balances" id="initialize-the-sdk-and-managed-user-balances"></a>

{% hint style="info" %}
In this step, we are going to initialize the SDK. We also use callbacks to track the user's account balance - this is optional and not required if you're planning to manage user balances on your own servers.
{% endhint %}

{% hint style="warning" %}
**Attention:** The username or external identifier passed in the init call (e.g. username, hashed email address, etc.) will be accessible in the conversion callbacks through the *{external\_identifier}* parameter.
{% endhint %}

First, the SDK needs to be initialized like this (APP\_KEY is the placement identifier you can find in your dashboard in the android or ios placement details):

```
#if UNITY_IOS
AyetSdk.init ("<YOUR_IOS_PLACEMENT_APP_KEY>", "<username (external identifier)>", this);
#endif
#if UNITY_ANDROID
AyetSdk.init ("<YOUR_ANDROID_PLACEMENT_APP_KEY>", "<username (external identifier)>", this);
#endif
```

Implement the **SdkUserBalance** interface in order to get notified when user balance changes occur:

```
public void userBalanceInitialized (int available_currency, int pending_currency, int spent_currency){
        Debug.Log("Your::Script::userBalanceInitialized => available_currency: " + available_currency.ToString() + "  pending_currency: "+pending_currency.ToString() + "  spent_currency: " + spent_currency.ToString() );
}
```

**userBalanceInitialized** is triggered after calling **AyetSdk.init()**.

```
public void userBalanceChanged (int available_currency, int pending_currency, int spent_currency){
        Debug.Log("YourScript::userBalanceChanged => available_currency: " + available_currency.ToString() + "  pending_currency: "+pending_currency.ToString() + "  spent_currency: " + spent_currency.ToString() );
}
```

**userBalanceChanged** is triggered if the user balance changes while running the app.&#x20;

If you want to spend user currency, for example if the user clicks a "purchaseInAppItem" button, you can utilize the **deductUserBalance** function:

```
AyetSdk.deductUserBalance (<DEDUCT_AMOUNT>, this);
```

Implement the SdkDeductCallback interface in order to get notified if a deduction succeeded:

```
public void deductSuccess (){
    Debug.Log ("YourScript::deductSuccess");
}
public void deductFailed (){
    Debug.Log ("YourScript::deductFailed");
}
```

## Check User Balances (Managed Currency Handling) <a href="#check-user-balances-managed-currency-handling" id="check-user-balances-managed-currency-handling"></a>

After initializing the SDK, you can check the current user balances anywhere in your code:

```
AyetSdk.getAvailableCurrency();
AyetSdk.getPendingCurrency ();
AyetSdk.getSpentCurrency ();
```

## Show the Offerwall&#x20;

```
AyetSdk.showOfferwall("your offerwall adslot name");
```

showOfferwall starts our offerwall activity and displays available tasks for the user to complete.

## Unity Example Script

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ExampleScript : MonoBehaviour , SdkUserBalance  , SdkDeductCallback  {

    public void userBalanceInitialized (int available_currency, int pending_currency, int spent_currency){

        Debug.Log("ExampleScript::userBalanceInitialized => available_currency: " + available_currency.ToString() + "  pending_currency: "+pending_currency.ToString() + "  spent_currency: " + spent_currency.ToString() );
    }

    public void userBalanceChanged (int available_currency, int pending_currency, int spent_currency){

        Debug.Log("ExampleScript::userBalanceChanged => available_currency: " + available_currency.ToString() + "  pending_currency: "+pending_currency.ToString() + "  spent_currency: " + spent_currency.ToString() );
    }

    public void deductSuccess (){

        Debug.Log ("ExampleScript::deductSuccess");
    }

    public void deductFailed (){

        Debug.Log ("ExampleScript::deductFailed");
    }

    void Start () {
    }

    void Update () {

        if (Input.touchCount == 1) {

            Touch touch = Input.touches [0];

            if (touch.phase == TouchPhase.Ended) {

                if (Input.GetTouch (0).position.y > (Screen.height/2)) {
                    //sdk initialization
                    AyetSdk.init ("abcde123abcde123abcde123", "user_id_123", this);

                } else {

                    if (Input.GetTouch (0).position.x < (Screen.width/3)) {
                        //show offerwall
                        AyetSdk.showOfferwall("offerwall adslot name");
                    }
                    else if(Input.GetTouch (0).position.x > ((Screen.width/3)*2)){
                        //show user current balance
                        Debug.Log ("ExampleScript  Available currency: " + AyetSdk.getAvailableCurrency());
                        Debug.Log ("ExampleScript  Pending currency: " + AyetSdk.getPendingCurrency ());
                        Debug.Log ("ExampleScript  Spent currency: " + AyetSdk.getSpentCurrency ());
                    }
                    else {
                        int amount = 1;
                        //deduct balance
                        AyetSdk.deductUserBalance (amount, this);
                    }
                }
            }
        }

    }
}
```

## Proguard Rules / Release Builds <a href="#proguard-rules-release-builds" id="proguard-rules-release-builds"></a>

If you're going to use **Proguard** in your release build to obfuscate your application, make sure to add the following rules to your **proguard-rules.pro** files:

```xml
-keep class com.ayetstudios.publishersdk.messages.** {*;}
-keep public class com.ayetstudios.publishersdk.AyetSdk
-keepclassmembers class com.ayetstudios.publishersdk.AyetSdk {
   public *;
}
-keep public interface com.ayetstudios.publishersdk.interfaces.UserBalanceCallback { *; }
-keep public interface com.ayetstudios.publishersdk.interfaces.DeductUserBalanceCallback { *; }

-keep class com.ayetstudios.publishersdk.models.VastTagReqData { *; }
```

{% hint style="info" %}
It's always highly recommended to test your release builds before publishing them on Google Play to verify that they behave as intended!
{% endhint %}

## Conversion Callbacks & Currency Handling <a href="#conversion-callbacks-and-currency-handling" id="conversion-callbacks-and-currency-handling"></a>

Learn about:

* Setting up callbacks
* IP Whitelists
* Securing callbacks using HMAC Security Hash
* Testing callbacks

Click on the link below:

{% content-ref url="/pages/5sxVWIW1fto5Mmv1JxeJ" %}
[Callbacks & Testing](/v/product-docs/callbacks-and-testing.md)
{% endcontent-ref %}

## Appendix: Assets/Plugins/Android/AndroidManifest.xml Template <a href="#android-xml-template" id="android-xml-template"></a>

```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication" <!-- Replace with your lower case package name -->
	android:versionCode="1" android:versionName="1.0" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal">

    <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />

    <application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name">
        <activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>

        <activity android:name="com.ayetstudios.publishersdk.OfferwallActivity"
	    android:configChanges="orientation|screenSize">
	    <intent-filter android:label="offer">
	        <action android:name="android.intent.action.VIEW" />
	        <category android:name="android.intent.category.DEFAULT" />
	        <category android:name="android.intent.category.BROWSABLE" />
	        <data android:scheme="offer" android:host="com.example.myapplication" /> <!-- Replace with your lower case package name -->
	    </intent-filter>
	</activity>

    </application>
    <uses-permission android:name="android.permission.INTERNET" /> <!-- mandatory permission -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- optional -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- optional -->
</manifest>	                
```
