【问题标题】:starting Coroutine gives null reference exception in unity启动协程统一给出空引用异常
【发布时间】:2019-08-04 01:53:40
【问题描述】:

我正在尝试从我的GameController.cs 脚本访问协程,该协程位于我的DatabaseManager.csscript 中。我正在尝试像这样访问协程:

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

这给了我一个空引用异常。 我知道在我尝试访问的协程中一切正常,因为这些脚本与我制作的另一个项目完全相同,唯一的区别是在另一个项目中我通过一个运行良好的动画事件调用协程,但是试图通过这个项目中的代码调用它给了我这个问题。

数据库管理器脚本附加到玩家游戏对象

数据库管理器脚本

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);
                }
            }
        }
    }

游戏控制器脚本

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;
    }
}

【问题讨论】:

  • 请发布异常堆栈跟踪
  • 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+&lt;SpawnWaves&gt;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) 这就是它给我的,只是指向 startCoroutine() 函数
  • 如果数据库管理器在播放器上,为什么要创建一个新的.. 除非你只使用默认选项,否则 null 是你需要设置的东西并且没有
  • 我正在从游戏控制器类而不是 Player 实例化一个新的数据库管理器。将 new 关键字与 unity 一起使用是否有问题,这可能会阻止我以这种方式调用协程

标签: c# unity3d coroutine


【解决方案1】:

如果DatabaseManager 是一种单一行为,那么您不应该使用new 关键字来实例化它。 正确方法:

AddComponent<DatabaseManager>();

如果使用 new 关键字创建 MonoBehaviour,调用将在运行时失败。这是因为 MonoBehaviour 是一个组件,需要附加到 GameObject,这是人们讨厌统一序列化的原因之一,因为您需要一个容器类来存储 monobehaviour 字段和属性

使用方法:

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

如果你不在一个你这样做的游戏对象上,并且你不在一个单一的行为中

var tempgameObject = new GameObject();
DatabaseManager databaseManager = tempgameObject.AddComponent<DatabaseManager>();

【讨论】:

  • 谢谢你,但我怎么能用这个代替我原来的
  • 谢谢。我现在就试试这个并报告结果
  • 如果我使用 DatabaseManager databaseManager = AddComponent&lt;DatabaseManager&gt;(); 它会给出错误 The name AddComponent does not exist in the current context
  • 试试这个DatabaseManager databaseManager = gameObject.AddComponent&lt;DatabaseManager&gt;();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多