using UnityEngine;
using System.Runtime.InteropServices;
///
/// Singleton that handles 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 a Show method when the player opts in to watch a rewarded ad:
/// RewardedAdsManager.Instance.ShowRewardedAdForHint();
/// RewardedAdsManager.Instance.ShowRewardedAdForExtraLife();
/// RewardedAdsManager.Instance.ShowRewardedAdForCoins();
/// RewardedAdsManager.Instance.ShowRewardedAdForPowerup();
///
/// Grant the reward only when result == "rewarded" (player watched the full ad).
/// result == "closed" means the player skipped — do not grant the reward.
///
/// 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 RewardedAdsManager : MonoBehaviour
{
[DllImport("__Internal")] private static extern void ShowRewardedAd(string rewardType, string callbackName);
[DllImport("__Internal")] private static extern void FocusUnityCanvas();
private static RewardedAdsManager _instance;
public static RewardedAdsManager 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 a rewarded ad in exchange for a hint.
public void ShowRewardedAdForHint() => ShowInternal("hint", "OnHintReward");
/// Show a rewarded ad in exchange for an extra life or continue.
public void ShowRewardedAdForExtraLife() => ShowInternal("extraLife", "OnExtraLifeReward");
/// Show a rewarded ad in exchange for in-game currency.
public void ShowRewardedAdForCoins() => ShowInternal("coins", "OnCoinsReward");
/// Show a rewarded ad in exchange for a power-up.
public void ShowRewardedAdForPowerup() => ShowInternal("powerup", "OnPowerupReward");
///
/// Show a rewarded ad with a custom reward type and callback name.
/// Add a matching case to OnRewardedAdResult's switch to handle the result.
///
public void ShowRewardedAdForCustom(string rewardType, string callbackName) => ShowInternal(rewardType, callbackName);
// -------------------------------------------------------------------------
// Internal
// -------------------------------------------------------------------------
private void ShowInternal(string rewardType, string callbackName)
{
PauseForAd();
#if UNITY_WEBGL && !UNITY_EDITOR
try
{
ShowRewardedAd(rewardType, callbackName);
}
catch (System.Exception e)
{
Debug.LogError($"[RewardedAdsManager] .jslib call failed: {e.Message}");
ResumeAfterAd();
OnRewardedAdResult($"{callbackName}|closed");
}
#else
// Editor simulation: reward is granted immediately so you can test your reward logic
OnRewardedAdResult($"{callbackName}|rewarded");
#endif
}
// -------------------------------------------------------------------------
// Callback — called by the platform via SendMessage
// Payload format: "callbackName|result"
// result = "rewarded" → player watched the full ad, grant the reward
// result = "closed" → player skipped the ad, do not grant the reward
// -------------------------------------------------------------------------
///
/// Called by the platform via SendMessage after the ad completes.
/// Do not rename this method — the platform calls it by name.
///
public void OnRewardedAdResult(string payload)
{
if (_instance == null) return;
var parts = string.IsNullOrEmpty(payload) ? new[] { "OnRewardedAdResult", "closed" } : payload.Split('|');
var callbackName = parts.Length > 0 ? parts[0] : "OnRewardedAdResult";
var result = parts.Length > 1 ? parts[1] : "closed";
Debug.Log($"[RewardedAdsManager] Ad result — callback: {callbackName}, result: {result}");
switch (callbackName)
{
case "OnHintReward": OnHintReward(result); break;
case "OnExtraLifeReward": OnExtraLifeReward(result); break;
case "OnCoinsReward": OnCoinsReward(result); break;
case "OnPowerupReward": OnPowerupReward(result); break;
default:
Debug.LogWarning($"[RewardedAdsManager] Unknown callback '{callbackName}' — resuming game.");
ResumeAfterAd();
break;
}
}
// -------------------------------------------------------------------------
// Reward handlers — add your grant logic in each "rewarded" block
// -------------------------------------------------------------------------
private void OnHintReward(string result)
{
if (result == "rewarded")
{
// TODO: Give the player a hint
// Example: HintSystem.GiveHint();
}
ResumeAfterAd();
}
private void OnExtraLifeReward(string result)
{
if (result == "rewarded")
{
// TODO: Give the player an extra life or continue
// Example: LivesSystem.AddLife();
}
ResumeAfterAd();
}
private void OnCoinsReward(string result)
{
if (result == "rewarded")
{
// TODO: Give the player in-game currency
// Example: CurrencySystem.AddCoins(100);
}
ResumeAfterAd();
}
private void OnPowerupReward(string result)
{
if (result == "rewarded")
{
// TODO: Give the player a power-up
// Example: PowerupSystem.UnlockPowerup();
}
ResumeAfterAd();
}
// -------------------------------------------------------------------------
// 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
}
}