Reference to Monobehaviour script from static class.

Hello can someone help me how to do this?

I want initialize monobehaviour class from static class but i am getting warning.

“You are trying to create a MonoBehaviour using the ‘new’ keyword. This is not allowed. MonoBehaviours can only be added using AddComponent(). Alternatively, your script can inherit from ScriptableObject or no base class at all”

If this will be in non static class i will go with

MyScript script = FindObjectOfType<MyScript>();

Currently i am using this but getting this warningMyScript script = new MyScript();

But how can i do this from static class and dont get this warrning?

Thanks for help.My code is working but i dont like this warning.

You can use the same construct as in a singleton. Fetch the object only if needed and store the reference in a static variable.

public static class MyScript
{
    static MyScript instance;
    public static MyScript Instance
    {
        get
        {
            if(instance == null)
            {
                // create or find object
                instance = GameObject.FindObjectOfType<MyScript>();
             }
             return instance;
        }
    }
}

Update: fixed coding error.

It has nothing to do with doing this from a static class.

MonoBehaviours are designed to be attached to GameObjects at all times. Unity will not allow them to exist unless they are attached to a GameObject.

The only valid ways to create an instance of a MonoBehaviour are:

  • AddComponent to create a new one and attach it to a GameObject
  • Instantiate to create a copy of an existing component and its GameObject together.

I stilldont get how can i achieve what i want, i cant make static class monobehaviour and alsoi cant initialize fromstatic class

What this will do?itwill enable me to initialize monobehaviour script from static class?I am not at home atm

It will allow you to execute the first line of code you posted from a static class. As @PraetorBlue said, you can not create it with “new”. So you have two options.

A) Find the existing object (Find… et all) and reference it in your static class. Which is the solution I posted.
B) Another option would be to create a new empty GameObject (new GameObject) and then use AddComponent() to create your script on it. Though usually people use Prefabs to do this. This is what PraetorBlue was talking about.

I tried it but if i create public static class MyScript : MonoBehaviour
it says this

This really sounds like classic XY Problem:

https://en.wikipedia.org/wiki/XY_problem

What are you TRYING to do, because 100% of the things you propose above will NEVER work in Unity.

I could bore you with pages of detail about lifecycle and constructor times, but you still CANNOT DO what you are trying to do.

So I ask again,

“What are you TRYING to do here?”

Note: this is not “What is your approach?” I can see your approach, that’s the problem.

The question is, “What is your goal here? What problem are you solving in your game?”

I maybe write it wrong i have static clas

I try to explain what i am trying to do :

I have one non mono behaviour class what managing my DB - SqlManager
In this script iam trying to create event what will trigger when value in my DB is updated.

Then in my second MONOBEHAVIOUR class i want capture this event and i want update UI values, i post my codes.
Thanks for help

If i make both scripts monobehaviour and if i replace MenuUI mUI = new MenuUI(); for MenuUI mUI = FindObject… and add SqlManager to GO then it is working but i dont want to have my SqlManager script as monobehaviour

7191133--862966--Sql.png
7191133--862969--menuui.png

You can use UnityEngine.Object features in plain C# classes like usual, static or otherwise.

Example of finding a type of MonoBehaviour:

using UnityEngine;

public static class SomeClass {
  MyScript script;

  void FindMyScript() {
    script = Object.FindObjectOfType<MyScript>();
  }
}

Example of instantiating a MonoBehaviour:

using UnityEngine;

public static class SomeClass {
  MyScript script;

  void InstantiateMyScript() {
    GameObject scriptObject = new GameObject();
    script = scriptObject.AddComponent<MyScript>();
  }
}

Both of these will find/instantiate in the currently active scene.

2 Likes

Doesn’t need to be static… just make it a singleton with an instance initializer (kinda how Vryken is doing above) and the first time you use it, everything will get set up, because by that time, Unity is truly up and running and you can safely call .AddComponent() to create your Monobehavior.

1 Like

This solved my issue, thanks.

sql = UnityEngine.Object.FindObjectOfType<SqlManager>();

My apologies, not sure why I inherited from MonoBehaviour there (typed it from memory on my tablet :smile:). I fixed the error above.

If I got you right then SQLManager is NOT a MonoBehaviour. You could make it a singleton and then request it from whichever class needs it (MonoBehaviour or not).

Also, I saw in your ui that you subscribe to the event with += in the Update() of your MonoBehaviour. You better move this to Awake() or OnEnable() or else it will subscribe anew in every frame, which I guess is not what you intended.

Anyhow, glad you solved it.

@_geo1
@Kurt-Dekker
@Vryken

Thanks for your answers, it helped however i like to know one more thing.
I have both scripts conected now Static class to Monobehaviour it is fine but i “FindingObjectOfType” each time i call this function and i dont like it. Is here some way how can i initilize this on start in static class?

My code in static class look like this.

   public static void AddIntValue(string name, int value)
        {
            events = UnityEngine.Object.FindObjectOfType<Events>();
            events.OnGameValueChange?.Invoke(events, EventArgs.Empty);
            if (name == Minerals.Soil.ToString())
            {
                Materials.Soil += value;
                progressExperience += value;
                experience += value;
                Materials.carryingMaterial += 1;
           
            }
}

nvm i just made static method Start and i call it once on “game start”