The object of type X has been destroyed but you are still trying to access it.

Hello everyone,

I’m in quite a pickle here as can’t find any answers to match my situation.

In my game (UI based) i have 3 scenes:

SCENE 1:

Is just generic loading page which connects to the backend and moves to next scene when connection has been established.

SCENE 2:

Is a login page. When the connection to the backend is established, an event is triggered which checks if the user is currently logged in by checking the presence of an AES encrypted file and if it exists it decrypts it and passes the login details or auth token to an authentication method which authenticates the user to the backend.

If user is already logged in (encrypted file exists) they won’t even see SCENE 2…unless the credentials have changed in the meantime, of course. The above happens quickly and when complete it loads SCENE 3.

If the user is not logged in (encrypted file doesn’t exist), then they are prompted for username and password and the LOGIN button creates the file, authenticates the user to the backend and loads SCENE 3.

SCENE 3:

This, as you suspected is the main scene. Stuff happens here with events sent to the backend, handling of responses, UI changes and the works. Normal stuff…

Now…here’s the catch. There’s a LOGOUT button in this scene which when pressed it does the following (in this order):

  • Deletes the encrypted file holding the current credentials
  • Resets the connection to the backend
  • Goes back to SCENE 2
    (nothing else)

This works as intended. The user then logs in and SCENE 3 is loaded with the current user’s stats pulled from the backend. But when I interact with any object in the scene I get the below error.

If I close the application and reopen it it goes through the normal process as above and everything works ok. So it’s got to be because I went from SCENE 3 to SCENE 2…then back to SCENE 3.

I can’t figure out what to do to discard SCENE 3 when player logs out and then reload a fresh SCENE 3 when they log in (in the same session).

There are no DoNotDestroyOnLoad objects in scene 3.

I hope the above makes sense.

Many thanks for your time and assistance.

Alex

2 Likes

The error is:

MissingReferenceException: The object of type X 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.

Where X is the object name that was affected by the action. So it’s not just TEXT. It depends on what the first interraction with the scene is and what script gets called.

UPDATE:

I’m getting a bit closer to fixing this. I have added the below wrapper:

if(this!=null)
{

// function body

}

to 6 functions in 6 scripts which are referenced in SCENE 3. And now it works as intended. But it doesn’t seem very efficient. Especially since the scene will grow a lot still as I’m just at the beginning of developing this game. Is there another way of solving this?

Worth noting: All the functions that I added the above wrapper to are functions that are called by an event (not the same event, mind you) i.e:

void Start () {
        GameManager.OnPopUp += PopUp;
      }
 
    public void PopUp()
    {
        if (this != null)
        {
            anim = GetComponent<Animator>();
            anim.enabled = true;
            anim.SetTrigger("Slideup");
        }
    }

So maybe this means something to a more seasoned developer?

2 Likes

Hello.
I think that the OP has solved his issue, but I will share my solution for future reference.
I faced the same problem and found out that the culprit is the event.
When you first add a listener to an event that is in a static class of your own, which is what I’ve done and what the OP was probably doing in this line :

  • void Start () {
  • GameManager.OnPopUp += PopUp;
  • }

The listener that is added will stay there even if the game-object holding the script is destroyed.
So when you change the scene, that script with the event listener will be destroyed but the listener will stay, and when you open the scene again, (regardless of adding a new listener) then call the event from somewhere, that old listener will be called but it’s script (and object)will be missing, thus throwing that exception.
The solution is at Awake or Start, to either remove all listeners of your event, or check if any of them has the same name as the one you’re going to add.
One way to do that would be :

 public delegate void EventType();
 public static event EventType EventInstanceName;
public static void RemoveEventListener(Action methodListener)
    {
        foreach (Delegate d in EventInstanceName.GetInvocationList())
            if (d.Method.Name == method.Method.Name)
                EventInstanceName-= (EventType)d;
    }

This should be in the class managing the event.

16 Likes

I think I’m hitting the same issue, but I’m new to this and dont understand the fix above, or where to even put it.
I have a scene2 scene which is working fine standalone.
It has a level generator in it which creates a load of pieces.

I’ve now added a mainmenu scene before it. Which works fine once, but if I then go back to main menu and back to scene2, it falls over with:

MissingReferenceException: The object of type ‘LevelPiece’ 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.Component.GetComponent[SpriteRenderer] () (at C:/buildslave/unity/build/artifacts/generated/common/runtime/ComponentBindings.gen.cs:48)
LevelGenerator.UpdateSprites () (at Assets/scripts/LevelGenerator.cs:485)
LevelGenerator.Start () (at Assets/scripts/LevelGenerator.cs:35)

This first seems to fail at the part of my level generator where I’ve already created by pieces, and am now going through them one my one updating the sprite paths.

SpriteRenderer[ ] renderer;
Sprite RunwayOut;
Sprite CommsTower;
Sprite ControlTower;
renderer = new SpriteRenderer[pieces.Count];
for (int x=0;x<pieces.Count;x++){
renderer[×] = pieces[×].GetComponent();

Looks like it fails in other places afterwards.

Finally, as I say this was all developed in scene2, with all the functionality in one scene initially. Now that I have added a main menu, should I be moving all of my level generation stuff into the main menu, and referencing it from scene2?
The mainmenu already has DontDestroyOnLoad (transform.gameObject); so I can read variables from it.
Or should it stay in scene2 and be regenerated each time?

Thanks in advance.

Not sure if it helps, but my LevelGenerator script is a singleton.
And looks like :

void Awake(){
instance = this;
}

// Use this for initialization
void Start () {
GenerateInitialPieces ();
GenerateTextPieces ();
PrintValues ();
//Debug.Log (“Calling Sprite Update”);
UpdateSprites ();

}
When I run from the menu for the first time, all is OK, and I can see all of my LevelPieces that have been generated in the hierarchy.
When I exit back to the menu, by entire scene2 disssapears from the hierarchy.
When I go back into scene2 from the main menu, I once again see all of the levelpieces that have been generated on my canvas.
So they are being recreated.
However, I have noticed that they begin at sequence/index 34.
It uses pieces.Count to get this when creating the objects in the list, so it does look like I need to somehow destroy the old list first.

From what I can see I’m creating a new one in the LevelGenerator script.
public class LevelGenerator : MonoBehaviour {
public static LevelGenerator instance;
public Transform levelStartPoint;
public static List pieces = new List ();
public static List textPieces = new List ();
public LevelPiece LevelPiece;
public TextPiece TextPiece;
private StandardVars standardVars = new StandardVars();
private int lastPiece;

Please use code tags, as described in the first (pinned) post in every forum here. Posting code without using the code tags properly makes it nigh-unreadable, and most people here won’t even bother trying to decipher it.

The general idea (in response to the OP) is that any object that handles adding a delegate to an event needs to handle removing that delegate when it’s destroyed. It’s that simple. There’s the built-in OnDestroy method that makes this process easier if needed.

As to your specific issue newcoder, there aren’t any events or delegates that I see in the code you’ve posted (I think), so either the problem is occurring elsewhere or your issue is unrelated to the OP’s issue, aside from you both trying to access a destroyed object. In your case, my guess is that you have a singleton with DontDestroyOnLoad, you’re filling it with references to LevelPieces as you create them, but you aren’t clearing the list when the scene is changed so it’s still trying to access old pieces when you go to make the new ones.

Toss pieces.Clear() / textPieces.Clear() at the top of the GenerateInitialPieces or GenerateTextPieces or whatever and you should be fine. If your singleton is on a DontDestroyOnLoad object, keep in mind that Awake and Start only get called once when the object is first created, not once per scene load, and if you’re not using DontDestroyOnLoad but recreating the singleton when the scene is loaded, then consider not using static objects, because they’re (pointlessly) keeping their values across scene loads.

1 Like

Thank you for your detailed reply. And apologies for the code tags.
That does sound likely be the cause.
I’ve just checked and it is a singleton:

public class LevelGenerator : MonoBehaviour {
   public static LevelGenerator instance;
   public Transform levelStartPoint;
   public static List<LevelPiece> pieces = new List<LevelPiece> ();
   public LevelPiece LevelPiece;
   void Awake(){
       instance = this;
   }

I’ve made no attempt to clear the list. I’d just assumed it all got destroyed and started again when the scene was terminated - and a new scene was same as starting from the beginning.

In fact, one of the first things I was going to try when I got home was to add something to the onDestroy method to remove all pieces one by one and see if that helped, but I will try your suggestion first.

edit: Actually, I’m pretty certain I DO NOT have DoNoDestroyOnLoad set on the levelgenerator script. The only place I put this was on a UImanager script on the Main Menu scene, and that was only so I could reference variables from it within my scene2 (which is were the level generator is). Does this still sound like the issue? I’ll try it anyway.

edit2:
The error I’m getting is actually from the levelGenerator script. I note you suggest that a singleton elsewhere may be trying to reference them, but it is actually itself.

To explain, my code generates (lets say 18) objects.
It then goes through each one in a loop checking a flag and amending the sprite path.
On first run these objects are numbered 0-17 internally

But on the 2nd run they are labelled internally 18-35.
And the first place I get the error is the loop that goes from 0 to <pieces.Count

I think the answer you posted may still be the correct answer, but I’m not sure my scenario matches what you are suggesting exactly. I wont be able to try it for a good few hours unfortunately.

Thanks again.

Firstly, thanks and well done. Adding pieces.Clear() fixed my immediate issue.
Unfortunately I had others after that.

I spent a couple of hours watching and reading on Singletons. And I realised that I only really had 1, and I wasn’t even using that properly. So I was doing loads of finds etc.

I’ve set about trying to add more in so I can share variables more easily. I dont know whether I’m doing the right thing or not, but I’ve now got a couple of issues that I really dont understand.

The main one is that my main aeroplane sprite object, that the camera is based on, seems to die immediately.
As soon as I go into the 2nd scene, I’ve put watches on it and I can see it going into the Dont destroy and aeroplane = this;

public class Aeroplane : MonoBehaviour {
    public float speed = 0.1f;
   
    public LevelGenerator levelgenerator;

    public static Aeroplane aeroplane;

    void Awake() {
        if (aeroplane == null) {
            DontDestroyOnLoad (gameObject);
            aeroplane = this;
        } else {
            if (aeroplane != this) {
                //Destroy (gameObject);
            }
        }
    }

and fails imediately with:

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.
CameraController.LateUpdate () (at Assets/scripts/CameraController.cs:19)

The CameraController script is attached to my main camera.

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.
CameraController.LateUpdate () (at Assets/scripts/CameraController.cs:19)

It is literally just :

public class CameraController : MonoBehaviour {

    public GameObject aeroplane;
    private Vector3 offset;
    private Vector3 screenSizeOffset = new Vector3 (23f,0f,0f);


    // Use this for initialization
    void Start () {
        offset = transform.position - aeroplane.transform.position;
    }
    
    // Update is called once per frame
    void LateUpdate () {
        transform.position = aeroplane.transform.position + offset + screenSizeOffset;
    }
}

and I have dropped the Aeroplane object onto the static variable in Unity inspector.

What am I missing? Is there some silly syntax error, or am I trying to do something wrong.

For reference, this all worked perfectly 2 days ago as a single scene. It has fallen apart because of 2 things:

  1. I added a main menu scene before it.
  2. Off the back of our earlier discussions I’ve tried to add in more singletons, as I was doing loads of finds to make things work.

Apologies, I realise this thread has gone off on a bit of a tangent, but I’m getting myself really confused now.
Thanks again.

My favourite approach to using singletons is to make all of the public methods static on a singleton, that way you can access them by using SingletonName.Method() from anywhere in the program. The singleton just needs to reference its own instance to get access to any inspector-displayed fields in those functions (using the “aeroplane” static reference internally). In your example, I would make a public static method called “GetTransform()” which returns the Transform of the object instance with “return aeroplane.GetComponent<Transform();” or whatever.

public class Aeroplane : MonoBehaviour
{
    [SerializeField]
    protected float speed = 0.1f;
 
    [SerializeField]
    protected LevelGenerator levelgenerator;

    protected static Aeroplane instance = null;

    protected void Awake()
    {
        if (instance == null)
        {
            DontDestroyOnLoad (gameObject);
            instance = this;
        }
        else
        {
            if (instance != this)
                Destroy(gameObject);
        }
    }

    public static Transform GetTransform()
    {
        return instance.GetComponent<Transform>();
    }
}

In your case, you made the reference to the instance public instead (that’s fine, just a style choice), so the CameraController doesn’t need a public reference to an Aeroplane object type, it only needs to call Aeroplane.aeroplane.transform to get its Transform through the static interface.

Drag-and-dropping a reference from an object marked DontDestroyOnLoad will cause problems- this is because the specific instance of that GameObject that you’re dragging and dropping is not necessary the same instance that will exist when that scene is loaded. The specific instance of that singleton may be destroying itself, because another copy of the singleton already exists in the scene (“there can be only one”)- this is precisely why you must use the static interface to get the instance, and not the inspector.

I hope all of that makes sense- let me know if you have any additional questions or concerns, or if you need clarification about something.

class fields do have initial default values in C#?

1 Like

I actually deleted it before you commented- I made the transition to C# around the same time I started using Unity and it really bugs me seeing uninitialized variables. I felt like I might be wrong so I went and checked, then deleted that part from the answer. shrugs

Ah, cool, no worries. I was just adding that :slight_smile: Didn’t see your update before, sorry.

Thanks again for the detailed reply. That does make some sense.
Although it is still failing with the same message at the same point.

I did start using functions as you suggested, but there were quite a lot, and you suggest it should still work if I just access the variables publically? I think that would be my preference, but equally I’m happy to go with what you say if it gets this working. The problem initially is there would be too many functions to add in at once to even be able to test my immediate problem.

I’ve gone through and taken out the public declarations for aeroplane in any script, and replaced with
Aeroplane.instance.transform.position in the code. It all compiles.

As I understand it, although have suggested you prefer using functions, I should still be able to access the private variables, which appears to be the case. I’ve checked the Unity inspector and all references to aeroplane are removed there.

I’m still using :

public static Aeroplane instance;

in the declaration of the aeroplane class so I can access these variables?

So unless I’ve misunderstood something I must have something lying around? Unless you have any other suggestions or observations.

For whatever reason the Aeroplane object does seem to dissapear in the Unity hierarchy when I run, indicating it is being closed down.

Is this the only place that can be happening, and if so is there anything wrong with it?

public static Aeroplane instance;

    void Awake() {
        if (instance == null) {
            DontDestroyOnLoad (gameObject);
            instance = this;
        } else {
            if (instance != this) {
                Destroy (gameObject);
            }
        }
    }

I think what I will do is drop back to a backup from a couple of days before I put the main menu screen on it, I’ll then try to get the singleton classes implemented on the approriate objects at that stage rather than trying to implement them in whilst other things are a bit flaky. Hopefully I’ll have better luck that way.

Thanks again.

One more thing while I remember to ask.
If aeroplane is my ‘player’ object, even before it was singleton, I don’t really understand how it could get more than one instance?

It is attached to an aeroplane gameobject in unity, but that’s it.

I am starting to think this may be a red herring, and the answer lies elsewhere.

As far as I can tell I have removed every public aeroplane ever created in the scripts.

Thanks, I really appreciate the time you’ve spent already on this.

Apologies for carpet bombing the thread…
I’ve gone though and converted a load more stuff.
The airplane sprite actually now looks like it is working, although the camera isn’t following it (will look at that later).
When I’m debugging I have put watches on a panel of buttons which is dissapearing.

It is defined as

public class InteractionPanel : MonoBehaviour {
    public bool panelOn;
    public bool startInteraction;
    public  int interactionNumber;
    //public InteractionPanel panel;
    //public Aeroplane aeroplane;
    public static InteractionPanel instance;

    void Awake() {
        if (instance == null) {
            DontDestroyOnLoad (gameObject);
            instance = this;
        } else {
            if (instance != this) {
                Destroy (gameObject);
            }
        }
    }

This is all set up in the unity hierarchy and is visible when I start the game. I’ve put watches on in the debugger and it goes into:
13 instance = this - still there
13 then into instance = this again - still there
16 then into Destroy (gameObject) - dissapears after this step

So it does look like something is trying to set this up twice.
After it dissapears it is no longer in the Unity hierarchy.

But I’ve been through all of my scripts and the hierarchy. I cannt see anything either having it assigned to a public variable in inspector, decalring a new object of type InteractionPanel, or accessing anything other than InteractionPanel.instance.blah

I cant work out if I’m missing one somewhere, or if I am missing something more obvious.

Just bear in mind that static survives reloading a scene and it’s references usually do not, so it will point at something that is garbage after loading. You should set up instances anyway regardless if they’re null or not in Awake if they will be static.

Sorry hippocoder, that doesn’t mean much to me unfortunately.
I’m on beginner-2 level at present :frowning:

Incidentally, I got round the issue on my previous post by commenting the destroy line (16) , though that obviously isn’t ideal and I dont understand why that would be required.

In case you saw my now recently deleted part of this thread re sprites, that is now resolved. My sprite prefab had been made invisible in unity so all subsequent ones were invisble.

All of the above was with my main menu disabled. Now I need to see if that all breaks things again.

And sure enough, it does. Going into game from main menu works, but as soon as I exit the game back to main menu it bombs. :frowning:

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

Do I need to destroy everything cleanly when I exit? This is all I’m doing now.

    public void ExitButtonOnCLick() {
        Debug.Log ("Clicked Exit");
        //GameObject levelGenerator = GameObject.Find("LevelGenerator");
  
        //levelGenerator.DestroyAll();
        //Application.UnloadLevel(1);
        Application.Quit();
        Application.LoadLevel(0);
    }

Your script should either check if it is null or you should not destroy the object.

UnityEngine.Component.GetComponent[SpriteRenderer] () (at C:/buildslave/unity/build/artifacts/generated/common/runtime/ComponentBindings.gen.cs:48)
LevelGenerator.UpdateSprites () (at Assets/scripts/LevelGenerator.cs:511)
LevelGenerator.Update () (at Assets/scripts/LevelGenerator.cs:548)

It looks like it dies as it goes back to the mainMenu scene, so presumably the level pieces get destroyed in the background but there is something still trying to render them.
Still, at least I have what I had before the main menu set up as Singleton and referencing directly rather than the previous finds I was doing everywhere.

I have to go out now, but will take a look at this when I get back, hopefully something simple.
Once again, thanks for your help and patience, very much appreciated.

I don’t think you should run the line ‘Application.Quit’ to go back to the main menu :slight_smile: try commenting that out & re-running your game.

I think I put that in when I was experimenting yesterday. Taken out but just the same.

I tried setting a function to remove all pieces and calling that before closing but still seems to do it. And the actual sprite prefabs don’t disappear if I set breakpoints.

So looks like I need to close all pieces and their equivalent level pieces/sprites down before going back to the menu scene.

Although I still dont really understand why it all needs to be closed down. I thought stuff would just persist between scenes? Or is this what was mentioned earlier where the list persists but the items within it dont?

One to look at tomorrow. Nearly there. …