Search code examples
c#classunity-game-enginenullmonodevelop

Unity3D C# cant create obj from class


I have a script where are written two classes.I have problem in creating object from the second class Stats in the class StatsTotal.stats[i] = new Stats(i); here i am having the problem.The object created from Stats() is null and so all elements of the array stats are null. In unity I can't create objects from my own classes ? Please help.Thanks.

StatsTotal script:

public class StatsTotal : MonoBehaviour
{

    // Use this for initialization
    Stats[] stats;
    static int carsCount;
    int currentCar;
    GameObject player;
    void Start()
    {

        carsCount = PlayerPrefs.GetInt("CarsCount");
        stats = new Stats[carsCount];
        for (int i = 0; i < carsCount; i++)
        {

            stats[i] = new Stats(i);
            if (stats[currentCar] != null)
            {
                Debug.Log(getStats().driftTimePresent + "    " + getStats().driftTimeTotal);
            }
            stats[i].ReadTotal();
        }
    }

    void OnLevelWasLoaded()
    {
        if (Application.loadedLevelName != "MenuScene" && Application.loadedLevelName != "PrizeScene")
        {
            foreach (GameObject obj in GameObject.FindGameObjectsWithTag("PlayerSystem"))
            {
                if (obj.GetComponent<PlayerScript>().mainPlayer)
                {
                    player = obj;
                    break;
                }
            }
        }
        currentCar = GetComponent<VariableHandler>().selectedCar;
    }

    // Update is called once per frame
    void Update()
    {
        if (Application.loadedLevelName != "MenuScene" && Application.loadedLevelName != "PrizeScene")
        {
            if (stats[currentCar] != null)
            {
                Debug.Log(getStats().driftTimePresent + "    " + getStats().driftTimeTotal);
                getStats().driftTimePresent = (int)player.GetComponent<PlayerScript>().driftTime;
            }
        }

    }

    public Stats getStats()
    {
        return stats[currentCar];
    }
}

Stats script:

public class Stats : MonoBehaviour
{

    public int driftTimeTotal, driftTimePresent;
    public int explodedTotal, explodedPresent;
    public int flagsTotal, flagsPresent;
    public int x2Total, x2Present;
    public int shieldTotal, shieldPresent;
    public int healthTotal, healthPresent;
    public int scoreTotal, scorePresents;
    public int finish1stTotal, finish1stPresent;
    public int bonusesTotal, bonusesPresent;
    public int hitsObjTotal, hitsObjPresent;
    public int hitsCarTotal, hitsCarPresent;
    public int jumpTotal, jumpPresent;
    public int index;

    public Stats(int index)
    {
        this.index = index;
    }
    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    public void ResetPresent()
    {
        driftTimePresent = 0;
        explodedPresent = 0;
        flagsPresent = 0;
        x2Present = 0;
        shieldPresent = 0;
        healthPresent = 0;
        scorePresents = 0;
        finish1stPresent = 0;
        bonusesPresent = 0;
        hitsObjPresent = 0;
        hitsCarPresent = 0;
        jumpPresent = 0;
    }
    public void SaveTotal()
    {
        PlayerPrefs.SetInt("driftTimeTotal" + index, driftTimeTotal);
        PlayerPrefs.SetInt("explodedTotal" + index, explodedTotal);
        PlayerPrefs.SetInt("flagsTotal" + index, flagsTotal);
        PlayerPrefs.SetInt("x2Total" + index, x2Total);
        PlayerPrefs.SetInt("shieldTotal" + index, shieldTotal);
        PlayerPrefs.SetInt("healthTotal" + index, healthTotal);
        PlayerPrefs.SetInt("scoreTotal" + index, scoreTotal);
        PlayerPrefs.SetInt("finish1stTotal" + index, finish1stTotal);
        PlayerPrefs.SetInt("bonusesTotal" + index, bonusesTotal);
        PlayerPrefs.SetInt("hitsObjTotal" + index, hitsObjTotal);
        PlayerPrefs.SetInt("hitsCarTotal" + index, hitsCarTotal);
        PlayerPrefs.SetInt("jumpTotal" + index, jumpTotal);
    }
    public void ReadTotal()
    {
        driftTimePresent = PlayerPrefs.GetInt("driftTimeTotal" + index);
        explodedPresent = PlayerPrefs.GetInt("explodedPresent" + index);
        flagsPresent = PlayerPrefs.GetInt("flagsPresent" + index);
        x2Present = PlayerPrefs.GetInt("x2Present" + index);
        shieldPresent = PlayerPrefs.GetInt("shieldPresent" + index);
        healthPresent = PlayerPrefs.GetInt("healthPresent" + index);
        scorePresents = PlayerPrefs.GetInt("scorePresents" + index);
        finish1stPresent = PlayerPrefs.GetInt("finish1stPresent" + index);
        bonusesPresent = PlayerPrefs.GetInt("bonusesPresent" + index);
        hitsObjPresent = PlayerPrefs.GetInt("hitsObjPresent" + index);
        hitsCarPresent = PlayerPrefs.GetInt("hitsCarPresent" + index);
        jumpPresent = PlayerPrefs.GetInt("jumpPresent" + index);
    }
    public void SetTotal()
    {
        driftTimeTotal = PlayerPrefs.GetInt("driftTimeTotal" + index) + driftTimePresent;
        explodedTotal = PlayerPrefs.GetInt("explodedTotal" + index) + explodedPresent;
        flagsTotal = PlayerPrefs.GetInt("flagsTotal" + index) + flagsPresent;
        x2Total = PlayerPrefs.GetInt("x2Total" + index) + x2Present;
        shieldTotal = PlayerPrefs.GetInt("shieldTotal" + index) + shieldPresent;
        healthTotal = PlayerPrefs.GetInt("healthTotal" + index) + healthPresent;
        scoreTotal = PlayerPrefs.GetInt("scoreTotal" + index) + scorePresents;
        finish1stTotal = PlayerPrefs.GetInt("finish1stTotal" + index) + finish1stPresent;
        bonusesTotal = PlayerPrefs.GetInt("bonusesTotal" + index) + bonusesPresent;
        hitsObjTotal = PlayerPrefs.GetInt("hitsObjTotal" + index) + hitsObjPresent;
        hitsCarTotal = PlayerPrefs.GetInt("hitsCarTotal" + index) + hitsCarPresent;
        jumpTotal = PlayerPrefs.GetInt("jumpTotal" + index) + jumpPresent;

    }
}

Solution

  • Simply don't inherit from MonoBehaviour in your Stats class. Use

    class Stats {
    ......
    }
    

    not

    public class Stats : MonoBehaviour 
    {
    
    }
    

    If you inherit from MonoBehaviour, you can no longer use the new keyword to create instance of the script, You must use the Instantiate function.

    In addition, your save and load implementation does not look good at-all. Since you have many variables to save, simply convert them into Json then save with PlayerPrefs. To load them, use PlayerPrefs to load the json data then convert it back into class.

    This is what it should look like:

    using UnityEngine;
    using System.Collections;
    using System;
    
    [Serializable]
    public class Stats
    {
    
        public int driftTimeTotal, driftTimePresent;
        public int explodedTotal, explodedPresent;
        public int flagsTotal, flagsPresent;
        public int x2Total, x2Present;
        public int shieldTotal, shieldPresent;
        public int healthTotal, healthPresent;
        public int scoreTotal, scorePresents;
        public int finish1stTotal, finish1stPresent;
        public int bonusesTotal, bonusesPresent;
        public int hitsObjTotal, hitsObjPresent;
        public int hitsCarTotal, hitsCarPresent;
        public int jumpTotal, jumpPresent;
        public int index;
    
        public void SaveTotal()
        {
            string playerJson = JsonUtility.ToJson(this);
            PlayerPrefs.SetString("playerStats", playerJson);
        }
    
        public static Stats ReadTotal()
        {
            string playerJson = PlayerPrefs.GetString("playerStats");
            if (playerJson == null)
            {
                return null;
            }
            Stats stats = JsonUtility.FromJson<Stats>(playerJson);
            return stats;
        }
    }
    

    Usage:

    //Create new Stats and Save it
    Stats stats = new Stats();
    stats.index = 90;
    stats.SaveTotal();
    
    //Load new Stats
    Stats newStat = Stats.ReadTotal();