Search Unity

Question placementId cannot be nil or empty

Discussion in 'Unity Ads & User Acquisition' started by FoxAdventures, Apr 24, 2022.

  1. FoxAdventures

    FoxAdventures

    Joined:
    Jan 31, 2018
    Posts:
    77
    So I had to integrate Unity Ads to my game, and because of the way everything is structured and my lack of knowledge on ads integration, I set up a bit of a confusing system. I will have to explain it best I can so that my question makes more sense (I will also be including the codes which I am about to mention):

    On game launch, it always opens on an empty scene which then directs the player to whichever scene they were in in their save file.

    There is the AdsInitializer script in the entrance scene and also a DontDestroyOnLoad script attached to the same gameobject.

    In every other scene, there is the InterstitialAdsButton script attached to all the buttons that need to invoke the ad when pressed. I have a list of objects of which InterstitialAdsButton script is attached to. The list is in AdsInitializer and it updates every time we go into a new scene.

    There is a UI master script that handles all of the buttons. I add and remove the buttons to the list, which is in AdsInitializer, in this script. It clears the list on Start and adds the right ones in that scene, so that we don't have leftover buttons or empty list items from the previous scene.

    I show the ads when a button is clicked through the UI script.

    So far, so good. When I play in the editor, the placeholder screen for the ads do show. However, I receive the error "placementId cannot be nil or empty" for every ad that I have in the scene. But this only happens in the first level that I load. As I progress through the game, or even if I die and hit Restart, it doesn't give that error anymore. I am suspecting that it is because it takes some time between the ads list to get cleared and then updated, so that's why the error shows? But that doesn't really explain why it only happens once. Would this even be a big deal at all if I published the game like this? Either way, how would I go about fixing it?

    Here are the codes:
    AdsInitializer.cs
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Advertisements;
    3. using System;
    4. using System.Collections.Generic;
    5.  
    6.  
    7. public class AdsInitializer : MonoBehaviour, IUnityAdsInitializationListener
    8. {
    9.     private static AdsInitializer adsInstance;
    10.  
    11.  
    12.     [SerializeField] string _androidGameId;
    13.     [SerializeField] string _iOSGameId;
    14.     [SerializeField] bool _testMode = true;
    15.     private string _gameId;
    16.  
    17.     public List<InterstitialAdsButton> adsList;
    18.  
    19.     void Awake()
    20.     {
    21.         DontDestroyOnLoad(this);
    22.  
    23.         if (adsInstance == null)
    24.         {
    25.             adsInstance = this;
    26.         }
    27.         else
    28.         {
    29.             Destroy(gameObject);
    30.         }
    31.  
    32.         InitializeAds();
    33.     }
    34.  
    35.     private void Start()
    36.     {
    37.         print("started");
    38.     }
    39.  
    40.     public void InitializeAds()
    41.     {
    42.         _gameId = (Application.platform == RuntimePlatform.IPhonePlayer)
    43.             ? _iOSGameId
    44.             : _androidGameId;
    45.         Advertisement.Initialize(_gameId, _testMode, this);
    46.     }
    47.  
    48.     public void OnInitializationComplete()
    49.     {
    50.         Debug.Log("Unity Ads initialization complete.");
    51.        
    52.         for(int i = 0; i < adsList.Count; i++) { adsList[i].LoadAd(); }
    53.  
    54.     }
    55.  
    56.     public void OnInitializationFailed(UnityAdsInitializationError error, string message)
    57.     {
    58.         Debug.Log($"Unity Ads Initialization Failed: {error.ToString()} - {message}");
    59.     }
    60. }

    StartStopUI.cs (only part of it, since the whole script is irrelevant and much longer)
    Code (CSharp):
    1. public class StartStopUI : MonoBehaviour
    2. {
    3.     //Ads
    4.     InterstitialAdsButton[] int_ads;
    5.     AdsInitializer adsIn;
    6.     private void Awake()
    7.     {
    8.         adsIn = GameObject.FindObjectOfType<AdsInitializer>();
    9.         adsIn.adsList.Clear();
    10.         int_ads = GameObject.FindObjectsOfType<InterstitialAdsButton>(true);
    11.         for (int i = 0; i < int_ads.Length; i++)
    12.         {
    13.             if (!adsIn.adsList.Contains(int_ads[i]))
    14.             {
    15.                 adsIn.adsList.Add(int_ads[i]);
    16.  
    17.             }
    18.         }
    19.     }
    20.  
    21. public void GoToNextScene()
    22.     {
    23.         for (int i = 0; i < int_ads.Length; i++)
    24.         {
    25.             if (int_ads[i].gameObject.name.Equals("StopButton"))
    26.             {
    27.                 int_ads[i].ShowAd();
    28.             }
    29.         }
    30.  
    31.         AnalyticsManager.instance.OnLevelComplete(level);
    32.         print(scene.buildIndex + " . . . " + SceneManager.sceneCountInBuildSettings);
    33.         Iterate();
    34.         SceneManager.LoadScene(scene.buildIndex + 1);
    35.     }
    36.  
    37. public void Restart()
    38.     {
    39.         for (int i = 0; i < int_ads.Length; i++)
    40.         {if (int_ads[i].gameObject.name.Equals("RestartButton"))
    41.             {
    42.                 int_ads[i].ShowAd();
    43.             }
    44.         }
    45.  
    46.         AnalyticsManager.instance.OnLevelFail(level);
    47.  
    48.         SceneManager.LoadScene(scene.name);
    49.  
    50.     }
    51.  
    52. }

    The whole thing is pretty confusing to me so I tried to tell it as simple as possible. My apologies if I somehow made it worse.
     
  2. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    626
    Please make sure that the placementId you pass in when calling the Advertising.Load and Advertising.Show methods is not an empty string.
     
  3. FoxAdventures

    FoxAdventures

    Joined:
    Jan 31, 2018
    Posts:
    77
    So I've been looking into this problem-- here's how I "fixed" it, but I'm not satisfied since this is a temp solution at best.

    I changed the code a lot so now it's a lot less complicated and only keeps track of 1 ad, since that's how many it will be in any given scene.

    The problem is that
    Code (CSharp):
    1.  public void LoadAd()
    2.     {
    3.         // IMPORTANT! Only load content AFTER initialization (in this example, initialization is handled in a different script).
    4.         Debug.Log("Loading Ad: " + _adUnitId);
    5.         Advertisement.Load(_adUnitId, this);
    6.     }
    In here, it doesn't register _adUnitId as ios or Android. Is this because I'm on PC? Anyway, the fix that I came up with is just changing _adUnitId with the android unit ID since this app is only going to be releasing for Android, and now I don't get any error messages. But this feels like a cop-out. There's gotta be a better way to do this. Am I just to make a simple if-else and say "load android ID if the platform is Android, load iOS ID if it's iOS" ? Or do I just change the code to use the iOS placement ID if I ever release an iOS build?
     
  4. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    626
    Please make sure to use the Unit IDs of the corresponding platform, both methods you mentioned are fine, which one you choose is up to you.
     
  5. MicasDev

    MicasDev

    Joined:
    Apr 10, 2022
    Posts:
    8
    hey do you know how to fix that it gets none-interactable?
     
  6. FoxAdventures

    FoxAdventures

    Joined:
    Jan 31, 2018
    Posts:
    77
    I'm not sure what you mean by that.
     
  7. MicasDev

    MicasDev

    Joined:
    Apr 10, 2022
    Posts:
    8
    its getting invisible and i cant click it
     
  8. MicasDev

    MicasDev

    Joined:
    Apr 10, 2022
    Posts:
    8
    and the comments in the script says it will be able to be clicked when it has loaded an ad but the console said it already loaded an ad, and when i look at the button its not interactable
     
  9. FoxAdventures

    FoxAdventures

    Joined:
    Jan 31, 2018
    Posts:
    77
    Yes it did appear to be glitching when I tried to analyze the console message when I was having this problem. I think I got around this by clicking on the lower message boxes first. But if you're having the same problem as I am, then the solution should also be pretty much the same. Have you read the thread in its entirety?
     
  10. Irvin_VA

    Irvin_VA

    Joined:
    Jun 11, 2022
    Posts:
    1
    Hi, I had this problem too, but I fixed it by going to "File" -> "Biuld Settings" then select "Android" and "Switch Platform"
     
    Hookey6, D_Sol, GamDevPro and 3 others like this.
  11. LostShepherd

    LostShepherd

    Joined:
    May 31, 2019
    Posts:
    38
    Hi,

    I have been having the same issue and think I worked out the problem, at least in my case.

    I had the RewardedAds script on a panel, the Rewarded Ad button was a child button on that panel, both are disabled by default on startup, as I only wanted to enable them once needed.

    The issue seems to be that the Awake() method in my RewardedAdsButton script was not called prior to my AdsInitializer.OnInitializationComplete call to RewardedAdsButton.LoadAd(). As a result of this the Awake() code

    Code (CSharp):
    1.         #if UNITY_IOS
    2.                 _adUnitId = _iOSAdUnitId;
    3.         #elif UNITY_ANDROID
    4.                 _adUnitId = _androidAdUnitId;
    5.         #endif
    never gets called, so _adUnitId is not set, then I get the following logs

    Unity Ads initialization complete.
    Loading Ad:
    placementId cannot be nil or empty

    The simple solution I had was to enable both the panel and button by default, but have their parent panel disabled, this way they never showed on app start, but did get initialised.

    The one thing I don't understand is how previously when AdsInitializer.OnInitializationComplete called RewardedAdsButton.LoadAd() it actually went into the LoadAd() method but Awake was not called first.

    At any rate hope this is useful this solved it for me and it was caused by objects not being enabled on start of application by default.

    Thanks,
    LS
     
    davidruedamartin26 and Bokky-T like this.
  12. Galaxy-1-Studios

    Galaxy-1-Studios

    Joined:
    Apr 28, 2021
    Posts:
    2
    This helped with the error, but my button remains to be not interactive (interactable = false) for some reason... I got the debug.log saying that the ad was loaded.
     
    LostShepherd likes this.
  13. grantar2k

    grantar2k

    Joined:
    Jun 6, 2017
    Posts:
    5
    I've come up with a solution for this after having this problem. As stated above the Rewarded Ad button will not work if the button is disabled in the inspector at the start of game "If you call it then". What i did was setup another function to call the rewardedAdsButton.LoadAd(), so for example, if i want the rewarded ad button to work after a battle, I would first enable the panel that it is on, then call the rewardedAdsButton.LoadAd() to Initialize that ad for that button. This will solve both issues.
     
  14. wernergast

    wernergast

    Joined:
    Jul 12, 2022
    Posts:
    18
    I have the same problem. The button is a child button. How did you fix it? I do not have many experience.
    When I do right mouse -> set as default parent -> its not working

    upload_2023-3-24_9-49-39.png
     

    Attached Files:

  15. ege_yildirim2005

    ege_yildirim2005

    Joined:
    Feb 11, 2021
    Posts:
    1
    GUYS i found another way LostShepherd said "The issue seems to be that the Awake() method in my RewardedAdsButton script was not called prior to my AdsInitializer.OnInitializationComplete call to RewardedAdsButton.LoadAd(). As a result of this the Awake() code" so i make the reward ads button active in the inspector then in my script i just make setactive(false) in void Start() so its get initialize in awake than buttons are going to invisible and EVERYTHING WORKS FINE IM brilliant.
     

    Attached Files:

  16. iammartaribeiro

    iammartaribeiro

    Joined:
    Sep 11, 2023
    Posts:
    1
    awesome, i had the same issue and i was able to solve it this way :)