0
\$\begingroup\$

I refer the website for proper way of referencing the script How to call a public function from another script in Unity? but it does not work, still return a nullreference exception in the example below. Not sure how to fix it.Apart from that I also consider using

 int a;
public int A
{ get; set; } 

and in HPscript using spawnpoint.A = spawnpoint.A - 1; but it come out the content is for read only.

Below is the codes I using.

I attach this code to a capsule gameobject that is use to spawn prefab gameobject,drag and drop prefab to the enemy GameObject inspector window, this part working correctly.

using System;
using UnityEngine;

public class Spawnpoint: MonoBehaviour
{ public GameObject Enemy;
  
  public int a;
  int currentstate = 0;
  int previousstate = 0;

   void Counting()
{//the below if statement is to ensure the Gameobject only spawn once when condition become true 
 //in every 10seconds
    var d = DateTime.Now.Second % 10;
    if(d==0)
    {
        currentstate = 1;
           
    }
    else
    {
        currentstate = 0;
    }
}

void Spawn()
{//Stop spawning when Gameobject equal 5
   
    if (d==0&&currentstate!=previousstate)
        if(a<5)
    {
        Instantiate(Enemy, new Vector3(UnityEngine.Random.Range(0, 4), 1, UnityEngine.Random.Range(0, 4)),Quaternion.identity);
        a = a+1;
    }
}

 void Update()
{
    Counting();
    Spawn();
    previousstate = currentstate;
}

}

The script below is not working. I want the HPscript to deduct the value "a",in Spawnpoint script so the script will continue spawn enemy when number less than 5.This script is attached to the prefab gameobject that is place in asset folder.

 using System;
 using UnityEngine;

public class HPScript : MonoBehaviour
{ Spawnpoint spawnpoint;


void Start()
{
    spawnpoint = GetComponent<Spawnpoint>();
}
public void counting()
{
    
    var c = DateTime.Now.Second % 30;
    if(c==0)

    {
       
        spawnpoint.a = spawnpoint.a - 1;
        
        Destroy(gameObject); }
}


void Update()
{
    counting();
    
}

}

\$\endgroup\$
2
  • \$\begingroup\$ Your spawnpoint is not on the same gameobject as your HP script and even if it was, it would not work. You want to have only one Spawner in your scene, it could be a static one for easier access (singleton comes to mind as well). Or you have to use a different lookup like Gameobject.Find("YourSpawnerName"). The alive time of your HP script is as well not always the same with your % 30, better use an Invoke("DestroyFunction", 30f) \$\endgroup\$
    – Zibelas
    Feb 12 at 16:14
  • \$\begingroup\$ My bad, is such a simple solution by using the 3rd example in the link yet I didn't try it out MoveTowards moveTowards = FindObjectOfType<MoveTowards>(), still struggle with "why it doen't work" without realize description both have to be on same object .Since this question does not have an answer yet, should it be close or delete or posting an answer, even I feel it doesn't worth spending time reading it. .Thanks for your help anyway. \$\endgroup\$
    – chuackt
    Feb 12 at 16:45
1
\$\begingroup\$

There are a few things that can be improved, first the updated scripts. The Spawner is responsible creating new enemies. As long as you have less than 5, it spawns one every 10seconds.

public class Spawner : MonoBehaviour
{
    public GameObject enemy;
    public int currentlySpawned;
    [SerializeField] private int maxSpawnable = 5;
    [SerializeField] private float spawnInterval = 10f;

    void Start()
    {
        //Each spawnInterval we just call Spawn()
        InvokeRepeating("Spawn", 0f, spawnInterval);
    }
    
    //make this public if you want to trigger Spawning from somewhere else as well
    void Spawn() {
        if (currentlySpawned < maxSpawnable)
        {
            currentlySpawned++;
            Vector3 spawnPosition = new Vector3(Random.Range(0, 5), Random.Range(0, 5));
            //The last transform is used to put all enemies under the Spawner in the inspector for better organization 
            Instantiate(enemy, spawnPosition, Quaternion.identity, transform);
        }
    }
}

The Enemy script is the same as your HPScript. It should go on the enemy prefab you have. I interpreted your script as that the enemy should die after 30sec.

public class Enemy : MonoBehaviour
{
    private Spawner spawner;
    
    void Start()
    {
       //if you have only one spawner in the scene 
       spawner = FindObjectOfType<Spawner>();
       //if there are more and you want to find a specific one
       //the first `Spawner` is the name of the GameObject in the inspector where your script is on
       //spawner = GameObject.Find("Spawner").GetComponent<Spawner>();
       Invoke("SelfDestruct", 30f); 
    }

    void SelfDestruct()
    {
        //short for spawner.currentlySpawned = spawner.currentlySpawned - 1;
        //other short version could be spawner.currentlySpawned -= 1;
        spawner.currentlySpawned--;
        Destroy(gameObject);
    }
}

Keep in mind you will always only have 3 enemies this way (since they die after 30sec and you spawn only one each 10sec), by the time you spawn the 4th, the first is dead.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.