我有一个GameScreenManger,可以根据游戏状态显示或隐藏面板。我有一个AdManager gameObject,它包含一个处理广告的脚本。我可以显示广告,但在onAdclosed上,如果我尝试引用GameScreenManager,并在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);
}
}GameScreen脚本
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();
}
}发布于 2019-10-08 17:32:18
因为回调来自非主线程,而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)编辑on ad closed回调,调度到主线程。
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);
});
}发布于 2019-10-08 17:00:00
在第二个脚本中似乎没有对对象的引用:
广告脚本
public GameScreenManager gsmanagerRef; //drag and drop on the editor or find it on initialization然后,您应该能够调用
gsmanagerRef.ShowResume(); //or any other function希望这能有所帮助!
https://stackoverflow.com/questions/58283080
复制相似问题