1

UnityでAndroidゲームapkを開発しています。プロジェクトに Google Admob SDK を統合し、 https://developers.google.com/admob/unity/rewarded-videoを参照して、Android APK に Google admob 報酬ビデオ広告を表示することに成功しました。

ただし、シーンをリロードしてゲームを再起動すると、コールバック関数が複数回呼び出されます。

コールバック関数の例:

// Called when an ad request has successfully loaded.
rewardBasedVideo.OnAdLoaded += HandleRewardBasedVideoLoaded;
// Called when an ad request failed to load.
rewardBasedVideo.OnAdFailedToLoad += HandleRewardBasedVideoFailedToLoad;
// Called when an ad is shown.
rewardBasedVideo.OnAdOpening += HandleRewardBasedVideoOpened;
// Called when the ad starts to play.
rewardBasedVideo.OnAdStarted += HandleRewardBasedVideoStarted;
// Called when the user should be rewarded for watching a video.
rewardBasedVideo.OnAdRewarded += HandleRewardBasedVideoRewarded;

シーンを初めてロード: コールバック関数が 1 回呼び出されます。

シーンが再度ロードされました: コールバック関数が 2 回呼び出されます。

シーンが再度ロードされました: コールバック関数が 3 回呼び出されます。

...

Unityのシーンをリロードしてもコールバック関数が溜まってしまうのが根本的な原因だと思います。

このようなコールバック関数を、シーンが変わっても 1 回だけ呼び出されるようにするにはどうすればよいですか?

4

2 に答える 2

1

だから私は最終的に広告を適切に機能させるための解決策を見つけました

まず、Google が示すように Google 広告 SDK をインストールします。

ここで Google の admonb unity 統合のチュートリアルに従ってください

次に、バナー広告、インタースティシャル広告、リワード ビデオ広告に次のスクリプトを使用します。

SaveManagerおよび関連するのは、私の機能で使用されるいくつかのスクリプトです

それらを無視する

関数ではupdate、ブール値を継続的にチェックして、広告が読み込まれているかどうかを確認する必要があります。Google Admob広告は別のスレッドで並行して読み込まれているため、によって提供されるコールバックを使用して、このブール値の値を変更します。私はマルチスレッドや並列処理の専門家ではありませんが、これらのコールバックから Unity 関数を呼び出すことはできず、代わりに bool を設定して、bool の値をチェックし続けることができることがわかりました。update function

インタースティシャル広告とリワード広告のonAdFailedToLoadイベント ハンドラを確認する

    using System;
    using UnityEngine;
    using UnityEngine.UI;
    using GoogleMobileAds.Api;

    // Example script showing how to invoke the Google Mobile Ads Unity plugin.

    public class adMob : MonoBehaviour
    {
    private BannerView bannerView;
    private InterstitialAd interstitial;
    private RewardedAd rewardedAd;
    private float deltaTime = 0.0f;
    private static string outputMessage = string.Empty;

    public Text coinValueHolder;
    int rewardAmount;

    private bool reqInterstitial = true;
    private bool reqRewardedAdVideo = true;

    public static adMob ins;

    public static string OutputMessage
    {
        set { outputMessage = value; }
    }

    public void Start()
    {

        #if UNITY_ANDROID
        string appId = "ca-app-pub-3940256099942544~3347511713";
        #elif UNITY_IPHONE
        string appId = "ca-app-pub-3940256099942544~1458002511";
        #else
        string appId = "unexpected_platform";
        #endif

        MobileAds.SetiOSAppPauseOnBackground(true);

        // Initialize the Google Mobile Ads SDK.
        MobileAds.Initialize(appId);

        this.CreateAndLoadRewardedAd();
    }

    // making the current object a singleton
    public void Awake()
    {
        if (ins == null)
        {
            ins = this;
            DontDestroyOnLoad(gameObject);
        }
        else if (ins != null)
        {
            Destroy(gameObject);
        }
    }

    public void Update()
    {
        // Calculate simple moving average for time to render screen. 0.1 factor used as 
        smoothing
        // value.
        this.deltaTime += (Time.deltaTime - this.deltaTime) * 0.1f;

        if (rewardAmount > 0)
        {
            coinValueHolder = 
            GameObject.FindGameObjectWithTag("coinText").GetComponent<Text>();

            SaveManager.coins += 100;
            SaveManager.ins.SaveDataFromDataObjects();
            coinValueHolder.text = SaveManager.coins.ToString();
            rewardAmount = 0;
        }

        if(reqInterstitial)
        {
            this.RequestInterstitial();
            reqInterstitial = false;
        }

        if(reqRewardedAdVideo)
        {
            this.CreateAndLoadRewardedAd();
            reqRewardedAdVideo = false;
        }
    }

    // Returns an ad request with custom ad targeting.
    public AdRequest CreateAdRequest()
    {
        return new AdRequest.Builder().Build();
    }

    public void RequestBanner()
    {
        // These ad units are configured to always serve test ads.
        #if UNITY_EDITOR
        string adUnitId = "unused";
        #elif UNITY_ANDROID
        string adUnitId = "ca-app-pub-3940256099942544/6300978111";
        #elif UNITY_IPHONE
        string adUnitId = "ca-app-pub-3940256099942544/2934735716";
        #else
        string adUnitId = "unexpected_platform";
        #endif

        // Clean up banner ad before creating a new one.
        if (this.bannerView != null)
        {
            this.bannerView.Destroy();
        }

        // Create a 320x50 banner at the top of the screen.
        this.bannerView = new BannerView(adUnitId, AdSize.Banner, AdPosition.Bottom);

        // Register for ad events.
        this.bannerView.OnAdLoaded += this.HandleAdLoaded;
        this.bannerView.OnAdFailedToLoad += this.HandleAdFailedToLoad;
        this.bannerView.OnAdOpening += this.HandleAdOpened;
        this.bannerView.OnAdClosed += this.HandleAdClosed;
        this.bannerView.OnAdLeavingApplication += this.HandleAdLeftApplication;

        // Load a banner ad.
        this.bannerView.LoadAd(this.CreateAdRequest());
    }

    public void DestroyBanner()
    {
        this.bannerView.Destroy();
    }

    public void RequestInterstitial()
    {
        // These ad units are configured to always serve test ads.
        #if UNITY_EDITOR
        string adUnitId = "unused";
        #elif UNITY_ANDROID
        string adUnitId = "ca-app-pub-3940256099942544/1033173712";
        #elif UNITY_IPHONE
        string adUnitId = "ca-app-pub-3940256099942544/4411468910";
        #else
        string adUnitId = "unexpected_platform";
        #endif

        // Clean up interstitial ad before creating a new one.
        if (this.interstitial != null)
        {
            this.interstitial.Destroy();
        }

        // Create an interstitial.
        this.interstitial = new InterstitialAd(adUnitId);

        // Register for ad events.
        this.interstitial.OnAdLoaded += this.HandleInterstitialLoaded;
        this.interstitial.OnAdFailedToLoad += this.HandleInterstitialFailedToLoad;
        this.interstitial.OnAdOpening += this.HandleInterstitialOpened;
        this.interstitial.OnAdClosed += this.HandleInterstitialClosed;
        this.interstitial.OnAdLeavingApplication += 
        this.HandleInterstitialLeftApplication;

        // Load an interstitial ad.
        this.interstitial.LoadAd(this.CreateAdRequest());
    }

    public void CreateAndLoadRewardedAd()
    {
        #if UNITY_EDITOR
        string adUnitId = "unused";
        #elif UNITY_ANDROID
        string adUnitId = "ca-app-pub-3940256099942544/5224354917";
        #elif UNITY_IPHONE
        string adUnitId = "ca-app-pub-3940256099942544/1712485313";
        #else
        string adUnitId = "unexpected_platform";
        #endif
        // Create new rewarded ad instance.
        this.rewardedAd = new RewardedAd(adUnitId);

        // Called when an ad request has successfully loaded.
        this.rewardedAd.OnAdLoaded += HandleRewardedAdLoaded;
        // Called when an ad request failed to load.
        this.rewardedAd.OnAdFailedToLoad += HandleRewardedAdFailedToLoad;
        // Called when an ad is shown.
        this.rewardedAd.OnAdOpening += HandleRewardedAdOpening;
        // Called when an ad request failed to show.
        this.rewardedAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;
        // Called when the user should be rewarded for interacting with the ad.
        this.rewardedAd.OnUserEarnedReward += HandleUserEarnedReward;
        // Called when the ad is closed.
        this.rewardedAd.OnAdClosed += HandleRewardedAdClosed;

        // Create an empty ad request.
        AdRequest request = this.CreateAdRequest();
        // Load the rewarded ad with the request.
        this.rewardedAd.LoadAd(request);
    }

    public void ShowInterstitial()
    {
        if (this.interstitial.IsLoaded())
        {
            this.interstitial.Show();
        }
        else
        {
            MonoBehaviour.print("Interstitial is not ready yet");
        }
    }

    public void ShowRewardedAd()
    {
        if (this.rewardedAd.IsLoaded())
        {
            this.rewardedAd.Show();
        }
        else
        {
            MonoBehaviour.print("Rewarded ad is not ready yet");
        }
    }

    #region Banner callback handlers

    public void HandleAdLoaded(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleAdLoaded event received");
    }

    public void HandleAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
    {
        MonoBehaviour.print("HandleFailedToReceiveAd event received with message: " + 
        args.Message);
    }

    public void HandleAdOpened(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleAdOpened event received");
    }

    public void HandleAdClosed(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleAdClosed event received");
    }

    public void HandleAdLeftApplication(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleAdLeftApplication event received");
    }

    #endregion

    #region Interstitial callback handlers

    public void HandleInterstitialLoaded(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleInterstitialLoaded event received");
    }

    public void HandleInterstitialFailedToLoad(object sender, AdFailedToLoadEventArgs args)
    {
        MonoBehaviour.print(
            "HandleInterstitialFailedToLoad event received with message: " + args.Message);
        this.reqInterstitial = true;
    }

    public void HandleInterstitialOpened(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleInterstitialOpened event received");
    }

    public void HandleInterstitialClosed(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleInterstitialClosed event received");
        this.reqInterstitial = true;
    }

    public void HandleInterstitialLeftApplication(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleInterstitialLeftApplication event received");
    }

    #endregion

    #region RewardedAd callback handlers

    public void HandleRewardedAdLoaded(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleRewardedAdLoaded event received");
    }

    public void HandleRewardedAdFailedToLoad(object sender, AdErrorEventArgs args)
    {
        MonoBehaviour.print(
            "HandleRewardedAdFailedToLoad event received with message: " + args.Message);
        this.reqRewardedAdVideo = true;
    }

    public void HandleRewardedAdOpening(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleRewardedAdOpening event received");
    }

    public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args)
    {
        MonoBehaviour.print(
            "HandleRewardedAdFailedToShow event received with message: " + args.Message);
    }

    public void HandleRewardedAdClosed(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleRewardedAdClosed event received");
        this.reqRewardedAdVideo = true;
    }

    public void HandleUserEarnedReward(object sender, Reward args)
    {
        string type = args.Type;
        double amount = args.Amount;
        rewardAmount = (int)amount;

        MonoBehaviour.print(
            "HandleRewardedAdRewarded event received for "
                        + amount.ToString() + " " + type);
    }

    #endregion
}

上記のスクリプトを階層内のゲームオブジェクトに配置します

広告を呼び出すには

    adMob.ins.DestroyBanner();

またはその他の関数 (静的 ins を宣言し、ゲームオブジェクトを参照することは、サウンドマネージャー、シーンマネージャー、追加マネージャーなどのマネージャーで使用されるシングルトンパターンとして知られています)

    adMob.ins._Your-Function-Name_();

使用後にイベントからハンドルをサブスクライブ解除する必要があります。そうしないと、予期しない動作が発生します。

void OnDestroy()
{
        // Called when an ad request has successfully loaded.
        rewardBasedVideo.OnAdLoaded -= HandleRewardBasedVideoLoaded;
        // Called when an ad request failed to load.
        rewardBasedVideo.OnAdFailedToLoad -= HandleRewardBasedVideoFailedToLoad;
        // Called when an ad is shown.
        rewardBasedVideo.OnAdOpening -= HandleRewardBasedVideoOpened;
        // Called when the ad starts to play.
        rewardBasedVideo.OnAdStarted -= HandleRewardBasedVideoStarted;
        // Called when the user should be rewarded for watching a video.
        rewardBasedVideo.OnAdRewarded -= HandleRewardBasedVideoRewarded;
}

たとえば、OnDestroy メソッドで実行します。

于 2019-11-21T09:44:12.030 に答える
1

以下を使用した後、イベントからハンドルをサブスクライブ解除する必要があります。

    // Called when an ad request has successfully loaded.
    rewardBasedVideo.OnAdLoaded -= HandleRewardBasedVideoLoaded;
    // Called when an ad request failed to load.
    rewardBasedVideo.OnAdFailedToLoad -= HandleRewardBasedVideoFailedToLoad;
    // Called when an ad is shown.
    rewardBasedVideo.OnAdOpening -= HandleRewardBasedVideoOpened;
    // Called when the ad starts to play.
    rewardBasedVideo.OnAdStarted -= HandleRewardBasedVideoStarted;
    // Called when the user should be rewarded for watching a video.
    rewardBasedVideo.OnAdRewarded -= HandleRewardBasedVideoRewarded;

たとえば、OnDestroy メソッドで実行します。

于 2018-10-17T12:08:18.433 に答える