Unity - Cant access reference to another script

I am trying to learn how does Unity work and I now struggle with problem that I cannot access script from another script. I was searching on Interner for couple hours, I have tried many options but nothing helped.

I have 2 scripts.

  • CoinSpawn.cs - attached to Player (I would change it to other object but I dont know yet to which one, because its something that runs in background so it really dont need to be on player)

  • CollectingCoin.cs - attached to Coin (Coin is object, that its not on game scene on the start, it spawns randomly)

CoinSpawn is script that randomly spawn Instantiate of object Coin. I want to change value of CoinSpawn.currentCoinOnScreen from CollectingCoin. I ve tried

CoinSpawn test = GameObject.Find("CoinSpawn").GetComponent<CoinSpawn>(); 

and it doesnt work. I also have my both scripts in the same asset folder. What am I doing wrong? Thank you

CoinSpawn.cs

public class CoinSpawn : MonoBehaviour
{
    public GameObject coin;
    public int maximumCoinPerScreen = 10;
    public int currentCoinOnScreen = 0;
    private int randomNumber;
    private Vector2 spawnPosition;

    private void Update()
    {
        randomNumber = Random.Range(1, 1000);
        if(randomNumber >= 0 && randomNumber <= 1 && currentCoinOnScreen != maximumCoinPerScreen)
        {
            currentCoinOnScreen++;
            float spawnY = Random.Range
    (Camera.main.ScreenToWorldPoint(new Vector2(0, 0)).y, Camera.main.ScreenToWorldPoint(new Vector2(0, Screen.height)).y);
            float spawnX = Random.Range
                (Camera.main.ScreenToWorldPoint(new Vector2(0, 0)).x, Camera.main.ScreenToWorldPoint(new Vector2(Screen.width, 0)).x);
            spawnPosition = new Vector2(spawnX, spawnY);
            GameObject coinObject = Instantiate(coin, spawnPosition, Quaternion.identity);
        } 
    } 
}

CollectingCoin.cs

public class CollectingCoin : MonoBehaviour
{
    UnityEngine.UI.Text Coins;
    public static int totalCoins = 0;

    private void Start()
    {
        Coins = GameObject.Find("Score").GetComponent<UnityEngine.UI.Text>(); 
    } 
    void OnTriggerEnter2D(Collider2D c2d)
    { 
        if (c2d.CompareTag("Player"))
        { 
            totalCoins++; 
            Destroy(gameObject);
            Coins.text = "COINS: " + totalCoins.ToString();

            // TESTING 
           CoinSpawn test = GameObject.Find("CoinSpawn").GetComponent<CoinSpawn>();
            CoinSpawn test2 = GetComponent<CoinSpawn>();
        }   
    }
}


Solution 1:

GameObject.Find("CoinSpawn").GetComponent<CoinSpawn>();

Searches for a GameObject with the name CoinSpawn. Since you told us this component is rather attached to the player object it makes sense that it isn't found.

GetComponent<CoinSpawn>();

searches for a CoinSpawn component on the very same object your CollectingCoin is attached to. From your description this clearly also isn't the case.


Since you say the CoinSpawn is attached to the player then you probably rather want to get the component from

void OnTriggerEnter2D(Collider2D c2d)
{ 
    if (c2d.CompareTag("Player"))
    { 
        ...

        // rather get the component on the player object you collided with
        CoinSpawn test = c2d.GetComponent<CoinSpawn>();
    }   
}

Alternatively assuming there is only one single instance of CoinSpawn in your scene anyway and not necessarily on your player you could use FindObjectOfType

CoinSpawn test = FindObjectOfType<CoinSpawn>();

Solution 2:

First of all, Do not ever use GameObject.Find(), its very expensive as it will go through all game objects in your scene to find the object. and this not a performance wise.

There are many ways to do so. Easyest one:

  1. Add both script to same gameobject as component.

  2. Make a global variable CoinSpawn inside CollectingCoin script and then use [serializedFiled] tag on top of it, by this way, you can drag and drop the reference in the editor before you start play. and you can access it the way you want.

2nd way:

Is same as first one, but instead of serializedFiled, just cache it at the beginning by using GetComponent.

Just make sure you have both scripts attached to the same gameobject.

public class CollectingCoin : MonoBehaviour
{
    UnityEngine.UI.Text Coins;
    public static int totalCoins = 0;
    CoinSpawn coinSpawn;

    private void Start()
    {
        coinSpawn = GetComponent<CoinSpawn>();
        Coins = GameObject.Find("Score").GetComponent<UnityEngine.UI.Text>(); 
    } 

    void OnTriggerEnter2D(Collider2D c2d)
    { 
        if (c2d.CompareTag("Player"))
        { 
            totalCoins++; 
            Destroy(gameObject);
            Coins.text = "COINS: " + totalCoins.ToString();

            // DO Whaterver you want with coinSpawn here 
        
        }   
    }
}