using UnityEngine;
using System.Runtime.InteropServices;
///
/// Singleton that handles interstitial (non-rewarded) ads for WebGL games.
///
/// SETUP: Add AutoCreateAdManagers to any GameObject in your first scene —
/// it will create this manager automatically at runtime.
///
/// USAGE: Call one of the public Show methods at the right moment in your game:
/// InterstitialAdsManager.Instance.ShowInterstitialAdAfterLevelComplete();
/// InterstitialAdsManager.Instance.ShowInterstitialAdOnPause();
/// InterstitialAdsManager.Instance.ShowInterstitialAdOnBrowse();
/// InterstitialAdsManager.Instance.ShowInterstitialAdOnStart();
///
/// The manager pauses time and mutes audio automatically before the ad,
/// then restores both when the ad closes. You do not need to pause/resume manually.
///
public class InterstitialAdsManager : MonoBehaviour
{
[DllImport("__Internal")] private static extern void ShowInterstitialAd(string adType, string callbackName);
[DllImport("__Internal")] private static extern void FocusUnityCanvas();
private static InterstitialAdsManager _instance;
public static InterstitialAdsManager Instance => _instance;
private float _prevTimeScale = 1f;
private bool _prevAudioPause = false;
private void Awake()
{
if (_instance == null)
{
_instance = this;
DontDestroyOnLoad(gameObject);
}
else if (_instance != this)
{
Destroy(gameObject);
}
}
// -------------------------------------------------------------------------
// Public API — call these from your game scripts
// -------------------------------------------------------------------------
/// Show an interstitial ad after the player completes a level.
public void ShowInterstitialAdAfterLevelComplete() => ShowInternal("next", "OnLevelCompleteAdClosed");
/// Show an interstitial ad when the player opens the pause menu.
public void ShowInterstitialAdOnPause() => ShowInternal("pause", "OnPauseAdClosed");
/// Show an interstitial ad when the player returns to the main menu.
public void ShowInterstitialAdOnBrowse() => ShowInternal("browse", "OnBrowseAdClosed");
/// Show an interstitial ad at the start of a round or session.
public void ShowInterstitialAdOnStart() => ShowInternal("start", "OnStartAdClosed");
///
/// Show an interstitial ad with a custom ad type and callback name.
///
/// H5 Games Ads type: "next", "pause", "browse", "start", or "preroll".
/// Must match the handler name added to OnInterstitialAdClosed's switch.
public void ShowInterstitialAdCustom(string adType, string callbackName) => ShowInternal(adType, callbackName);
// -------------------------------------------------------------------------
// Internal
// -------------------------------------------------------------------------
private void ShowInternal(string adType, string callbackName)
{
PauseForAd();
#if UNITY_WEBGL && !UNITY_EDITOR
try
{
ShowInterstitialAd(adType, callbackName);
}
catch (System.Exception e)
{
Debug.LogError($"[InterstitialAdsManager] .jslib call failed: {e.Message}");
ResumeAfterAd();
OnInterstitialAdClosed($"{callbackName}|closed");
}
#else
// Editor simulation: ad closes immediately
OnInterstitialAdClosed($"{callbackName}|closed");
#endif
}
// -------------------------------------------------------------------------
// Callback — called by the platform via SendMessage
// Payload format: "callbackName|result" (result is always "closed")
// -------------------------------------------------------------------------
///
/// Called by the platform via SendMessage after the ad closes.
/// Do not rename this method — the platform calls it by name.
///
public void OnInterstitialAdClosed(string payload)
{
if (_instance == null) return;
var parts = string.IsNullOrEmpty(payload) ? new[] { "OnInterstitialAdClosed", "closed" } : payload.Split('|');
var callbackName = parts.Length > 0 ? parts[0] : "OnInterstitialAdClosed";
var result = parts.Length > 1 ? parts[1] : "closed";
Debug.Log($"[InterstitialAdsManager] Ad closed — callback: {callbackName}, result: {result}");
switch (callbackName)
{
case "OnLevelCompleteAdClosed": OnLevelCompleteAdClosed(result); break;
case "OnPauseAdClosed": OnPauseAdClosed(result); break;
case "OnBrowseAdClosed": OnBrowseAdClosed(result); break;
case "OnStartAdClosed": OnStartAdClosed(result); break;
default:
Debug.LogWarning($"[InterstitialAdsManager] Unknown callback '{callbackName}' — resuming game.");
ResumeAfterAd();
break;
}
}
// -------------------------------------------------------------------------
// Ad-closed handlers — add your game logic in each TODO block
// -------------------------------------------------------------------------
private void OnLevelCompleteAdClosed(string result)
{
ResumeAfterAd();
// TODO: Continue to the next level or show the results screen
// Example: LevelManager.LoadNextLevel();
}
private void OnPauseAdClosed(string result)
{
ResumeAfterAd();
// TODO: Show your pause menu or resume the game
// Example: PauseMenu.Show();
}
private void OnBrowseAdClosed(string result)
{
ResumeAfterAd();
// TODO: Navigate to your main menu or game selection screen
// Example: SceneManager.LoadScene("MainMenu");
}
private void OnStartAdClosed(string result)
{
ResumeAfterAd();
// TODO: Begin the game or the next round
// Example: GameController.StartRound();
}
// -------------------------------------------------------------------------
// Pause / resume helpers (called automatically — no need to call manually)
// -------------------------------------------------------------------------
private void PauseForAd()
{
#if UNITY_WEBGL && !UNITY_EDITOR
_prevTimeScale = Time.timeScale;
_prevAudioPause = AudioListener.pause;
Time.timeScale = 0f;
AudioListener.pause = true;
TryFocusCanvas();
#endif
}
private void ResumeAfterAd()
{
#if UNITY_WEBGL && !UNITY_EDITOR
Time.timeScale = _prevTimeScale;
AudioListener.pause = _prevAudioPause;
TryFocusCanvas();
#endif
}
private void TryFocusCanvas()
{
#if UNITY_WEBGL && !UNITY_EDITOR
try { FocusUnityCanvas(); } catch { }
#endif
}
}