Accessing the Class a GameObject Belongs To

I have a (non-MonoBehaviour) class. One of its fields is a GameObject. When I am in another script, I want to find that GameObject in the scene, and get the instance of the class it belongs to. I have no trouble finding the GameObject, but I do not know how to find it’s parent class. Anyone know how to do this? I can’t find anything on it online.

Edit:

I have been meaning to come back to this now that I have solved the problem, but I kept forgetting. Turns out, I was just fundamentally mis-informed about how Mono-Behaviour works. I was sure that since you couldn’t construct them, you could only have one instance.

I knew that you could add them as a component to multiple GameObjects, but I just assumed they were all references to the same script, which I guess technically they are, but phrasing it that way is misleading.

For anyone else struggling with a similar issue, what did it for me was realizing that when I add a MonoBehaviour script as a component to a GameObject, it creates a new instance of that script. In this way, it’s kind of backwards/counter-intuitive. You don’t want an instance of a class with a GameObject associated with it, you want a GameObject that has an instance of your class.

Rather than creating an instance of my class when I wanted to create a new object in the scene, I started by creating the GameObject, then created a new instance of my class by using GameObject.AddComponent(). This method creates an instance of the class you give it with its own instances of its fields.

Simply put, the GameObject owns the script (class) not the other way around. So if you are trying to access an instance of a class from a GameObject, The GameObject needs to be the parent, and the script needs to be a component. Multiple GameObjects with the same script component do not refer to the same instance of that class.

GameObjects don’t “belong” to classes.

Components (such as MonoBehaviours) can be added to GameObjects.

GameObjects don’t have a parent class that means anything in scripting.

The Transform Component on a GameObject may indicate that a GameObject is parented below another GameObject, also accessed via its Transform.

Beyond that, GameObjects are just “empty vessels.”

This post sounds a LOT like an XY Problem so let’s back up and ask the standard “What are you trying to accomplish?” question rather than trying to start from the impossibilities listed above.

Well, I’m not sure what you mean by “GameObjects don’t “belong” to classes.”

I have a class that has a GameObject as a field. It looks like this (with some name changes):

public abstract class MyClass
{
    public int ID;
    public string Stage;
    public double BaseDamage;
    public double BaseSpeed;
    public GameObject ThisObject;

So, when I construct this class, through one of its inheriting classes, it creates a GameObject, and holds a reference to it. I want to be able to find this instance of this class through the GameObject.

As for what I am trying to accomplish, I want to change one of the fields of this class when the GameObject “ThisObject” collides with another GameObject in the scene. It only seems logical that I would check for the collision between the objects, then use some imaginary method like ThisObject.GetParentClass().Stage = “Some String”;

Nothing like that happens simply from declaring a variable!!

Nothing about declaring a variable ever would create a GameObject. That’s not a thing.

You can make a GameObject by calling new GameObject() and assigning the result back to ThisObject

You can also use other means of finding existing GameObjects (such as those in scenes or prefabs) and then assign it to ThisObject.

Before you move onto imaginary methods, definitely get the requisite GameObject you want (see above) and assign it into ThisObject. The best way to obtain GameObjects is always to make a public or serialized field in a MonoBehaviour and drag it in.

// in a MonoBehaviour-derived script:
public GameObject ThisObject;  /// be sure to drag this in via the inspector!

However you and I are never going to add or manipulate custom properties like “Stage” to GameObject.

We are also not calling .GetParentClass() on a GameObject. That’s not a thing either.

We put those things in MonoBehaviours, which are Components, and Components get AddComponent-ed to GameObjects, and we can use GetComponent to get them back and interoperate with public methods / fields on the MonoBehaviour.

It really sounds like you want to start back with some basic Unity and C# tutorials because most of what you post above is an incorrect mental model of what is actually happening. You should also strive to use correct terminology, or you will struggle unnecessarily.

I suppose you didn’t notice this was an abstract class? Here is the constructor where where it is instantiated:

public MyClassInheritor(int Id, Vector3 Position, bool Planted)
    {
        this.ID = Id;
        this.Stage = "leaf";
        this.BaseDamage = 15;
        this.BaseSpeed = 4;
        ThisObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

It doesn’t matter abstract or not.

You didn’t post your creation of the primitive.

Everything else I posted above still stands:

You and I are NEVER adding or manipulating custom properties on a GameObject.

EVERYTHING you are attempting above is trivially and normally accomplished with a MonoBehaviour, which knows intimately what GameObject it is on.

ALSO: you do not use constructors with MonoBehaviours: you use Awake() or OnEnable()

Here is some timing diagram help:

https://docs.unity3d.com/Manual/ExecutionOrder.html

At the end of the day, it sounds like all you want is this type of construct, which I use everywhere, and which works fine with inherited and abstract and every other object oriented craziness you care to try, including interfaces I suppose:

Factory Pattern in lieu of AddComponent (for timing and dependency correctness):

I should mention that the reason I can’t do this in a MonoBehavior script is that I need many unique instances of this class to exist at one time. MonoBehavior doesn’t support that, and even if I could use monobehavior, I don’t want to associate the GameObjects to a the script as a whole, I want them to be associated with instances of a the class.

I am unsure how this helps my issue at all. I already know that there is no method like GetParentClass(). That’s why I called it imaginary.

This link does not seem related. I am creating an instance of a class, and holding a refrence to a GameObject within it. I just want to access this instance of the class. Perhaps there is no direct way to access this information, but there must be some connection because I can do it the other way.

If I can easily do MyClassInheritor.ThisObject to access the GameObject, why would there be absolutely no way to start from ThisObject and retrieve MyClassInheritor?

If everything I am saying here is “Trivially and normally accomplished with a MonoBehavior” how could I possibly create multiple instances of a MonoBehavior class? It’s easy to associate a script with a MonoBehavior class, but I do not want to associate a script, I want to associate an instance of a class. Without doing that, I cannot have each GameObject be associated with unique values. They will all just share values with the single MonoBehavior script.

Again, wrong. Every single instance of a MonoBehaviour is unique. It can also be differently-typed. It can even express different interfaces and all of those interfaces can be dealt with in a common way.

Merely having a variable in a class does not give a reciprocal link to the instance of that variable. What if you had 27 different places all pointing to that same GameObject? Which one would the GameObject point back to?

Since you cannot modify the contents of a GameObject to link back to your MyClassInheritor, your main method of doing this is via AddComponent, where you could trivially make a field to inject your MyClassInheritor instance.

But at that point, why not put all of the MyClassInheritor in the MonoBehaviour!

Okay, well this seems to be my point of confusion then.

To start, I want to have a class that extends an abstract class I made.

Normally, I would create a class, say, “MyAbstractClass”, and I would make another class named “MyClass” that extends “MyAbstractClass” via: public Class MyClass: MyAbstractClass.

If MyClass is also monobehavior, how do I still do this?

Secondly, if I somehow did that, in the past, I have gotten errors when I try to create a constructor for any class that inherits MonoBehavior. If I cannot use a constructor, how do I create multiple instances of it?

Thirdly, once I have multiple instances of it, how would I associate one unique instance of a MonoBehavior to a GameObject rather than associating the entire script?

I had taken these three problems to all be individually impassable, so I assumed that together, there was simply no way to do it. Any ideas?

[QUOTE="where you could trivially make a field to inject your MyClassInheritor instance.

But at that point, why not put all of the MyClassInheritor in the MonoBehaviour![/QUOTE]

THIS
THIS is my point of contention. How do I inject only an instance into the GameObject rather than the entire script?

When I try to simply add the component like this:
GameObject.AddComponent();

I get the error:

There is no implicit reference conversion from ‘MyClass’ to ‘UnityEngine.Component’.

https://answers.unity.com/questions/119516/inheriting-from-a-class-that-inherits-from-monobeh.html

I’m afraid I cannot help you until you use the standard terminology. There is NEVER an injection happening in Unity.

  • start with a GameObject reference
  • use AddComponent() to add MonoBehaviours (which gives a reference back)
  • modify the public properties of those behaviours (if you like)
  • lather rinse repeat, either using a new GameObject, OR… putting as many instances of the MonoBehaviour you want on the same GameObject.

Again, it has to be a MonoBehaviour. If you want to inherit from it to make other things to AddComponent(), then somwhere there MUST be a MonoBehaviour. That’s the glue to the engine.

The Unity engine DOES NOT LIVE in C# land.

[QUOTE="
where you could trivially make a field to inject your MyClassInheritor instance.
[/QUOTE]

Sorry, I was just using your terminology.

If I need the class to be MonoBehaviour before I can AddComponent, how do I do that without losing the inheritance? I also lose the constructor if I make it MonoBehaviour. Can I also replace that somehow?

You can have Gameobjects in non mono behavior class ?

The idea of gameobject is to connect to your script in the scene, thus has to be referenced and that cant happen in an abstract script that does not live in the scene.

So one way is to have a linker script on the gameobject, passing its data to the other script (if can accept gameobject). This way can do a simple search for that script on the scene to find the object.

To take up your example, MyAbstractClass would need to inherit from MonoBehaviour. Now, as you have noticed, you can’t/shouldn’t use the constructor of any class that inherits from MonoBehaviour. MonoBehaviours are instantiated via Instantiate or AddComponent.

If there’s any initialization you want to do when a MonoBehaviour is instantiated, there are two immediately apparent options: You can either use the MonoBehaviours Awake() or Start() methods, or you can implement some sort of initialization method that can be called from the Object instantiating the MonoBehaviour. Create your own constructor, so to speak.

Example:

public abstract class MyAbstractClass : MonoBehaviour
{
    public int ID;
    public string Stage;
    public double BaseDamage;
    public double BaseSpeed;
    public GameObject SomeObject;
}

public class MyClassInheritor : MyAbstractClass
{
    private void Awake()
    {
        this.Stage = "leaf";
        this.BaseDamage = 15;
        this.BaseDamage = 4;
    }

    public void Initialize(int id)
    {
        this.ID = id;
        this.SomeObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
    }
}

You can use it like any other MonoBehaviour:

void SomeFunction()
{
    GameObject someGameObject = new GameObject();
    MyClassInheritor myInheritor = someGameObject.AddComponent<MyClassInheritor>();
    myInheritor.Initialize(42);
}