如何在 google OnAdclosed on Unity 上从一个 GameObject 访问另一个方法?

How to access method from one GameObject to another on google OnAdclosed on Unity?

我有一个 GameScreenManger,它会根据游戏状态显示或隐藏面板。我有一个 AdManager 游戏对象,其中包含一个处理广告的脚本。我能够显示广告,但在 onAdclosed 上,如果我尝试引用 GameScreenManager,它在 Admanager Script 中包含一个脚本,并在 onAdclosed 事件侦听器运行时调用一个函数,调用正在触发,但操作不起作用。有人可以帮助我吗?

using UnityEngine;
using GoogleMobileAds.Api;
using System;

public class AdManager : MonoBehaviour
{
    public static AdManager instance;

    private string appId = "";

    private InterstitialAd InterstitialAd;
    private string InterstitialAdId = "interstitial_Ad_Id";


    private RewardedAd RewardedVideoAd;
    private string RewardedVideoAdId = "rewarded_video_ad_Id ";

    public GameObject RewardPanel;
    public GameScreenManager gameManager;

    public bool isRewardedVideo;

    private bool RewardedVideoLoaded = false;

    public void Awake()
    {
        if(instance == null)
        {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
            instance = this;
        } else
        {
            Destroy(this);
        }

        MobileAds.Initialize(initStatus => { });
    }

    private void Start()
    {
        RequestInterstitial();

        RewardedVideoAd = new RewardedAd(RewardedVideoAdId);

        RequestRewardedVideo();

        // Called when an ad request has successfully loaded.
        this.RewardedVideoAd.OnAdLoaded += HandleRewardedAdLoaded;

        // Called when an ad request failed to load.
        this.RewardedVideoAd.OnAdFailedToLoad += HandleRewardedAdFailedToLoad;

        // Called when an ad is shown.
        this.RewardedVideoAd.OnAdOpening += HandleRewardedAdOpening;

        // Called when an ad request failed to show.
        this.RewardedVideoAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;

        // Called when the user should be rewarded for interacting with the ad.
        this.RewardedVideoAd.OnUserEarnedReward += HandleUserEarnedReward;

        // Called when the ad is closed.
        this.RewardedVideoAd.OnAdClosed += HandleRewardedAdClosed;

    }

    private void Update()
    {
        if (RewardedVideoLoaded == false)
        {
            RequestRewardedVideo();
        }
    }

    private void RequestInterstitial()
    {
        string adUnitId = InterstitialAdId;

        // Initialize an InterstitialAd.
        this.InterstitialAd = new InterstitialAd(adUnitId);

        // Create an empty ad request.
        AdRequest request = new AdRequest.Builder().Build();
        // Load the interstitial with the request.
        this.InterstitialAd.LoadAd(request);
    }

    public void ShowInterstitial()
    {
        if (this.InterstitialAd.IsLoaded())
        {
            this.InterstitialAd.Show();
        }
    }

    public void RequestRewardedVideo()
    {
        // Create an empty ad request.
        AdRequest request = new AdRequest.Builder().Build();
        // Load the interstitial with the request.
        this.RewardedVideoAd.LoadAd(request);

        if (this.RewardedVideoAd.IsLoaded())
        {
            isRewardedVideo = true;
            RewardedVideoLoaded = true;
        } else
        {
            isRewardedVideo = false;
            RewardedVideoLoaded = false;
        }
    }

    public void ShowRewardedVideo()
    {
        if (this.RewardedVideoAd.IsLoaded())
        {
            this.RewardedVideoAd.Show();
        }
    }

    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);
    }

    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");

        Debug.Log("{lo} OnClosed called sender = " + sender);

        RequestRewardedVideo();

        gameManager.CheckForLives(); //This is not working.

        this.RewardPanel.SetActive(true);

    }

    public void HandleUserEarnedReward(object sender, Reward args)
    {

        Debug.Log("{lo} Earned a Reward  HandleUserEarnedReward called!");

        string type = args.Type;
        double amount = args.Amount;
        this.RewardPanel.SetActive(true);

    }
}

游戏画面脚本

using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class GameScreenManager : MonoBehaviour
{
    public GameObject PauseScreen;
    public GameObject OutOfLifeScreen;
    public GameObject PauseButton;
    public GameObject Scoretext;
    public GameObject Livesbutton;

    public Text MusicText;

    public void LoadPause()
    {
        PauseScreen.SetActive(true);
        bool audioPlaying = FindObjectOfType<AudioManager>().audioPlaying;

        MusicText.text = audioPlaying ? "MUSIC ON" : "MUSIC OFF";
        Time.timeScale = 0f;
    }

    public void ShowResume()
    {
        PauseScreen.SetActive(false);
        Time.timeScale = 1f;
    }

    public void ShowMainMenu()
    {
        Time.timeScale = 1f;
        SceneManager.LoadScene("Menu");
    }

    public void ShowOutOfLives()
    {
        OutOfLifeScreen.SetActive(true);
        PauseButton.SetActive(false);
        Time.timeScale = 0f;

    }

    public void CloseOutOfLives()
    {

       Debug.Log(" {lo} Entered CloseOutOfLives");
       OutOfLifeScreen.SetActive(false);
       PauseButton.SetActive(true);
       Time.timeScale = 1f;
    }

    public void TogggleSound()
    {
        FindObjectOfType<AudioManager>().ToggleMute();
        bool audioPlaying = FindObjectOfType<AudioManager>().audioPlaying;

        MusicText.text = audioPlaying ? "MUSIC ON" : "MUSIC OFF";
        PlayerPrefs.SetInt("audioNeeded", audioPlaying ? 1 : 0);
    }

    public void Quit()
    {
        Application.Quit();
    }
}

您似乎没有在第二个脚本中引用您的对象:

广告脚本

public GameScreenManager gsmanagerRef; //drag and drop on the editor or find it on initialization

那么你应该可以调用

gsmanagerRef.ShowResume(); //or any other function

希望对您有所帮助!

因为回调来自非主线程,而 unity 是单线程环境,所以一些 unity API 是无法从非主线程访问的,例如你不能使用 GameObject.SetActive 或除了主线程之外还有很多组件函数,所以您需要做的是先将回调分派给主线程,然后函数中的所有语句都会执行。

方法如下。

1) 一个在 unity 的主线程上执行方法的简单调度程序。 在您的场景中创建一个空的游戏对象,并将其附加到它。

using System;
using System.Collections.Generic;

/// <summary>
/// Helps dispatch task results to the main thread to be able to operate on unity's API like SetActive, enabled etc...
/// </summary>
public class MainThreadDispatcher : MonoBehaviour
{
    Queue<Action> jobs = new Queue<Action>();
    static MainThreadDispatcher Instance = null;

    private void Awake()
    {
        Instance = this;
    }
    private void Update()
    {
        while (jobs.Count > 0)
        {
            var next = jobs.Dequeue();
            if(next != null)
            {
                next.Invoke();
            }
        }
    }
    /// <summary>
    /// Dispatches a function to be executed on unity's main thread to be able to use unity's API.
    /// </summary>
    /// <param name="newJob"></param>
    public static void Dispatch(Action newJob)
    {
        if (newJob == null)
            return;
        Instance.jobs.Enqueue(newJob);
    }
}

2) 编辑您的广告关闭回调以分派到主线程。

    public void HandleRewardedAdClosed(object sender, EventArgs args)
    {
        // simply give unity control back.
        // you can pick and choose to execute what on main thread,
        // but I'm just gonna dispatch the whole block.
        MainThreadDispatcher.Dispatch(() =>
        {
            MonoBehaviour.print("HandleRewardedAdClosed event received");

            Debug.Log("{lo} OnClosed called sender = " + sender);

            RequestRewardedVideo();

            gameManager.CheckForLives();

            this.RewardPanel.SetActive(true);
        });
    }