# Unity

Our CMP is available for Unity as a Unity Package containing plugins for Android, iOS and tvOS. The package is available from the following git repository:

[AppConsent Unity package](https://gitlab.datalf.chat/customers/appconsent-unity.git)

Minimum supported version of unity is **2021.3.46f1 LTS**.

<https://unity.com/fr/releases/editor/archive>

***

## Simple execution

This example is taken directly from the sample code below.

<figure><img src="/files/iuuTcHpxnuA7ckpe0O1v" alt=""><figcaption></figcaption></figure>

### Runner Sample

Here's the Unity sample runner project into which we've integrated our solution. [Sample](https://gitlab.datalf.chat/customers/appconsent-runner-sample)

### Developer Sample

Here's a sample Unity project in which we've integrated our solution, enabling you to interact directly with it from the main screen. [Sample](https://gitlab.datalf.chat/customers/appconsent-unity-sample)

## Add the SFBX AppConsent package to your Unity project

From the *window* menu, open the *Package Manager*

<figure><img src="/files/8pL8rIU4KxMwVAyJm4lJ" alt=""><figcaption></figcaption></figure>

Inside the Package Manager window, click on the *+* button *+* in the top-left corner. From the drop-down menu select *Add package from git URL*.

<figure><img src="/files/D0LleEcTv2HUiXG0o9pv" alt=""><figcaption></figcaption></figure>

In the popup text field, enter the url to the package's git repository <https://gitlab.datalf.chat/customers/appconsent-unity.git> and click on *Add*.

<figure><img src="/files/6ZsjhuwU5Ml8R2nBaN1P" alt=""><figcaption></figcaption></figure>

The SFBX AppConsent package has been added to your project.

<figure><img src="/files/1Pd0FfFrRPkYXHld8Kok" alt=""><figcaption></figcaption></figure>

***

## Recommendation Android

The plugin allows you to define a success or error callback before CMP initialization, enabling you to log and/or use the CMP when it is fully initialized (asynchronous).

Here's an example of how CMP works on Android

```kotlin
using SFBX.AppConsent;
using UnityEngine;
using System.Collections;

public class AppConsentGUI : MonoBehaviour, ISDKCallbackListener, ISDKPresentNoticeListener
{
    ACNotice bridge = null;
    private bool isCmpInitialized = false;
    int centerX = Screen.width / 2;
    int buttonWidth = Screen.width / 2;
    int buttonHeight = Screen.height / 14;
    int buttonX;

    GUIStyle labelStyle = new GUIStyle();
    GUIStyle buttonStyle;

    string status = "";
    int logIndice = 0;

    void Awake()
    {
        AndroidJNIHelper.debug = true;
        // Only for Android - does not impact iOS !
        ACNotice.SetNoticeCallback(this);
        bridge = new ACNotice("18ecaea4-554a-4f74-9242-520fe62058a8");
        UpdateStatus("bridge instanciated => " + bridge);
    }

    // Start is called before the first frame update
    void Start()
    {
        labelStyle.alignment = TextAnchor.MiddleCenter;
        labelStyle.normal.textColor = Color.white;
        buttonX = centerX - ( buttonWidth / 2);
        
        bridge.InitACNotice();

        #if UNITY_IOS || UNITY_TVOS
            // On iOS, there's no need for a callback, so you can directly change the boolean's state. 
            OnReadyOnSuccess();
        #endif
    }

    // Update is called once per frame
    void Update()
    {
        centerX = Screen.width / 2;
        buttonWidth = Screen.width / 2;
        buttonHeight = Screen.height / 14;
        buttonX = centerX - ( buttonWidth / 2);
    }

    void OnGUI()
    {
        labelStyle.fontSize = 28;
        labelStyle.wordWrap = true;

        buttonStyle = new GUIStyle(GUI.skin.button);
        buttonStyle.fontSize = 28;

        GUI.Label(new Rect(buttonX, buttonHeight * 2, buttonWidth, buttonHeight), "SFBX AppConsent", labelStyle);

        if (GUI.Button(new Rect(buttonX, buttonHeight * 4, buttonWidth, buttonHeight), "Display CMP", buttonStyle))
        {
            if(isCmpInitialized == true && bridge != null){
                bridge.SetPresentNoticeListener(this);
                bool isDisplayed = bridge.ShowNotice();
                if(isDisplayed == true){
                    UpdateStatus("Notice displayed");
                }else{
                    UpdateStatus("Notice not displayed, look at your consent or RGPD country.");
                }
            }else{
                UpdateStatus("AppConsent not ready yet");
            }
        }

        if (GUI.Button(new Rect(buttonX, buttonHeight * 6, buttonWidth, buttonHeight), "Settings", buttonStyle))
        {
            if(isCmpInitialized == true && bridge != null){
                bridge.ShowSettings();
                UpdateStatus("Settings displayed");
            }else{
                UpdateStatus("AppConsent not ready yet");
            }
        }

        if (GUI.Button(new Rect(buttonX, buttonHeight * 8, buttonWidth, buttonHeight), "Check Consents", buttonStyle))
        {
            if(isCmpInitialized == true && bridge != null){
                bool consent = bridge.ConsentGiven();
                bool allConsentables = bridge.AllConsentablesAllowed();
                bool gdpr = bridge.IsSubjectToGDPR();
                bool acceptAll = bridge.UserAcceptAll();
                bool extra = bridge.ExtraVendorAllowed("TobuM9Iw");
                bool consentable = bridge.ConsentableAllowed(1,0);
                UpdateStatus("consents: " + consent + allConsentables + gdpr + acceptAll + extra + consentable);
            }else{
                UpdateStatus("AppConsent not ready yet");
            }
        }

        if (GUI.Button(new Rect(buttonX, buttonHeight * 10, buttonWidth, buttonHeight), "Reset Consents", buttonStyle))
        {
            if(isCmpInitialized == true && bridge != null){
                bridge.ClearConsents();
                UpdateStatus("Cleared consents");
            }else{
                UpdateStatus("AppConsent not ready yet");
            }
        }

        GUI.Label(new Rect(0, buttonHeight * 12, Screen.width, buttonHeight), status, labelStyle);
    }

    public void OnReadyOnSuccess()
    {   
        UpdateStatus("Appconsent onReadyOnSuccess");
        isCmpInitialized = true;
        
        Debug.Log("AppConsent is ready to be use !");
        UpdateStatus("Setting listener + trying to show notice");
        bridge.SetPresentNoticeListener(this);

        bool isDisplayed = bridge.ShowNotice();
        if(isDisplayed == true){
            UpdateStatus("Notice displayed");
        }else{
            UpdateStatus("Notice not displayed, look at your consent or RGPD country.");
        }
    }
    
    public void OnReadyOnError(AndroidJavaObject err)
    {
        isCmpInitialized = false;
        Debug.LogError("Failed to start AppConsent");
    }

    public void OnConsentGiven()
    {
        Debug.Log("The user has given his consent");
        UpdateStatus("Consent given !");
    }

    public void OnConsentGivenError(AndroidJavaObject err)
    {
        Debug.LogError("An error as occurred, please read Log.");
        UpdateStatus("An error as occurred, please read Log.");
    }

    private void UpdateStatus(string log){
        if(logIndice % 10 == 0){
            status = logIndice++ + " - " + log;
        }else{
            status = status + "\n" + logIndice++ + " - " + log;
        }
    }
}
```

## API Documentation

Detailed API documentation is available [here](https://docs.sfbx.io/unity-api-reference/index.html).

## FAQ

All our FAQs can be found in our git [README](https://gitlab.datalf.chat/customers/appconsent-unity/-/blob/master/README.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sfbx.io/configuration/step-3-notice-implementation-web-app-tv/ios/appconsent-sdk/unity.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
