I used the code from Unity and the rewards are multiples... first 1 then 2 then 3 and increasing... i tried deleting some code, but keep doing the same, then this happened.
I searched online and i couldn't find anything that explains clicking the rewarded ads button more than once.
Everything (apparently) is working fine only if i don't assing a button and leave the "SerializeField" empty, because if i remove the button, goes back to give more rewards... can somebody check this and tell me what's going on? i add the code Here
using UnityEngine;
using UnityEngine.Advertisements;
using UnityEngine.UI;
public class AdsInitializer : MonoBehaviour, IUnityAdsInitializationListener, IUnityAdsLoadListener, IUnityAdsShowListener
{
[SerializeField] string _androidGameId = "4634758";
[SerializeField] string _iOSGameId = "4634759";
[SerializeField] bool _testMode = false;
private string _gameId;
[SerializeField] Button _showAdButton;
[SerializeField] string rewardAndroidAdUnitId = "Rewarded_Android";
[SerializeField] string rewardiOSAdUnitId = "Rewarded_iOS";
string rewardAdUnitId = null; // This will remain null for unsupported platforms
void Awake()
{
_gameId = (Application.platform == RuntimePlatform.IPhonePlayer)
? _iOSGameId
: _androidGameId;
rewardAdUnitId = (Application.platform == RuntimePlatform.IPhonePlayer)
? rewardiOSAdUnitId
: rewardAndroidAdUnitId;
Advertisement.Initialize(_gameId, _testMode, this);
rewardAdUnitId = (Application.platform == RuntimePlatform.IPhonePlayer)
? rewardiOSAdUnitId
: rewardAndroidAdUnitId;
}
public void OnInitializationComplete()
{
Debug.Log("Unity Ads initialization complete.");
LoadRewardedAd();
}
public void OnInitializationFailed(UnityAdsInitializationError error, string message)
{
Debug.Log($"Unity Ads Initialization Failed: {error.ToString()} - {message}");
}
#region REWARDED ADS
public void LoadRewardedAd()
{
Debug.Log("Loading Ad: " + rewardAdUnitId);
Advertisement.Load(rewardAdUnitId, this);
}
public void ShowRewardedAd()
{
Advertisement.Show(rewardAdUnitId, this);
}
#endregion
public void OnUnityAdsAdLoaded(string adUnitId)
{
if (adUnitId.Equals(rewardAdUnitId))
{
// Configure the button to call the ShowAd() method when clicked:
//_showAdButton.onClick.AddListener(ShowRewardedAd);
// Enable the button for users to click:
//_showAdButton.interactable = true;
Debug.Log("RewardedAds Loaded");
}
}
public void OnUnityAdsShowComplete(string adUnitId, UnityAdsShowCompletionState showCompletionState)
{
if (adUnitId.Equals(rewardAdUnitId) && showCompletionState.Equals(UnityAdsShowCompletionState.COMPLETED))
{
Debug.Log("Unity Ads Rewarded Ad Completed");
// Grant a reward.
_showAdButton.onClick.RemoveAllListeners(); //with this line of code the problem is solved but shows the NullReference.
// Load another ad:
Advertisement.Load(rewardAdUnitId, this);
}
}
public void OnUnityAdsFailedToLoad(string adUnitId, UnityAdsLoadError error, string message)
{
if (adUnitId.Equals(rewardAdUnitId))
{
Debug.Log($"Error loading Ad Unit {adUnitId}: {error.ToString()} - {message}");
}
}
public void OnUnityAdsShowFailure(string adUnitId, UnityAdsShowError error, string message)
{
if (adUnitId.Equals(rewardAdUnitId))
{
Debug.Log($"Error showing Ad Unit {adUnitId}: {error.ToString()} - {message}");
}
}
public void OnUnityAdsShowStart(string adUnitId) { }
public void OnUnityAdsShowClick(string adUnitId) { }
void OnDestroy()
{
//with or without it doesn't change, it works only when the game is closed, and when reopen is working the same
//_showAdButton.onClick.RemoveAllListeners();
}
}
SOLVED!!
So, basically the script from Unity somehow has an unknown error, i couldn't explain myself how or from where... so the solution i fould was to add a bool in this case showAd = false and implemented it inside the showAd and the OnUnityAdsShowComplete functions, fortunatelly that was enough to solve the issue, now I can put the script in the button or in an AdManager and call the funtion from the button in the section OnClick() either way now is not showing neither error neither multiples with the rewards.
Hope it will be usefull for someone else.
using UnityEngine;
using UnityEngine.Advertisements;
using UnityEngine.UI;
public class AdsInitializer : MonoBehaviour, IUnityAdsInitializationListener, IUnityAdsLoadListener, IUnityAdsShowListener
{
[SerializeField] string _androidGameId = "4634758";
[SerializeField] string _iOSGameId = "4634759";
[SerializeField] bool _testMode = true;
private string _gameId;
[SerializeField] Button _showAdButton; //You can remove this if want to add the function manually from OnClick()
[SerializeField] string _androidAdUnitId = "Rewarded_Android";
[SerializeField] string _iOSAdUnitId = "Rewarded_iOS";
string _adUnitId = null; // This will remain null for unsupported platforms
private bool showAd = false;
void Awake()
{
InitializeAds();
Debug.Log("Awake");
_adUnitId = (Application.platform == RuntimePlatform.IPhonePlayer)
? _iOSAdUnitId
: _androidAdUnitId;
Debug.Log("the _adUnitId is: " + _adUnitId);
}
public void InitializeAds()
{
_gameId = (Application.platform == RuntimePlatform.IPhonePlayer)
? _iOSGameId
: _androidGameId;
Advertisement.Initialize(_gameId, _testMode, this);
}
public void OnInitializationComplete()
{
Debug.Log("Unity Ads initialization complete.");
LoadAd();
}
public void OnInitializationFailed(UnityAdsInitializationError error, string message)
{
Debug.Log($"Unity Ads Initialization Failed: {error.ToString()} - {message}");
}
public void LoadAd()
{
// IMPORTANT! Only load content AFTER initialization (in this example, initialization is handled on top of the script).
Debug.Log("Loading Ad: " + _adUnitId);
Advertisement.Load(_adUnitId, this);
}
// If the ad successfully loads, add a listener to the button and enable it:
public void OnUnityAdsAdLoaded(string adUnitId)
{
Debug.Log("Ad Loaded: " + adUnitId);
if (adUnitId.Equals(_adUnitId))
{
// Configure the button to call the ShowAd() method when clicked:
_showAdButton.onClick.AddListener(ShowAd); //You can remove this if want to add the function manually from OnClick()
// Enable the button for users to click:
_showAdButton.interactable = true; //You can remove this if want to add the function manually from OnClick()
}
}
// Implement a method to execute when the user clicks the button:
public void ShowAd()
{
if (showAd == false)
{
Debug.Log("Showing Ad");
// Disable the button:
_showAdButton.interactable = false; //You can remove this if want to add the function manually from OnClick()
// Then show the ad:
Advertisement.Show(_adUnitId, this);
_showAdButton.onClick.RemoveAllListeners(); //You can remove this if want to add the function manually from OnClick()
Debug.Log("All Listeners Removed");
showAd = true;
}
}
// Implement the Show Listener's OnUnityAdsShowComplete callback method to determine if the user gets a reward:
public void OnUnityAdsShowComplete(string adUnitId, UnityAdsShowCompletionState showCompletionState)
{
if (showAd == true)
{
if (adUnitId.Equals(_adUnitId) && showCompletionState.Equals(UnityAdsShowCompletionState.COMPLETED))
{
Debug.Log("Unity Ads Rewarded Ad Completed");
// Grant a reward.
// Load another ad:
Advertisement.Load(_adUnitId, this);
showAd = false;
}
}
}
public void OnUnityAdsFailedToLoad(string adUnitId, UnityAdsLoadError error, string message)
{
Debug.Log($"Error loading Ad Unit {adUnitId}: {error.ToString()} - {message}");
// Use the error details to determine whether to try to load another ad.
}
public void OnUnityAdsShowFailure(string adUnitId, UnityAdsShowError error, string message)
{
Debug.Log($"Error showing Ad Unit {adUnitId}: {error.ToString()} - {message}");
// Use the error details to determine whether to try to load another ad.
}
public void OnUnityAdsShowStart(string adUnitId) { }
public void OnUnityAdsShowClick(string adUnitId) { }
}
Related
In my project, the banner opens after the scene is reloaded, everything seems to be in order in the editor.
Everything works fine in the editor, I checked it, but it’s only worth building the project on Android, it doesn’t work there normally. It will appear only after the scene is reloaded, and then not immediately with a delay of 2-3 seconds.
My code:
using UnityEngine;
using System.Collections;
using UnityEngine.Advertisements;
public class BannerAd : MonoBehaviour
{
[SerializeField] BannerPosition _bannerPosition;
[SerializeField] private string _androidAdUnitId = "Banner_Android";
[SerializeField] private string _iOSAdUnitId = "Banner_iOS";
private string _adUnitId;
private void Awake()
{
_adUnitId = (Application.platform == RuntimePlatform.IPhonePlayer)
? _iOSAdUnitId
: _androidAdUnitId;
}
private void Start()
{
Advertisement.Banner.SetPosition(_bannerPosition);
LoadBanner();
}
private IEnumerator LoadAdBanner()
{
yield return new WaitForSeconds(1f);
LoadBanner();
}
public void LoadBanner()
{
BannerLoadOptions options = new BannerLoadOptions
{
loadCallback = OnBannerLoaded,
errorCallback = OnBannerError
};
Advertisement.Banner.Load(_adUnitId, options);
}
private void OnBannerLoaded()
{
Debug.Log("Banner loaded");
ShowBannerAd();
}
private void OnBannerError(string message)
{
Debug.Log($"Banner Error: {message}");
}
public void ShowBannerAd()
{
BannerOptions options = new BannerOptions
{
clickCallback = OnBannerClicked,
hideCallback = OnBannerHidden,
showCallback = OnBannerShown
};
Advertisement.Banner.Show(_adUnitId, options);
}
public void HideBannerAd()
{
Advertisement.Banner.Hide();
}
private void OnBannerClicked() { }
private void OnBannerShown() { }
private void OnBannerHidden() { }
}
It might be the ad is still not initialized when you call LoadBanner so it doesn't work at first. The best is to call LoadBanner when Initialization is complete. Set _testMode to true or false based on your need.
public class BannerAd : MonoBehaviour, IUnityAdsInitializationListener
{
[SerializeField] bool _testMode = true;
private string _adUnitId;
void Awake()
{
InitializeAds();
}
public void InitializeAds()
{
_adUnitId = (Application.platform == RuntimePlatform.IPhonePlayer)
? _iOSGameId
: _androidGameId;
Advertisement.Initialize(_adUnitId, _testMode, this);
}
public void OnInitializationComplete()
{
LoadBanner();
}
//rest of the code
}
}
[EDIT] Everything is working now! Thank's to #MrMoonMan!
As the title says, I'm working on a mobile game and I just implemented a Check Update popup.
The thing is, the popup is displayed every time the menu scene is loaded, and this is very annoying because if the player goes to the weapon menu and then comes back to the main menu 10 times, he will see the popup 10 times. The goal is to have the popup appear only once per game session, Here is what I tried for the moment but without success:
Using a bool variable
Destroy the gameobject to which the checkupdate script is attached when the user presses the "No Thank's" button
Here is the code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class CheckUpdate : MonoBehaviour
{
public string versionUrl = "";
public string currentVersion;
private string latestVersion;
public GameObject newVersionAvailable;
private static bool hasBeenChecked = false;
void OnAwake()
{
DontDestroyOnLoad(this);
StartCoroutine(LoadTxtData(versionUrl));
}
private IEnumerator LoadTxtData(string url)
{
UnityWebRequest loaded = new UnityWebRequest(url);
loaded.downloadHandler = new DownloadHandlerBuffer();
yield return loaded.SendWebRequest();
latestVersion = loaded.downloadHandler.text;
CheckVersion();
}
private void CheckVersion()
{
Debug.Log("currentVersion = " + currentVersion);
Debug.Log("latestVersion = " + latestVersion);
Version versionDevice = new Version(currentVersion);
Version versionServer = new Version(latestVersion);
int result = versionDevice.CompareTo(versionServer);
if ((latestVersion != "") && (result < 0))
{
newVersionAvailable.SetActive(true);
}
if (GetChecked())
return;
}
public void ClosePopUp(GameObject obj)
{
obj.SetActive(false);
Destroy(this);
}
public void OpenURL(string url)
{
Application.OpenURL(url);
}
public static bool GetChecked()
{
if (hasBeenChecked)
{
return hasBeenChecked;
}
hasBeenChecked = true;
return false;
}
}
EDIT
Ok so you mentioned that it still happens every time the scene is reloaded. That is because the object is created when the scene is loaded. It isn't saved between scenes. To handle that properly you need to tell it to not get destroyed when the scene is unloaded and to do that is simple, and that is by Adding DontDestroyOnAwake. Here is an example of the code:
public class CheckUpdate : MonoBehaviour
{
public string versionUrl = "";
public string currentVersion;
private string latestVersion;
public GameObject newVersionAvailable;
void OnAwake()
{
DontDestroyOnLoad(this);
}
void OnStart()
{
StartCoroutine(LoadTxtData(versionUrl));
}
private IEnumerator LoadTxtData(string url)
{
UnityWebRequest loaded = new UnityWebRequest(url);
loaded.downloadHandler = new DownloadHandlerBuffer();
yield return loaded.SendWebRequest();
latestVersion = loaded.downloadHandler.text;
}
private void CheckVersion()
{
Debug.Log("currentVersion = " + currentVersion);
Debug.Log("latestVersion = " + latestVersion);
Version versionDevice = new Version(currentVersion);
Version versionServer = new Version(latestVersion);
int result = versionDevice.CompareTo(versionServer);
if ((latestVersion != "") && (result < 0))
{
newVersionAvailable.SetActive(true);
}
}
public void ClosePopUp(GameObject obj)
{
obj.SetActive(false);
}
public void OpenURL(string url)
{
Application.OpenURL(url);
}
}
,,Menu scene''? It sound some suspicious. If you load and unload whole new scene as menu, state as bool field in MonoBehaviours or modifing the scene structure (destory, create object) will not work beacuse allways will be loaded new scene from scratch. ;)
If you have to have menu on seperated scene use someting other to manage the state. For example:
DontDestoryOnLoad objects.
Or some C# static class or singleton (not a MonoBehaviour).
I added Unity Ads to my project.
At the first run at all works good and it show that an ad will show, but when I hit play the second time it give me this error
MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
This is my script for the ads :
public class Monetization : MonoBehaviour, IUnityAdsListener
{
string GooglePlay_ID = "****";
bool GameMode = true;
string myPlacementId = "rewardedVideo";
void Start()
{
Advertisement.AddListener(this);
Advertisement.Initialize(GooglePlay_ID, GameMode);
}
public void ShowRewardedVideo()
{
// Check if UnityAds ready before calling Show method:
if (Advertisement.IsReady(myPlacementId))
{
Advertisement.Show(myPlacementId);
}
else
{
Debug.Log("Rewarded video is not ready at the moment! Please try again later!");
}
}
// Implement IUnityAdsListener interface methods:
public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
{
// Define conditional logic for each ad completion status:
if (showResult == ShowResult.Finished)
{
// Reward the user for watching the ad to completion.
SceneManager.LoadScene(4);
}
else if (showResult == ShowResult.Skipped)
{
// Do not reward the user for skipping the ad.
}
else if (showResult == ShowResult.Failed)
{
Debug.LogWarning("The ad did not finish due to an error.");
}
}
public void OnUnityAdsReady(string placementId)
{
// If the ready Placement is rewarded, show the ad:
if (placementId == myPlacementId)
{
// Optional actions to take when the placement becomes ready(For example, enable the rewarded ads button)
}
}
public void OnUnityAdsDidError(string message)
{
// Log the error.
}
public void OnUnityAdsDidStart(string placementId)
{
// Optional actions to take when the end-users triggers an ad.
}
}
When you load a new scene, the game objects in the previous scene will be destroyed. To prevent this add the following function in your Monetization script.
void Awake() {
DontDestroyOnLoad(this.gameObject);
}
I am using Unity 2019.2.8f1 and I am preparing to publish my first game on Google Play Store. Unfortunately the reward is not being given to the user after watching a rewarded ad. The user should get an extra life whenever he/she watches a rewarded ad.
Here is my Ad Manager script. I am using dummy ids for testing.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleMobileAds.Api;
using System;
public class AdManager : MonoBehaviour
{
public static AdManager instance;
private string AppId = "ca-app-pub-3940256099942544~3347511713";
private BannerView banner;
private string bannerID = "ca-app-pub-3940256099942544/6300978111";
private InterstitialAd videoAD;
private string videoID = "ca-app-pub-3940256099942544/1033173712";
private int showing, video;
private RewardBasedVideoAd rewardedAds;
private string rewardedID = "ca-app-pub-3940256099942544/5224354917";
public bool RewardTaken;
public void HandleRewardBasedVideoClosed(object sender, EventArgs args)
{
Debug.Log("HandleRewardBasedVideoClosed event received");
RequestRewardedAD();
}
public void HandleRewardBasedVideoRewarded(object sender, Reward args)
{
UIManager.variable.RewardPanel.SetActive(true);
UIManager.variable.gameOver.SetActive(false);
}
private void Awake()
{
rewardedAds = RewardBasedVideoAd.Instance;
showing = PlayerPrefs.GetInt("show");
video = PlayerPrefs.GetInt("video");
MobileAds.Initialize(AppId);
RequestvideoAD();
if (instance == null)
{
instance = this;
}
else
{
Destroy(this);
}
}
private void Start()
{
RewardTaken = false;
if (video == 1)
{
ShowvideoAD();
}
if (showing == 1)
{
requestBanner();
}
RequestRewardedAD();
// Called when the user should be rewarded for watching a video.
rewardedAds.OnAdRewarded += HandleRewardBasedVideoRewarded;
// Called when the ad is closed.
rewardedAds.OnAdClosed += HandleRewardBasedVideoClosed;
}
public void requestBanner()
{
banner = new BannerView(bannerID, AdSize.Banner, AdPosition.Bottom);
AdRequest request = new AdRequest.Builder().Build();
banner.LoadAd(request);
banner.Show();
}
public void RequestvideoAD()
{
videoAD = new InterstitialAd(videoID);
AdRequest request = new AdRequest.Builder().Build();
videoAD.LoadAd(request);
}
public void ShowvideoAD()
{
if (videoAD.IsLoaded())
{
videoAD.Show();
}
else
{
Debug.Log("FullscreenADNotLoaded");
}
}
public void RequestRewardedAD()
{
AdRequest request = new AdRequest.Builder().Build();
rewardedAds.LoadAd(request,rewardedID);
}
public void ShowRewardedAD()
{
if(rewardedAds.IsLoaded())
{
rewardedAds.Show();
Debug.Log("Ads Are Working");
}
else
{
Debug.Log("Rewarded Ads not laded properly");
}
}
public void HideAD()
{
banner.Hide();
}
}
Even though the console was not showing any message that I wanted to show as a part of the test. After trying several times, I decided to remove the debug text.
It looks like you are attaching Callbacks to a different ad object and you are loading ads from a different object.
Try using rewardedAds
to Load Ad
public void RequestvideoAD()
{
AdRequest request = new AdRequest.Builder().Build();
rewardedAds.LoadAd(request);
}
This is the code "template" I used for adverts in my project. Although the adverts are working (A bit slow when testing). Unity gives me this: "ShowOptions.resultCallback' is obsolete: 'Implement IUnityAdsListener and call Advertisement.AddListener(). I tried to do adverts by using a listener, but it failed to work... Any suggestions?
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Advertisements;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class PlayerController : MonoBehaviour
{
string gameId;
bool testMode;
string placementId;
void Start()
{
gameId = "<my id here>";
testMode = false;
placementId = "<placement id here>";
Advertisement.Initialize(gameId, true);
}
void ShowAd()
{
if (Application.internetReachability == NetworkReachability.NotReachable)
{
//Give internet connectivity feedback here
}
else
{
ShowOptions options = new ShowOptions();
options.resultCallback = HandleShowResult;
Advertisement.Show(placementId, options);
}
}
void HandleShowResult(ShowResult result)
{
switch (result)
{
case ShowResult.Finished:
//Advert completed
break;
case ShowResult.Skipped:
//Advert skipped
break;
case ShowResult.Failed:
//Advert failed
break;
}
}
}
Image:The error I get when using the listener method
The error basically tells you exactly what to do:
ShowOptions.resultCallback' is obsolete: 'Implement IUnityAdsListener and call Advertisement.AddListener()'
In the API there is a complete example! Adopted to your code:
public class PlayerController : MonoBehaviour, IUnityAdsListener
{
private string gameId;
private bool testMode;
private string placementId;
private bool adsAreReady;
private void Start()
{
gameId = "<my id here>";
testMode = false;
placementId = "<placement id here>";
// WAIT FOR ADS
Advertisment.AddListener(this);
Advertisement.Initialize(gameId, true);
}
public void ShowAd()
{
if (Application.internetReachability == NetworkReachability.NotReachable)
{
//Give internet connectivity feedback here
return;
}
if(!adsAreReady)
{
// Give not ready yet feedback
return;
}
ShowOptions options = new ShowOptions();
Advertisement.Show(placementId, options);
}
// Implement IUnityAdsListener interface methods:
public void OnUnityAdsDidFinish (string placementId, ShowResult showResult)
{
// Define conditional logic for each ad completion status:
switch(showResult)
{
case ShowResult.Finished:
// Reward the user for watching the ad to completion.
break;
case ShowResult.Skipped:
// Do not reward the user for skipping the ad.
break;
case ShowResult.Failed:
Debug.LogWarning (“The ad did not finish due to an error.);
break;
}
}
public void OnUnityAdsReady (string placementId)
{
if (placementId != myPlacementId) return;
adsAreReady = true;
}
public void OnUnityAdsDidError (string message)
{
// Log the error.
}
public void OnUnityAdsDidStart (string placementId)
{
// Optional actions to take when the end-users triggers an ad.
}
}
NOTE that in your code you never call ShowAdd .. it should probably be public and called from somewhere else.