Search Unity

Using variables from a class Update function in another script to save the data in a csv-file

Discussion in 'Scripting' started by Andricho, Mar 14, 2019 at 4:45 PM.

  1. Andricho

    Andricho

    Joined:
    Mar 7, 2019
    Posts:
    6
    Hi!
    This is my first unity project and also my first post, so please comment if I neeed to include further information or anything of the sort.

    I'm currently trying to build a minigame where all the information gets automatically saved and appended in a csv-file after the Save method gets called inside the IncreaseScore method, and before the scene automatically changes.
    Saving my score, and filling the other cells with information such as the currentLevel the score was obtained in went smooth. But now I need to save the final cordinate variables from another class that constantly gets updated inside its Update method and I'm stuck. It' s important that its the final updated value for each variable, since the cordinate variables are based on the left HTC Vive hand controll position, and I need to calculate the total movement.
    Clearly my understanding of creating an instance of another class/the update method is too poorly, and the architecture is probably off too. So any advice on this would also be highly appreciated since I'm gonna expand the game to include other things in the future.
    Below is my code and the error message I get, thank you very much for any help provided.

    Error message:
    NullReferenceException: Object reference not set to an instance of an object
    GameManager.Update () (at Assets/Scripts/GameManager.cs:68)

    I understand I need to create an instance of the LeftControllerTracking class somehow, but I'm not sure where and how to extract the last value the finalMovement variables will be updated to.


    My GameManager class

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5. using System;
    6. using System.Runtime.Serialization.Formatters.Binary;
    7. using System.IO;
    8. using System.Text;
    9.  
    10. public class GameManager : MonoBehaviour
    11. {
    12.  
    13.     //the new part
    14.     public GameObject leftposition;
    15.     LeftControllerTracking leftController;
    16.  
    17.     public List<string[]> rowData = new List<string[]>();
    18.  
    19.     // Player score
    20.     public int score = 0;
    21.  
    22.     // High score
    23.     public int highScore = 0;
    24.  
    25.     // Static instance of the Game Manager,
    26.     // can be access from anywhere
    27.     public static GameManager instance = null;
    28.  
    29.     // Level, starting in level 1
    30.     public int currentLevel = 1;
    31.  
    32.     // Highest level available in the game
    33.     public int highestLevel = 3;
    34.  
    35.     // Called when the object is initialized
    36.     void Awake()
    37.     {
    38.  
    39.         // if it doesn't exist
    40.         if (instance == null)
    41.         {
    42.             print("assigning GameManager instance");
    43.             // Set the instance to the current object (this)
    44.             instance = this;
    45.         }
    46.  
    47.         // There can only be a single instance of the game manager
    48.         else if (instance != this)
    49.         {
    50.             print("GameManager instance already exists");
    51.             // Destroy the current object, so there is just one manager
    52.             Destroy(gameObject);
    53.             return;
    54.         }
    55.  
    56.         // Don't destroy this object when loading scenes
    57.         DontDestroyOnLoad(gameObject);
    58.  
    59.     }
    60.  
    61.  
    62.     private void Update()
    63.     {
    64.         //new part that is missplaced and can't be accessed anyway it seems
    65.          //leftX = leftController.finalMovementX;
    66.          //leftY = leftController.finalMovementY;
    67.          //leftZ = leftController.finalMovementZ;
    68.     }
    69.  
    70.     // Need the finalMovement variables as argument here
    71.     public void Save(int score, int currentLevel, float leftX, float leftY, float leftZ)
    72.     {
    73.  
    74.         // Creating First row of titles manually the first time i use the script
    75.         string[] rowDataTemp = new string[7];
    76.         rowDataTemp[0] = "Name";
    77.         rowDataTemp[1] = "ID";
    78.         rowDataTemp[2] = "Lvl";
    79.         rowDataTemp[3] = "Score";
    80.         rowDataTemp[4] = "X Movement";
    81.         rowDataTemp[5] = "Y Movement";
    82.         rowDataTemp[6] = "Z Movement";
    83.         //rowDataTemp[3] = "Total Movement";
    84.         rowData.Add(rowDataTemp);
    85.  
    86.         // You can add up the values in as many cells as you want.
    87.         for (int i = 0; i < 1; i++)
    88.         {
    89.             rowDataTemp = new string[7];
    90.             rowDataTemp[0] = "Andreas"; // name
    91.             rowDataTemp[1] = "1"; // ID
    92.             rowDataTemp[2] = "" + currentLevel; // Score
    93.             rowDataTemp[3] = "" + score; // Score
    94.             rowDataTemp[4] = "" + leftX; // X Movement
    95.             rowDataTemp[5] = "" + leftY; // Y Movement
    96.             rowDataTemp[6] = "" + leftZ; // Z Movement
    97.  
    98.             rowData.Add(rowDataTemp);
    99.  
    100.         }
    101.  
    102.         string[][] output = new string[rowData.Count][];
    103.  
    104.         for (int i = 0; i < output.Length; i++)
    105.         {
    106.             output[i] = rowData[i];
    107.         }
    108.  
    109.         int length = output.GetLength(0);
    110.         string delimiter = ",";
    111.  
    112.         StringBuilder sb = new StringBuilder();
    113.  
    114.         for (int index = 0; index < length; index++)
    115.             sb.AppendLine(string.Join(delimiter, output[index]));
    116.  
    117.         string filePath = getPath();
    118.  
    119.         //switch to System.IO.File.AppendText(filePath); the second time you use the script
    120.         StreamWriter outStream = System.IO.File.CreateText(filePath);
    121.         outStream.WriteLine(sb);
    122.         outStream.Close();
    123.  
    124.     }
    125.  
    126.     // Following method is used to retrive the relative path as device platform
    127.     private string getPath()
    128.     {
    129. #if UNITY_EDITOR
    130.         return Application.dataPath + "/CSV/" + "Saved_data.csv";
    131. #elif UNITY_ANDROID
    132.         return Application.persistentDataPath+"Saved_data.csv";
    133. #elif UNITY_IPHONE
    134.         return Application.persistentDataPath+"/"+"Saved_data.csv";
    135. #else
    136.         return Application.dataPath +"/"+"Saved_data.csv";
    137. #endif
    138.     }
    139.  
    140.  
    141. // Increase score
    142. public void IncreaseScore(int amount)
    143.     {
    144.         // Increase the score by the given amount
    145.         score += amount;
    146.  
    147.         // Show the new score in the console
    148.         print("New Score: " + score.ToString());
    149.  
    150.         if (score > highScore)
    151.         {
    152.             highScore = score;
    153.             print("New high score: " + highScore);
    154.         }
    155.  
    156.         if (score > 24)
    157.         {
    158.             // Increase level
    159.             Save(score, currentLevel, leftController.finalMovementX, leftController.finalMovementY, leftController.finalMovementZ);
    160.             GameManager.instance.IncreaseLevel();
    161.         }
    162.     }
    163.  
    164.     // Restart game. Refresh previous score and send back to level 1
    165.     public void Reset()
    166.     {
    167.         // Reset the score
    168.         score = 0;
    169.  
    170.         // Set the current level to 1
    171.         currentLevel = 1;
    172.  
    173.         // Load corresponding scene (level 1 or "splash screen" scene)
    174.         SceneManager.LoadScene("Level" + currentLevel);
    175.     }
    176.  
    177.     // Go to the next level
    178.     public void IncreaseLevel()
    179.     {
    180.         if (currentLevel < highestLevel)
    181.         {
    182.             currentLevel++;
    183.         }
    184.         else
    185.         {
    186.             currentLevel = 3;
    187.         }
    188.         SceneManager.LoadScene("Level" + currentLevel);
    189.     }
    190. }
    191.  
    192.  
    My LeftControllerTracking that is attached to my left controller gameobject


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class LeftControllerTracking : MonoBehaviour {
    6.  
    7.     public Transform track;
    8.     public Transform cachedTransform;
    9.     public Vector3 cachedPosition;
    10.     public float finalMovementX = 0;
    11.     public float finalMovementY = 0;
    12.     public float finalMovementZ = 0;
    13.  
    14.     void Start()
    15.     {
    16.         if (track)
    17.         {
    18.             cachedPosition = track.position;
    19.         }
    20.     }
    21.  
    22.     public void Update()
    23.     {
    24.         if (track && cachedPosition != track.position)
    25.         {
    26.             finalMovementX = (finalMovementX + (track.position.x - cachedPosition.x));
    27.             finalMovementY = (finalMovementY + (track.position.y - cachedPosition.y));
    28.             finalMovementZ = (finalMovementZ + (track.position.z - cachedPosition.z));
    29.  
    30.             print("New Total Left Katana X cordinate: " + finalMovementX);
    31.             print("New Total Left Katana Y cordinate: " + finalMovementY);
    32.             print("New Total Left Katana Z cordinate: " + finalMovementZ);
    33.  
    34.             cachedPosition = track.position;
    35.             transform.position = cachedPosition;
    36.         }
    37.     }
    38.  
    39.  
    40. }
    41.  
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    4,341
    Line 68 of your GameManager doesn't point to anything, which leads me to believe you modified the script after getting the error? It would be helpful to get a new null error so we know what line it's pointing to.
     
  3. Andricho

    Andricho

    Joined:
    Mar 7, 2019
    Posts:
    6
    You're absolutely right, tried to clean up some misstakes in the old code then posted the new. my misstake! Here is the error I get with the current code:

    "
    NullReferenceException: Object reference not set to an instance of an object
    GameManager.IncreaseScore (Int32 amount) (at Assets/Scripts/GameManager.cs:159)
    SwordCutter.OnCollisionEnter (UnityEngine.Collision collision) (at Assets/Scripts/SwordCutter.cs:53)
    "
     
  4. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    4,341
    Alright, so you are correct. leftController is most likely null.

    If LeftControllerTracking is a script on a gameobject in the scene, you could just make the variable public, or make it a serializedField and drag and drop the object into the variable. Otherwise, you'd have to connect it through code. You already have the variable created in your GameManager. The gameobject in your scene that has the LeftControllerTracking is an instance of that class. You just need to connect the two.
     
  5. Andricho

    Andricho

    Joined:
    Mar 7, 2019
    Posts:
    6
    I'm afraid I dont quite follow. The variables finalMovementX and so on are public in the provided LeftControllerTracking script above, which is attached to the GameObject ControllerLeft in the inspector.
    I've also dragged the ControllerLeft GameObject to the GameManager object with the GameManager script in the inspector view if that's what you mean.

    I'm afraid connecting the two through code (or some other way) is the problem I need help with.
     
  6. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    4,341
    In GameManager, LeftControllerTracking is private. Your null error is in GameManager line 159, which references leftController which is your private variable, so it is most likely null. If you can't make that variable public, and drag and drop, will have to use a GetComponent call to assign to it.

    To add if leftPostion contains the LeftControllerTracking component, then you need to have

    Code (CSharp):
    1.  
    2. leftController = leftPostion.GetComponent<LeftControllerTracking>();
    3.  
     
    Andricho likes this.
  7. Andricho

    Andricho

    Joined:
    Mar 7, 2019
    Posts:
    6
    You're absolutely right, it was private and I can now access it, I thought you meant the finalMovement variables.
    Thank you very much, now half of the problem is resolved, but I still get 0 back from the variables when I use them in my Save function inside GameManager, which mean I don't get the latest updated variable value from the LeftControllerTracking script, only the initial set 0 value.
     
  8. Andricho

    Andricho

    Joined:
    Mar 7, 2019
    Posts:
    6
    Update: Everything is in its order now! Tahnk you vert much for your help!