显示插页式广告和奖励广告后游戏崩溃
Game crashes after showing intersitial and rewarded ads
我正在使用 admob 投放广告。广告在编辑器上运行良好,但在 phone 上则不然。我在游戏中有一个按钮可以显示激励广告,然后加载下一关。我在关卡末尾展示插页式广告,然后加载下一个关卡。但是在加载下一级游戏崩溃后。我试图修复它几天,但它一直在发生。我正在添加我的广告管理器脚本。 (单位 ID 当然不是空的)
using System.Collections;
using UnityEngine;
using GoogleMobileAds.Api;
using System;
public class AdManager : MonoBehaviour
{
public static AdManager instance;
private BannerView bannerView;
private RewardedAd rewardedAd;
private InterstitialAd interstitialAd;
#if UNITY_ANDROID
string bannerAdUnitId = " ";
string rewardedAdUnitId = " ";
string interstitialAdUnitId = " ";
#else
string bannerAdUnitId = "unexpected_platform";
string rewardedAdUnitId = "unexpected_platform";
string interstitialAdUnitId = "unexpected_platform";
#endif
void Awake()
{
if(instance != null && instance != this){
Destroy(this.gameObject);
}
else{
instance = this;
DontDestroyOnLoad(this.gameObject);
}
}
private void Start() {
MobileAds.Initialize(initStatus => { });
RequestInterstitialAd();
RequestBannerAd();
RequestRewardedAd();
}
//BANNER
public void RequestBannerAd(){
if (bannerView != null)
bannerView.Destroy();
else{
bannerView = new BannerView(bannerAdUnitId, AdSize.Banner, AdPosition.Bottom);
AdRequest request = new AdRequest.Builder().Build();
bannerView.LoadAd(request);
}
}
//REWARDED
public void RequestRewardedAd(){
if(rewardedAd != null)
rewardedAd.Destroy();
rewardedAd = new RewardedAd(rewardedAdUnitId);
// Called when an ad request failed to show.
rewardedAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;
// Called when the ad is closed.
rewardedAd.OnAdClosed += HandleRewardedAdClosed;
AdRequest request = new AdRequest.Builder().Build();
rewardedAd.LoadAd(request);
}
public void ShowRewardedAd(){
if (rewardedAd.IsLoaded()) {
rewardedAd.Show();
}
else{
StartCoroutine(RewardedNotLoadedFunctionCall());
}
}
IEnumerator RewardedNotLoadedFunctionCall(){
FindObjectOfType<GameManagement>().RewardedAdNotLoaded();
yield return null;
}
public void HandleRewardedAdClosed(object sender, EventArgs args)
{
RequestRewardedAd();
StartCoroutine(AdClosedFunctionCall());
}
IEnumerator AdClosedFunctionCall(){
FindObjectOfType<GameManagement>().AdClosed();
yield return null;
}
public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args)
{
StartCoroutine(RewardedNotLoadedFunctionCall());
}
//interstitial
private void RequestInterstitialAd(){
if(interstitialAd != null)
interstitialAd.Destroy();
interstitialAd = new InterstitialAd(interstitialAdUnitId);
interstitialAd.OnAdClosed += HandleOnAdClosed;
AdRequest request = new AdRequest.Builder().Build();
interstitialAd.LoadAd(request);
}
public void ShowInterstitialAd(){
if (interstitialAd.IsLoaded()) {
interstitialAd.Show();
}
else{
StartCoroutine(AdClosedFunctionCall());
}
}
public void HandleOnAdClosed(object sender, EventArgs args)
{
RequestInterstitialAd();
StartCoroutine(AdClosedFunctionCall());
}
}
logcat
Admob Ad 不 运行 与 Unity 的主线程在同一线程上。
rewardedAd.OnAdClosed += HandleRewardedAdClosed;
从Admob的线程调用Unity的函数会出现意外错误。
首先,将 UnityMainThreadDispatcher 添加到您的项目中。 Admob回调调用的所有函数都需要UnityMainThreadDispatcher排队到主线程:
public void HandleRewardedAdClosed(object sender, EventArgs args)
{
UnityMainThreadDispatcher.Instance().Enqueue(()=>{
RequestRewardedAd();
StartCoroutine(AdClosedFunctionCall());
});
}
其次,您不应该使用 FindObjectOfType()。这是一项昂贵的操作,如果找不到 GameManagement 对象,您可能 运行 进入 NullReferenceException。由于此异常并未发生在 Unity 的主线程上,因此 logcat 消息很含糊。
您应该改用单例模式或观察者模式。
第三,即使用户跳过奖励广告,您也给予了奖励。使用 rewardedAd.OnUserEarnedReward
确保用户已获得奖励广告。
我正在使用 admob 投放广告。广告在编辑器上运行良好,但在 phone 上则不然。我在游戏中有一个按钮可以显示激励广告,然后加载下一关。我在关卡末尾展示插页式广告,然后加载下一个关卡。但是在加载下一级游戏崩溃后。我试图修复它几天,但它一直在发生。我正在添加我的广告管理器脚本。 (单位 ID 当然不是空的)
using System.Collections;
using UnityEngine;
using GoogleMobileAds.Api;
using System;
public class AdManager : MonoBehaviour
{
public static AdManager instance;
private BannerView bannerView;
private RewardedAd rewardedAd;
private InterstitialAd interstitialAd;
#if UNITY_ANDROID
string bannerAdUnitId = " ";
string rewardedAdUnitId = " ";
string interstitialAdUnitId = " ";
#else
string bannerAdUnitId = "unexpected_platform";
string rewardedAdUnitId = "unexpected_platform";
string interstitialAdUnitId = "unexpected_platform";
#endif
void Awake()
{
if(instance != null && instance != this){
Destroy(this.gameObject);
}
else{
instance = this;
DontDestroyOnLoad(this.gameObject);
}
}
private void Start() {
MobileAds.Initialize(initStatus => { });
RequestInterstitialAd();
RequestBannerAd();
RequestRewardedAd();
}
//BANNER
public void RequestBannerAd(){
if (bannerView != null)
bannerView.Destroy();
else{
bannerView = new BannerView(bannerAdUnitId, AdSize.Banner, AdPosition.Bottom);
AdRequest request = new AdRequest.Builder().Build();
bannerView.LoadAd(request);
}
}
//REWARDED
public void RequestRewardedAd(){
if(rewardedAd != null)
rewardedAd.Destroy();
rewardedAd = new RewardedAd(rewardedAdUnitId);
// Called when an ad request failed to show.
rewardedAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;
// Called when the ad is closed.
rewardedAd.OnAdClosed += HandleRewardedAdClosed;
AdRequest request = new AdRequest.Builder().Build();
rewardedAd.LoadAd(request);
}
public void ShowRewardedAd(){
if (rewardedAd.IsLoaded()) {
rewardedAd.Show();
}
else{
StartCoroutine(RewardedNotLoadedFunctionCall());
}
}
IEnumerator RewardedNotLoadedFunctionCall(){
FindObjectOfType<GameManagement>().RewardedAdNotLoaded();
yield return null;
}
public void HandleRewardedAdClosed(object sender, EventArgs args)
{
RequestRewardedAd();
StartCoroutine(AdClosedFunctionCall());
}
IEnumerator AdClosedFunctionCall(){
FindObjectOfType<GameManagement>().AdClosed();
yield return null;
}
public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args)
{
StartCoroutine(RewardedNotLoadedFunctionCall());
}
//interstitial
private void RequestInterstitialAd(){
if(interstitialAd != null)
interstitialAd.Destroy();
interstitialAd = new InterstitialAd(interstitialAdUnitId);
interstitialAd.OnAdClosed += HandleOnAdClosed;
AdRequest request = new AdRequest.Builder().Build();
interstitialAd.LoadAd(request);
}
public void ShowInterstitialAd(){
if (interstitialAd.IsLoaded()) {
interstitialAd.Show();
}
else{
StartCoroutine(AdClosedFunctionCall());
}
}
public void HandleOnAdClosed(object sender, EventArgs args)
{
RequestInterstitialAd();
StartCoroutine(AdClosedFunctionCall());
}
}
logcat
Admob Ad 不 运行 与 Unity 的主线程在同一线程上。
rewardedAd.OnAdClosed += HandleRewardedAdClosed;
从Admob的线程调用Unity的函数会出现意外错误。
首先,将 UnityMainThreadDispatcher 添加到您的项目中。 Admob回调调用的所有函数都需要UnityMainThreadDispatcher排队到主线程:
public void HandleRewardedAdClosed(object sender, EventArgs args)
{
UnityMainThreadDispatcher.Instance().Enqueue(()=>{
RequestRewardedAd();
StartCoroutine(AdClosedFunctionCall());
});
}
其次,您不应该使用 FindObjectOfType()。这是一项昂贵的操作,如果找不到 GameManagement 对象,您可能 运行 进入 NullReferenceException。由于此异常并未发生在 Unity 的主线程上,因此 logcat 消息很含糊。
您应该改用单例模式或观察者模式。
第三,即使用户跳过奖励广告,您也给予了奖励。使用 rewardedAd.OnUserEarnedReward
确保用户已获得奖励广告。