- Home /
MissingReferenceException after loading a scene, missing object of type text and button.
Hi,
So i have a GameOverMenu.cs which is attached to a GameOverMenu object with the UI for a Menu that activates when the player loses. In the GameOverMenu there's a button to buy lives for Ads. every time an Ad is seen the code reloads the LivesText so the "Lives Increase". Afterwards you can Go Back To Main Menu or Reload the level you just played. When i reload the level and the player loses again and i try to buy lives a get these two errors:
1. "MissingReferenceException: The object of type 'Text' 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. UnityEngine.EventSystems.UIBehaviour.IsActive () (at C:/Program Files/Unity/Hub/Editor/2019.3.0f6/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/EventSystem/UIBehaviour.cs:28) UnityEngine.UI.Graphic.SetVerticesDirty () (at C:/Program Files/Unity/Hub/Editor/2019.3.0f6/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Graphic.cs:249) UnityEngine.UI.Text.set_text (System.String value) (at C:/Program Files/Unity/Hub/Editor/2019.3.0f6/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Text.cs:211) GameOverMenu.SetLivesDisplay () (at Assets/Scripts/Utilities/GameOverMenu.cs:40) RewardedAds.OnUnityAdsDidFinish (System.String placementId, UnityEngine.Advertisements.ShowResult showResult) (at Assets/Scripts/Ads/RewardedAds.cs:64) UnityEngine.Advertisements.Platform.Platform+<>c_DisplayClass41_0.b_0 () (at Library/PackageCache/com.unity.ads@3.4.4/Runtime/Advertisement/Platform/Platform.cs:171) UnityEngine.Advertisements.Utilities.CoroutineExecutor.Update () (at Library/PackageCache/com.unity.ads@3.4.4/Runtime/Advertisement/Utilities/CoroutineExecutor.cs:17)"
2. "MissingReferenceException: The object of type 'Button' 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. UnityEngine.UI.Selectable.set_interactable (System.Boolean value) (at C:/Program Files/Unity/Hub/Editor/2019.3.0f6/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Selectable.cs:350) RewardedAds.OnUnityAdsReady (System.String placementId) (at Assets/Scripts/Ads/RewardedAds.cs:86) UnityEngine.Advertisements.Platform.Editor.EditorPlatform+<>c_DisplayClass13_0.b_2 () (at Library/PackageCache/com.unity.ads@3.4.4/Runtime/Advertisement/Platform/Editor/EditorPlatform.cs:67) UnityEngine.Advertisements.Utilities.CoroutineExecutor.Update () (at Library/PackageCache/com.unity.ads@3.4.4/Runtime/Advertisement/Utilities/CoroutineExecutor.cs:17)"
So, the second error didn't happened before so i probably did something there.
The code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GameOverMenu : MonoBehaviour
{
[SerializeField] public Text livesText = default;
[SerializeField] public Slider loadingBar;
[SerializeField] public GameObject loadingImage;
private AsyncOperation async;
public BallData ballData { get; set; }
[SerializeField] public int Level { get; set; }
[SerializeField] public int Lives { get; set; }
// Start is called before the first frame update
void Start()
{
loadingImage.SetActive(false);
SetLivesDisplay();
}
// Update is called once per frame
void Update()
{
}
public void GoBackToMenu()
{
SceneManager.LoadScene("Main Menu");
}
public void SetLivesDisplay()
{
LoadPlayer();
livesText.text = Lives.ToString(); **//First Error**
}
public void LoadPlayer()
{
//Load Game if there is no data then send to level 1
if (SaveSystem.SaveExists("GameData"))
{
ballData = SaveSystem.Load<BallData>("GameData");
Lives = ballData.Lives;
Level = ballData.Level;
}
else
{
//HardInput
Lives = 2;
}
}
public void AsyncLoadLastLevel()
{
loadingImage.SetActive(true);
StartCoroutine(LoadLastLevel());
}
IEnumerator LoadLastLevel()
{
LoadPlayer();
async = SceneManager.LoadSceneAsync(Level);
while (!async.isDone)
{
loadingBar.value = async.progress;
yield return null;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Advertisements;
using UnityEngine.SceneManagement;
public class RewardedAds : MonoBehaviour , IUnityAdsListener
{
#if UNITY_IOS
private string gameId = "3220555";
#elif UNITY_ANDROID
private string gameId = "3220554";
#endif
Button myButton;
string myPlacementId = "rewardedVideo";
bool testMode = true;
[SerializeField] GameOverMenu gameOverMenu = default;
public BallData ballData { get; set; }
[SerializeField] int Level { get; set; }
[SerializeField] int Lives { get; set; }
void Start()
{
Debug.Log("Rewarded Start Ran!");
Level = SceneManager.GetActiveScene().buildIndex;
ballData = SaveSystem.Load<BallData>("GameData");
Lives = ballData.Lives;
myButton = GetComponent<Button>();
//Interactivity is dependent to placement's status
myButton.interactable = Advertisement.IsReady(myPlacementId);
//Map the Show Rewarded Video Function to the button's click listener
if (myButton)
{
myButton.onClick.AddListener(ShowRewardedVideo);
}
// Initialize the Ads Listener and service
Advertisement.AddListener(this);
Advertisement.Initialize(gameId, testMode);
}
//function to show rewarded video ad
void ShowRewardedVideo()
{
Advertisement.Show(myPlacementId);
}
//implement iunityadslistener interface methods
public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
{
//define conditional logic for each ad completion status
if (showResult == ShowResult.Finished)
{
Lives++;
ballData = new BallData(Level, Lives);
SaveSystem.Save(ballData, "GameData");
Debug.Log("User saw the Ad, +1 lives!");
gameOverMenu.SetLivesDisplay();
}
else if (showResult == ShowResult.Skipped)
{
Debug.Log("The user skipped the Ad!");
}
else if (showResult == ShowResult.Failed)
{
Debug.LogWarning("The add did not finished the Ad due to an error.");
}
}
public void OnUnityAdsReady(string placementId)
{
//if the ready placement is rewarded && playerLives lower than 5 lives, activate button
if (placementId == myPlacementId && Lives < 5)
{
myButton.interactable = true;
Debug.Log("Button number of lives " + Lives);
}
else
{
myButton.interactable = false; **//Second Error**
}
}
public void OnUnityAdsDidError(string message)
{
//Log error
}
public void OnUnityAdsDidStart(string placementId)
{
//optional actions to take when the end user triggers an add
}
}
In the second image you can see the structure, inside the same object i have allocated both scripts. RewardedAds lives in Plus Lives and GameOverMenu lives in the Parent.everything if referenced through editor and i though that every time the scene loads the reference will "reload". But i'm getting the sense that that's not happening. Can it be that the LoadScene method is being called from within the same object? I've tried to transforn.Find() and GetChild on Start() but it is not working, as of now everything is being reference in editor.
Regards,