I have a static class which I add to every script that needs it.
I set variables in following fashion: public static MyClass myClass = GameObject.Find("MyObject").GetComponent<MyClass>();
Then use using static ThatStaticClass;.
Throws:
UnityException: Find is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehaviour ‘_GameMaster’ on game object ‘GameMaster’.
See “Script Serialization” page in the Unity Manual for further details.
GAB…cctor () (at Assets/Scripts/Core/GAB.cs:29)
Rethrow as TypeInitializationException: The type initializer for ‘GAB’ threw an exception.
_GameMaster…ctor () (at Assets/Scripts/Core/_GameMaster.cs:28)
UnityException: Find is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehaviour 'AAA' on game object 'AAAGO'.
It was never a problem before. It happened only after I updated my Unity, whatever happened, I need to know how to deal with it now how to get it fixed and how to get it working.
Edit:
And what is this: Recursive Serialization is not supported. You can't dereference a PPtr while loading. (Constructors of C# classes may not load objects either. See stacktrace.)
What stacktrace?! There’s nothing below it.
Your title cuts off before the most critical word of the error: Find is not allowed to be called from a MonoBehaviour constructor
The constructor needs to be called before the scene has finished loading, and even in edit-mode to do things like determine the default values of serialized variables. You can’t call Find because there’s no scene to Find stuff in!
If you search around, you’ll find tons of working examples of singleton MonoBehaviours that will show you alternate ways of doing this.
Also, I agree with Joe-Censored that I can’t imagine this worked in any version of Unity. It’s possible that it used to fail in a slightly-different way, but calling Find from a static constructor is clearly not a safe thing to do.
Well it didn’t fail enough, and I think I know why. The objects I’m trying to Find are empty GameObject with scripts. They don’t render onto the scene, these GameObjects are also present before I even press Play. Maybe internal references were already set.
All the objects in your object hierarchy are part of the scene; whether they “render” is not relevant. And GameObject.Find only searches active scenes, so even if you had some objects that weren’t part of any scene, that wouldn’t mean you could Find them before loading the scene, it would mean that you couldn’t Find them at all.
I think the most likely explanation is some kind of programmer mistake; either you were doing something different before and you changed it in a way that you didn’t realize was important, or it was always giving garbage results but you didn’t notice because your tests weren’t thorough enough.
But if you really think it’s worth getting to the bottom of this, you could post an example project demonstrating what you were doing along with the exact version number of Unity under which it worked.
Well, they’re just class references. And they never failed to pass their data forward. I don’t know how much more thorough would I have to make it. E.g. myClass.itsVariable.thatFunction(); never failed.
Nah, I think you guys have much more important things to do than sit with me trying to get me to find out what went wrong, I guess I’ll move all my setters to Awake function in one of the scripts which will Find related scripts and assign them in the static class.
I believe qcw27710’s point was that if the variable hadn’t been properly initialized by the Find() call, then a null reference exception would have been thrown.
(Of course, in the general case, it is theoretically possible that something else could have initialized the variable between when the Find() call failed and when it was dereferenced. Presumably qcw27710 is confident this did not happen.)
That exactly. But no, this reference isn’t set in any other way. This is literally the only way.
I’m confident it didn’t happen as I’m literally searching for any other MyClass myClass; reference and there is none. This static class is the only class that mentions these classes and their Finds. Static class is meant to provide universal accessibility to those scripts, so that I will have to reattach and redefine reference variable.
I don’t want to be an armchair programmer and don’t want to sound like a dumb smirk, but… are you absolutely certain that Find searches objects in Scene and not Hierarchy?
Manual: https://docs.unity3d.com/ScriptReference/GameObject.Find.html
Mentions active GameObjects, nothing about the scene. The objects I’m trying to find are by default active GameObjects. Is it certain that no GameObjects can be selected unless there’s a scene? How does [ExecuteInEditMode] work?
Once again, I’m not questioning your knowledge, just wondering.
It searches the Hierarchy, but the Hierarchy is filled with objects from the loaded scenes, so there shouldn’t be anything in the Hierarchy until the first scene has loaded.
What @Joe-Censored said… or in other words, the hierarchy window is just a visual representation / UI at edit time for the available objects in the currenty loaded scenes.
Huh… i tried putting my feild input/var in my code. but it never worked. instead it just threw more errors and still said: UnityException: Find is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehaviour
What @Suddoha said… the hierarchy window is just a visual representation but it also specifies the path ex: Player > PlayerModel > Head. if i want to accses the Head using c# i would put in my script GameObject.Find("Player/PlayerModel/Head"). just a tell of what the hiearchy can do(in scripts)