Acces class methods from other class

Hello!
I’m triyng to working with OOP principles, so I create simple clases for current tasks. The problem is, I can’t understand how to acces to them properly. I can’t understand how to do it properly. It’s a bit complicated for me right now. I’d appresiate if you help me to understand the principle :slight_smile:

I have 3 different classes:

  • 1st class - Manager
  • 2nd class - Dictionary
  • 3rd class - ChangeValueInDictionary

The Manager Class instantiate a Dictionary Class somewhere in memory and 3rd class shoud change value in the Dictionary via Dictionary merhod.

  • 1st class added to Camera
  • 3rd class added to GameObject that collides with other objects with different names.
  • 2nd class doesn’t

There’s no problem to get an acces from 1st class to 2nd class.
I can’t get an acces to 2nd class from 3rd.

When I try to acces from 3rd class to second it’s write that 2nd class is null. What is the right way to get link to second class from other classes?

1st class - Manager

public class Manager : MonoBehaviour
{
    public PosDictionary mDictionary;
    public void Start()
    {
        mDictionary = new PosDictionary();
        mDictionary.AddValueToDictionary();
    }
}

2nd class - Dictionary

public class PosDictionary : MonoBehaviour
{
    Dictionary<string, Vector3> sphRotDict = new Dictionary<string, Vector3>();
    Vector3 sphereRot0 = new Vector3(0f, 0f, 0f);
    Vector3 sphereRot1 = new Vector3(1f, 1f, 1f);
    public string keyToDict;
    public void AddValueToDictionary()
    {
        keyToDict = "pos0";
        sphRotDict.Add("pos0", sphereRot0);
        sphRotDict.Add("pos1", sphereRot1);
        Debug.Log("Dictionary size is " + sphRotDict.Count);
    }
    public void ChangeKey(string newKey)
    {
        keyToDict = newKey;
    }
}

3rd class - ChangeValueInDictionary

public class ChangeValueInDictionary : MonoBehaviour
{
    PosDictionary mPosDictionary;
    string newPosName;
    void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("ChangePosition"))
        {
            newPosName = other.name;
            Debug.Log("newPosName is " + newPosName);

            mPosDictionary = GetComponent<PosDictionary>();
            if (mPosDictionary != null)
            {
                mPosDictionary.ChangeKey(newPosName);
            }
            else
            {
                Debug.Log("mPosDictionary is null");
            }
        }
        else
        {
            Debug.Log("Ball collides with unknown object");
        }
    }

Console

  • Dictionary size is 2
  • newPosName is ChangePosition
  • mPosDictionary is null

Remember what GetComponent() does.

Done just naked as GetComponent() (as you do in line 12 of the bottom script) will get the component ONLY from the GameObject where this script is located.

Use a reference to another GameObject or script with GetComponent() for other uses:

mPosDictionary = SomeOtherGameObjectOrScriptReference.GetComponent<PosDictionary>();

Generally,

Referencing variables, fields, methods (anything non-static) in other script instances:

https://discussions.unity.com/t/833085/2

https://discussions.unity.com/t/839310

REMEMBER: it isn’t always the best idea for everything to access everything else all over the place. For instance, it is BAD for the player to reach into an enemy and reduce his health.

Instead there should be a function you call on the enemy to reduce his health. All the same rules apply for the above steps: the function must be public AND you need a reference to the class instance.

That way the enemy (and only the enemy) has code to reduce his health and simultaneously do anything else, such as kill him or make him reel from the impact, and all that code is centralized in one place.

Keep in mind this:

does not mean “slice it all up for fun.” It means organize meaningfully-related chunks of code into perimeters of knowledge, eg “objects,” so that your overall program clarity is improved and becomes (in theory) more extensible and less fragile. Just plucking code apart and sticking it in three arbitrary classes does not necessarily improve anything, especially when a) those codelets all need to know intimate details about each other, and b) nobody else will ever use the sub-parts besides those codes. If that’s the case, you’re just splattering code for no good reason.

1 Like

Great links, your advises are very helpfull as usual. Thanks!

It seems that I use the GetComponent the wrong way.

1st Class create 2nd class here:

mDictionary = new PosDictionary();

is it right?

And 3rd class try to find 2nd class here, is it?

public PosDictionary mPosDictionary;

And the problem is that 2nd calss haven’t implemented yet. So 3rd class get null object.

So I shoud add it with the GetComponent(). But where is 2nd class? :smile:
How to find it?

I’ve tried this:

  1. Added Game Object (Main Camera) that contains the Manager Class via Inspector
  2. Take Manager Class from Game Object
  3. Take PosDictionary Class from Manager Class
    public GameObject mainCamera;
    public Manager mManager;
    public PosDictionary mPosDictionary;
            mManager = mainCamera.GetComponent<Manager>();
            mPosDictionary = mManager.GetComponent<PosDictionary>();

But mPosDictionary still null. What’s wrong?

yeah, that’s great definition about how no to do OOP)
Actually I have a big dictionary other classes work with in a porject.
So I decided to implement it as a single class.
And here I’ve added only a part of it as example to be short.

You can never make MonoBehaviour instances using the new keyword… NEVER!

In fact, the above code should be generating a warning in your log.

The only valid way of making a MonoBehaviour is by having a GameObject reference and calling .AddComponent();

You’re right, I got this warning but I didn’t pay attention to it.
I decide to add the Dictionary class to the Main Camera and avoid such problems that I make myself :slight_smile: