- Home /
[C#] Calling Destroy() in a custom class destructor
When trying to call Destroy on a GameObject which is a member of my custom class, in the class destructor, I get the following error :
"Destroy can only be called from the main thread"
public class myClass {
GameObject go;
public myClass()
{
go = GameObject.Instantiate(...);
}
~myClass()
{
Destroy(go);
}
}
I have a class extending Monobehaviour to act as the "main" using its Update() function. If I set my custom class to null in the main loop, the destructor is called but it can't use Destroy() on the gameObject and thus the gameObject remains on screen, while I need it to be destroyed as well.
I know I could add a function to myClass in order to destroy the gameObject, and call it just before setting the class to null, but I'd really prefer calling it directly from the destructor for simplicity's sake. So my question is : What's the simplest solution to destroy a gameObject of a class when destroying the class itself ?
... Why are you using a destructor?
You also seem to be confused on the nature of classes. The class of a GameObject is always GameObject.
In general on $$anonymous$$onoBehaviour you don't use any of the standard constructors and destructors. Ins$$anonymous$$d replace them with Awake, OnEnable, Start, OnDisable and OnDestroy as appropriate.
Dear Bored$$anonymous$$ormon, I think you are actually confusing classes that extend $$anonymous$$onoBehaviour and those that do not, when you create a new script it originally extends $$anonymous$$onoBehaviour which gives you access to the special functions Update() etc..., but it's quite heavy on overhead if you have many (like thousands for example). Genrally speaking, you tend to try to keep your classes $$anonymous$$imalistic so they are the most lightweight as possible. You will notice that my custom class myClass is not extending $$anonymous$$onoBehaviour, because it's heavy on overhead when you have thousands. Here I'm using a destructor because I want to do something when the class is destroyed (set to null). For example you could put some Debug.Log("blabla") in the destructor and every time you destroy it the message will show up in the console. And I don't want to have to call a function externally to be able to destroy the instance of the GameObject which I keep reference of in myClass, I want that instance to be destroyed with the class.
Okay, I see where you are co$$anonymous$$g from now, and how it could be useful. This is just the first time I have seen a destructor used within Unity.
I'm not sure if what you are after is possible without introducing more overhead. As I understand it constructors and destructors run in a separate loading thread. You can't touch anything Unity from outside the main thread.
SO seems to indicate adding the destroy instruction to a list on a $$anonymous$$onoBehaviour that is checked from update might work. This does introduce extra overhead.
Answer by Bunny83 · Nov 13, 2014 at 07:30 PM
In 99% of all cases you don't want to use a destructor (finalizer) at all:
http://stackoverflow.com/questions/3649066/use-of-destructor-in-c
http://blog.stephencleary.com/2009/08/how-to-implement-idisposable-and.html
The destructor is called by the garbage collector which runs on a different thread. Custom managed classes never ever use a destructor unless you have unmanaged resources which need to be cleaned up. Never rely on a destructor to do something which should be in a manually called method. The destructor / finalizer in C# has nothing to do with a destructor in C++.
Thanks for the info, I've already started to read about IDisposable, which I tried to implement earlier when looking for a solution, but without success. There is no problem implementing the interface, but the trouble is the Dispose function doesn't seem to be called when I set the class instance to null. Example code :
public class myClass : IDisposable {
GameObject go;
public myClass()
{
go = GameObject.Instantiate(...);
}
public void Dispose()
{
GameObject.Destroy(go);
GC.SuppressFinalize(this);
}
// Also tried with a destructor calling Dispose()
~myClass()
{
this.Dispose();
}
}
And if I want to call Dispose() in a destructor I still have the same problem since Dispose() tries to call Destroy on the gameObject, so I would still have to call both Dispose() and set to null which would result in the same situation as coding and calling a method to handle gameObject destruction. I just want to be able to have the instance stored in GameObject go destroyed whenever I set myClass to null, without having to call another method ; is it even possible with C# ?
@laoril:
Have you read the links i've posted? Besides the general misuse of the Finalizer (.NET or the CLR in general doesn't have a destructor. The C# "destructor" is actually the Finalize method called by the GC), since the Finalizer is called from the GC thread and Unity is in general not thread-safe you can't call any Unity API method from a finalizer.
You also shouldn't call the Dispose method from the finalizer. The finalizer is in general very limited in what it can access. You also must ensure that you don't raise any exception in the Finalizer since it's called from the GC thread and can completely lock or crash the GC which will kill your application without a proper error message as you can't handle exceptions inside the Finalizer.
You should completely forget about the finalizer / destructor in Unity and even in C# in general. The only purpose of the finalizer is to clean up unmanaged resources.
To get rid of a GameObject you have to call Destroy on the main thread since all objects derived from UnityEngine.Object are managed by Unity. In C# or .NET you never rely on what happens in the GC. If an object is collected by the GC it's already disconnected from the active environment and can't interact with most things in the managed world. In C# / .NET you never "destroy" objects manually. They are always collected when they go out of extent. At this point it can't interact with most systems as it's already dead. Again, the only purpose of the finalizer is to clean up unmanaged resources. You can't even rely on a certain period of time when an object is collected. It could even take $$anonymous$$utes or never (when the program exits). The GC isn't forced to collect objects within a certain time. To quote one of the articles i've linked:
A correctly-written program cannot assume that finalizers will ever run at any point prior to program ter$$anonymous$$ation.
So your only way (which is also the only valid way) to cleanup Unity objects you have created is to explicitly call a method to clean up those things. That's the main purpose of the IDisposable interface. It provides a method which should be called by the user to clean up things when done.
Answer by zharik86 · Nov 13, 2014 at 07:17 PM
I was trying some method without success. I think, it's impossible. See forum links. Maybe, with destroy class, you destroy and GameObject, which class is attach. Then use function OnDestroy().
Answer by laoril · Nov 14, 2014 at 12:57 PM
Well I read the links, and as I said, implementing an IDisposable interface doesn't get Dispose() call when setting to null. When calling Dispose(), the instructions in Dispose() are called, but the class isn't set to null, and thus, if I'm trying to get rid of the class instance in a array of class instances, the instance remains, unless I call Dispose then set it to null. So as I mentionned, I have to call Dispose and then set the class to null, which I wanted to avoid. It is a shame that it is not possible, Also, I have a computer science book about programming in C# with Unity, and the author does use constructors and destructors. Anyways, thanks for the replies ( and the downvote ;) ), think I'll just create my own method to get rid of the GameObject instance
Your answer
![](https://koobas.hobune.stream/wayback/20220613171433im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers
Destroy object when transform.position.x > 10. 1 Answer
How do I make Destroy(gameObject) work in my script? 1 Answer
(2d) How can I destroy a gameObject when I pass over it? 1 Answer
Destroy(gameObject) does not work 2 Answers