• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by Bovine · Mar 04, 2014 at 12:47 PM · bugduplicatedeadoldfindobjectsoftypeall

FindObjectsOfTypeAll() returns old objects

In my save game system, items that need to be saved are marked with a small script, StableId, which has an Id property of GUID. I use these to find GameObjects in a newly loaded Scene or when the player loads the game and a scene is loaded.

The problem I have, is that if the player is in Scene A and I load a saved game that is in Scene A, the game loads the data, reloads Scene A and that using the data makes changes to scene A to bring it back to the state the scene was in when the game was saved.

So, pushing aside any better solutions for saving, I have a problem ATM.

I call FindObjectOfTypeAll(typeof(StableId) and get back an array of all the StableIds in my scene. However, when I load the game, having reloaded the same Scene, the StableIds that were available in the previously loaded scene are still available, so I get the same GameObjects added to my Dictionary of StableIds twice, which is obviously incorrect.

Is this a known issue? Why is FindObjectsOfTypeAll() returning components that should be dead?

Here's the StableId code:

 public class StableId : MonoBehaviour
 {
     // a string GUID to uniqely identify this GameObject
     public string Id;
 
     // if true then the object is part of the scene and stored as such
     // otherwise it is considered an out of scene object and stored only
     // with the game
     public bool StoreWithScene = true;
 
     // if true the component has awoken in the scene,
     // so prefabs containing StableIds will NOT be visible to the
     // save game system
     public bool IsInScene = false;
 
     void Awake()
     {
         IsInScene = true;
     }
 
     void OnDestroy()
     {
         IsInScene = false;
     }
 
 }

The Serialization code is huge, so I cannot include that.

The reason I know that there are old instances, is that I've been outputting the InstanceId for the GameObjects my StableIds are attached to, and I can see that the ones that were loaded prior to loading the scene again, are still there.

Note that I have checked the scene - there are no duplicates, just the latest ones. I guess I could hack in a check to reject all InstanceIds that are below a threshold and update that every time a level has finished loading, but it feels more than a bit nasty and makes the assumption that the InstanceIds are never re-used.

Any help/suggestions greatly appreciated!

I guess the questions are:

  • Should FindObjectsOfTypeAll() return old objects?

  • Either way, can anyone think of a good way to detect an old object?

Thanks Ian H

Comment
Add comment · Show 9
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image whydoidoit · Mar 04, 2014 at 12:59 PM 0
Share

Are you specifically only looking for scene objects Ian? I can think of a way around that.

avatar image Bovine · Mar 04, 2014 at 01:04 PM 0
Share

Hmm, yes $$anonymous$$ike. But I want inactive ones as well - happy to have any solution. I'm sure you've had to do a bit of this for your save system.

Ours used to work, it's just that I added a new thing to be serialized and it's exploding :/

It's either something changed with this API or I am missing something/doing something daft, but I've spent a good few hours debugging it, and it certainly looks like there are old objects laying around - I am pretty sure I don't have a reference to them either.

avatar image whydoidoit · Mar 04, 2014 at 01:07 PM 1
Share

So if all of the root scene objects were live you could scan those and use GetComponentsInChildren on each also searching for inactive. You could have a helper that help all of the scene root objects that was initialized in the editor in case any were deactivated.

FindObjectsOfTypeAll is looking at available project items and all sort I think.

avatar image Bovine · Mar 04, 2014 at 01:34 PM 0
Share

Yes that's not a bad solution tbh, typically not many root objects tbh, and probably everything to be saved is below one root node thinking about it, though the serialization code doesn't contain any specialization for the current game, so yes, I might as well do that.

$$anonymous$$ight as well convert to answer and I can accept, though I guess it doesn't solve the issue I have with that method, but that's probably not a problem, at least, it's not a problem for me :D

avatar image whydoidoit · Mar 04, 2014 at 01:54 PM 1
Share

Yeah - messy really. You can FindObjectsOfType(Transform) and filter out everything with a parent. That's why I was wondering about a scene register for them where you just drop them in or run that in an Editor script.

Show more comments

4 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Bovine · Mar 04, 2014 at 03:55 PM

So, I'll answer this with my answer, plus Mike's answer.

Firstly, getting the top level objects and FindComponentsInChildren is probably a bit more efficient and StableId could be a bit simpler. However, in my case it didn't solve the problem, because I had loaded the level and without yielding or forcing the garbage collector to run, my call to either FindObjectsOfType() or FindObjectsOfTypeAll() was returning the newly loaded objects along with the, not-quite-dead objects. So the answer here is to ensure that you have garbage collected or yielded. It may be only one of these that is required, but it may be both.

If someone really needs to know I can check, but basically I now have the following code surrounding loading a scene:

             Debug.Log("loading " + levelName + "...");
             Application.LoadLevel(levelName);
 
             do
             {
                 yield return null;
             }
             while(Application.loadedLevelName != levelName);
 
             // lets force a collect, seems the old level is still here :-|
             System.GC.Collect();
             System.GC.WaitForPendingFinalizers();
             yield return null;

And it now works, the dead objects are now indeed dead. It's possible that the yield was enough while I waited for the requested level to be loaded in a previous version of Unity, or it may just be a bug I hadn't spotted when loading the same level as the current level.

Anyway, enjoy!

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image KainAsylum · Mar 18, 2014 at 07:55 PM 0
Share

This was very helpful. Thank you, Bovine! I came across this as well as I need to support recognition of inactive objects, which can't be done with GameObject.FindObjectsOfType.

I wish there was some way to track if an object is actually already destroyed and waiting for GC.

avatar image
1

Answer by KainAsylum · Mar 19, 2014 at 12:00 AM

On a related note, if anyone is noticing duplicates when playing from editor, it's because FindObjectsOfTypeAll() will also return the version of your GameObject that is in the editor as opposed to the Scene that is in play.

I was able to filter these out with by checking the 'hideFlags' of the Transform (not the gameObject) and making sure it is set to HideFlags.None before I can trust it.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bovine · Mar 19, 2014 at 05:31 AM 0
Share

Interesting, I haven't noticed that but I only consider GameObjects whose StableId IsInScene.

avatar image samizzo · May 14, 2014 at 11:44 PM 0
Share

Are you sure about that? I don't see duplicates but I do see some strange objects that look like they are only scene editor objects (e.g. one called HandlesGO).

avatar image
1

Answer by Masked_Riddler · Feb 20, 2019 at 06:10 PM

Found a much better method by using scene.name and comparing to scenemanager.getactivescene().name.

 using UnityEngine;
 using UnityEngine.SceneManagement;
 
 
     public static GameObject FindByName(string name) // Finds in the entire scene by discrete name, even inactives! 
     {
         string sceneName = SceneManager.GetActiveScene().name;
         foreach (GameObject obj in Resources.FindObjectsOfTypeAll(typeof(GameObject)))
             if (obj.name == name)
                 if (obj.scene.name == sceneName) return obj;
         return null;
     }
 
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Gentle-Troll · Apr 02, 2021 at 11:59 AM 0
Share

Indeed, that's the much better method! Many thanks!

avatar image
0

Answer by IsaiahKelly · Mar 13, 2017 at 08:08 PM

FindObjectsOfTypeAll() Returns Everything!

If you're using Resources.FindObjectsOfTypeAll() (replacement for Obsolete Object.FindObjectsOfTypeAll) it will return all GameObjects in the scene and project folder. So you need to filter them if you only want active scene objects. Please check out my answer to another question for a way to filter results based on the active scene.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

26 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Something went wrong in the Beast lightmapper: Duplicate name 1 Answer

Wierdest bug ever!! (pls help!) 0 Answers

Run Unity 5.3.3f1 files on version 4.6 2 Answers

GUI Bug in compiled game. 0 Answers

Adding object to list add the same object to another list 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges