Roger Wang
Roger Wang

Reputation: 605

Why does my non-static GameObject lose its reference in a script after scene reloaded?

I have an empty GameObject on my Canvas used to display an ad menu, which I have attached to a separate script (not on the menu itself) in a public variable through the inspector.

I am setting it inactive in a script using adMenu.SetActive(false), which works on the first playthrough of my game. However, when I restart the scene through a button in my scene, the menu loses its reference to the same GameObject in the inspector, and I receive this error:

MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.

This has never happened to me with other GameObjects initialized in similar ways after a scene reload.

 

Additional details:

 

Code:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Advertisements;
using MEC;

public class AdManager : MonoBehaviour, IUnityAdsListener
{
    internal static AdManager instance;
    private static bool isInitialized = false;

    public GameObject adMenu;
    private string placement = "rewardedVideo";

    void Start()
    {
        instance = this;
        if (!isInitialized)
        {
            isInitialized = true;
            Advertisement.AddListener(this);
            Advertisement.Initialize(Constants.appleGameId, true);
        }
    }

    IEnumerator<float> ShowAd()
    {
        if (!Advertisement.IsReady())
        {
            yield return Timing.WaitForOneFrame;
        }
        Advertisement.Show(placement);
    }

    public void CloseAdMenu()
    {
        Debug.Log("Is adMenu null: " + (adMenu == null));  // Returns false on first playthrough only
        adMenu.SetActive(false);
    }


    public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
    {
        if (showResult == ShowResult.Finished)
        {
            CloseAdMenu();
        }
    }

    public void OnUnityAdsReady(string placementId)
    {
        // throw new System.NotImplementedException();
    }

    public void OnUnityAdsDidError(string message)
    {
        // throw new System.NotImplementedException();
    }

    public void OnUnityAdsDidStart(string placementId)
    {
        // throw new System.NotImplementedException();
    }
}

Upvotes: 0

Views: 1033

Answers (2)

derHugo
derHugo

Reputation: 90862

What happens has nothing to do with your menu object nor the static Instance.

The issue is the callback of

public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)

since you registered the instance via

Advertisement.AddListener(this);

but this instance will be Destroyer after the scene was changed.

As shown in the examples you should do

private void OnDestroy() 
{
    Advertisement.RemoveListener(this);
}

Upvotes: 1

Lotan
Lotan

Reputation: 4283

On your restart method, you should re-activate the button with adMenu.SetActive(true), if not, when you call the scene again, adMenu GameObject is disabled, so you can't access the GameObject.

Maybe you can add a method in your AdManager like:

public void OpenAdMenu()
{
    adMenu.SetActive(true);
}

and call it on AdManager.Start()

Upvotes: 0

Related Questions