4

I am trying to access a Coroutine from my GameController.cs script, the Coroutine is located in my DatabaseManager.csscript. I am trying to access the Coroutine like this:

 DatabaseManager d1 = new DatabaseManager();
 d1.uploadData();

This is giving me a null reference exception. I know that everything works like it should in the coroutine I am trying to access because these scripts are the exact same from another project I made, the only difference is in the other project I called the coroutine through an animation event which worked fine, but trying to call it through code in this project is giving me that issue.

The Database manager script is attached to the Player game object

DatabaseManager script

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using UnityEngine.UI;
using CompanionLibrary; //include my library to utilise its functions
//use neccessary libraries.




    //This class handles sending game data to the database.
    public class DatabaseManager : MonoBehaviour
    {


        //declare variables to hold data values.
        static string username;
        string password;
        int score =0;
        int kills=0;  //initialise variables to 0 
        int bulletsFired=0;
        int bulletsHit=0;
        int bulletsMissed=0;
        int timePlayed = 0;
        int scorePerMin=0;
        StatGeneration companion = new StatGeneration();
        //On awake function to check if sign in or logged in booleans are set.
        public void Awake()
        {


        if (ButtonManagers.signedUp == true) //if signedUp boolean is true....
            {
                username = ButtonManagers.signUpUsername; //assign the username to equal the signUpUsername value.
                password = ButtonManagers.signUpPassword; //assign the password to equal the signUpPassword value.
            Debug.Log("Username: " + username);
            Debug.Log("Password: " + password);
        }

            //if loggedIn boolean is true....
            if (ButtonManagers.loggedIn == true)
            {
                username = ButtonManagers.loginUsername;//assign the username to equal the loggedInUsername value.
                password = ButtonManagers.loginPassword;//assign the password to equal the loggedInPassword value.
            }
        }

        //the function uploadData gets called in an AnimationEvent when the user dies.
        public void uploadData()
        {
        //As this gets called when the game ends, make sure the players stats are stored.
        kills = DestroyByContact.kills;
        score = GameController.score;
        bulletsFired = PlayerController.bulletsFired;
        bulletsHit = DestroyByContact.bulletsHit;
        bulletsMissed = DestroyByContact.bulletsMissed;
        timePlayed = TimeManager.time;
        scorePerMin = companion.TPS_scorePerMinTime(timePlayed);
        StartCoroutine(SendPlayerData()); //Start the Coroutine Upload.
    }


    IEnumerator SendPlayerData()
        {
            if (ButtonManagers.loggedIn==false)
            {
                //instantiate my library
                Debug.Log("Time in seconds: " + timePlayed);
                Debug.Log(companion.TPS_hitAccuracy(bulletsHit, bulletsFired) + "percent bullet accuracy");
                Debug.Log("Score per minute" + companion.TPS_scorePerMin(score,scorePerMin));


                Debug.Log("Username: " + username);
                Debug.Log("Password: " + password);
                Debug.Log("Kills: " + kills.ToString());
                Debug.Log("score: " + score.ToString());
                Debug.Log("bulletsFired: " + bulletsFired.ToString());
                Debug.Log("bulletsHit: " + bulletsHit.ToString());
                Debug.Log("bulletsMissed: " + bulletsMissed.ToString());
                WWWForm form = new WWWForm();
                form.AddField("database", "2DS_STATS");
                form.AddField("username", username);
                form.AddField("password", password);
                form.AddField("kills", kills);
                form.AddField("bulletsFired", bulletsFired);
                form.AddField("bulletsHit", bulletsHit);
                form.AddField("bulletsMissed", bulletsMissed);
                form.AddField("score",score);
                form.AddField("hitAccuracy", companion.TPS_hitAccuracy(bulletsHit, bulletsFired));
                form.AddField("scorePerMinute", companion.TPS_scorePerMin(score, scorePerMin));
                form.AddField("timePlayed", companion.UNI_TimePlayed(timePlayed));
                UnityWebRequest www = UnityWebRequest.Post("http://u530535384.hostingerapp.com/insertGameData.php", form);
                yield return www.SendWebRequest();

                if (www.isNetworkError || www.isHttpError)
                {
                    Debug.Log(www.error);
                }
                else
                {
                    Debug.Log("Form upload complete!");
                    Debug.Log(www.downloadHandler.text);
                }
            }
            else
            {

                Debug.Log(companion.TPS_hitAccuracy(bulletsHit, bulletsFired) + "percent bullet accuracy");
                Debug.Log("Time in seconds: " + timePlayed);
                Debug.Log("Username: " + username);
                Debug.Log("Password: " + password);
                Debug.Log("Kills: " + kills.ToString());
                Debug.Log("score: " + score.ToString());
                Debug.Log("bulletsFired: " + bulletsFired.ToString());
                Debug.Log("bulletsHit: " + bulletsHit.ToString());
                Debug.Log("bulletsMissed: " + bulletsMissed.ToString());
                WWWForm form = new WWWForm();
                form.AddField("database", "2DS_STATS");
                form.AddField("username", username);
                form.AddField("password", password);
                form.AddField("kills", kills);
                form.AddField("bulletsFired", bulletsFired);
                form.AddField("bulletsHit", bulletsHit);
                form.AddField("bulletsMissed", bulletsMissed);
                form.AddField("score", score);
                form.AddField("hitAccuracy", companion.TPS_hitAccuracy(bulletsHit, bulletsFired));
                form.AddField("scorePerMinute", companion.TPS_scorePerMin(score, scorePerMin));
                form.AddField("timePlayed", companion.UNI_TimePlayed(timePlayed));
                UnityWebRequest www = UnityWebRequest.Post("http://u530535384.hostingerapp.com/updateUserStats.php", form);
                yield return www.SendWebRequest();

                if (www.isNetworkError || www.isHttpError)
                {
                    Debug.Log(www.error);
                }
                else
                {
                    Debug.Log("Form upload complete!");
                    Debug.Log(www.downloadHandler.text);
                }
            }
        }
    }

GameController Script

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameController : MonoBehaviour
{
    public GameObject hazard;
    public Vector3 spawnValues;
    public int hazardCount;
    public float spawnWait;
    public float startWait;
    public float waveWait;

    public Text scoreText;
    public Text restartText;
    public Text gameOverText;

    private bool gameOver;
    private bool restart;
    public static int score;

    void Start()
    {
        gameOver = false;
        gameOverText.text = "";
        score = 0;
        UpdateScore();
        StartCoroutine(SpawnWaves());
    }



    IEnumerator SpawnWaves()
    {
        yield return new WaitForSeconds(startWait);
        while (true)
        {
            for (int i = 0; i < hazardCount; i++)
            {
                Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
                Quaternion spawnRotation = Quaternion.identity;
                Instantiate(hazard, spawnPosition, spawnRotation);
                yield return new WaitForSeconds(spawnWait);
            }
            yield return new WaitForSeconds(waveWait);

            if (gameOver)
            {
                SceneManager.LoadScene("Main Menu");//load the game.
                Debug.Log("I was called");
                DatabaseManager d1 = new DatabaseManager();
                d1.uploadData();
            }
        }
    }

    public void AddScore(int newScoreValue)
    {
        score += newScoreValue;
        UpdateScore();
    }

    void UpdateScore()
    {
        scoreText.text = "Score: " + score;
    }

    public void GameOver()
    {
        gameOverText.text = "Game Over!";
        gameOver = true;
    }
}
Charlie Ansell
  • 451
  • 1
  • 7
  • 22
  • Please post the exception stack trace – Rico Suter Mar 13 '19 at 11:40
  • ````NullReferenceException UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator routine) (at C:/buildslave/unity/build/Runtime/Export/MonoBehaviour.bindings.cs:88) DatabaseManager.uploadData () (at Assets/Scripts/DatabaseManager.cs:59) GameController+c__Iterator0.MoveNext () (at Assets/Scripts/GameController.cs:53) UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)```` that is what it gives me, just points to the startCoroutine() function – Charlie Ansell Mar 13 '19 at 11:45
  • if the database manager is on the player why make a new one.. unless you only use default options chances are the null is something you needed to set and havent – BugFinder Mar 13 '19 at 11:51
  • Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – BugFinder Mar 13 '19 at 11:53
  • I am instantiating a new Database Manager from the game controller class not the Player. is there a problem with using the new keyword with unity which might be stopping me from calling the coroutine in this way – Charlie Ansell Mar 13 '19 at 11:55
  • it would seem a daft thing to have a databased manager on a player, but needing 2 strikes of bad design - having not provided the manager code, its as singleton class and the class is being destroyed on start – BugFinder Mar 13 '19 at 11:56
  • yeah i have it on the player at the moment for debugging purposes until i figure out what is wrong with this coroutine.... – Charlie Ansell Mar 13 '19 at 11:58
  • then put in debug messages checking values – BugFinder Mar 13 '19 at 12:07
  • is databasemanager a monobehaviour? – Menyus Mar 13 '19 at 12:09
  • As I said already I know that the Coroutine is fine and works, its only when i try to call it in this manner it will not allow it – Charlie Ansell Mar 13 '19 at 12:09
  • database manager is a monobehaviour – Charlie Ansell Mar 13 '19 at 12:10
  • if it will help I can post both scripts in the question if required – Charlie Ansell Mar 13 '19 at 12:12
  • You can post it, i posted an answer, because now im sure whats your problem is – Menyus Mar 13 '19 at 12:17

1 Answers1

8

If DatabaseManager is a monobehaviour then you should not instantiate it with the new keyword. Correct way:

AddComponent<DatabaseManager>();

If the new keyword is used to create a MonoBehaviour, the call will fail at run time. This is because a MonoBehaviour is a component, and needs to be attached to a GameObject, this is one of the reason people hate serialization in unity, because you need a container class to store a monobehaviours fields and properties

How to use:

DatabaseManager databaseManager = gameObject.AddComponent<DatabaseManager>();

If you aint on a gameobject where you do this, and you aint in a monobehaviour

var tempgameObject = new GameObject();
DatabaseManager databaseManager = tempgameObject.AddComponent<DatabaseManager>();
Menyus
  • 6,633
  • 4
  • 16
  • 36