Unity-设置脚本实例以使用另一个脚本中的类Update函数中的变量

时间:2019-03-15 09:53:41

标签: c# unity3d

这是我的第一个统一项目,也是我的第一篇文章,因此,如果我需要提供更多信息或类似信息,请发表评论。

我目前正在尝试制作一个小型游戏,该游戏中的所有信息都将自动保存,并在GrowthScore方法内调用Save方法之后且场景自动更改之前将其附加到一个csv文件中。 保存我的分数,并在其他单元格中填充诸如currentLevel之类的信息,即可顺利获得分数。但是现在我需要从另一个类中保存最终的坐标变量,该类会在其Update方法中不断更新,而我陷入了困境。重要的是每个变量的最终更新值,因为坐标变量基于HTC Vive左手的左手控制位置,因此我需要计算总运动量。 显然,我对创建另一个类/更新方法的实例的理解太差,因为我无法从其他文章中找到如何解决它的方法。 以下是我的代码和收到的错误消息,非常感谢您提供的任何帮助。

错误消息: “ NullReferenceException:对象引用未设置为对象的实例 GameManager.IncreaseScore(Int32量)(在Assets / Scripts / GameManager.cs:159) SwordCutter.OnCollisionEnter(UnityEngine.Collision碰撞)(位于Assets / Scripts / SwordCutter.cs:53)“

我了解我需要以某种方式创建LeftControllerTracking类的实例,但是我不确定如何以及在何处创建实例。下面提供的LeftControllerTracking脚本已附加到检查器中的GameObject ControllerLeft。 我还通过检查器视图中的GameManager脚本将ControllerLeft GameObject拖动到GameManager对象。

我的GameManager类:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Text;

public class GameManager : MonoBehaviour
{
    //the new part
    public GameObject leftposition;
    LeftControllerTracking leftController;

    public List<string[]> rowData = new List<string[]>();

    // Player score
    public int score = 0;

    // High score
    public int highScore = 0;

    // Static instance of the Game Manager,
    // can be access from anywhere
    public static GameManager instance = null;

    // Level, starting in level 1
    public int currentLevel = 1;

    // Highest level available in the game
    public int highestLevel = 3;

    // Called when the object is initialized
    void Awake()
    {

        // if it doesn't exist
        if (instance == null)
        {
            print("assigning GameManager instance");
            // Set the instance to the current object (this)
            instance = this;
        }

        // There can only be a single instance of the game manager
        else if (instance != this)
        {
            print("GameManager instance already exists");
            // Destroy the current object, so there is just one manager
            Destroy(gameObject);
            return;
        }

        // Don't destroy this object when loading scenes
        DontDestroyOnLoad(gameObject);

    }


    private void Update()
    {
        //new part that is missplaced and can't be accessed anyway it seems
        //leftX = leftController.finalMovementX;
        //leftY = leftController.finalMovementY;
        //leftZ = leftController.finalMovementZ;
    }

    // Need the finalMovement variables as argument here
    public void Save(int score, int currentLevel, float leftX, float leftY, float leftZ)
    {

        // Creating First row of titles manually the first time i use the script
        string[] rowDataTemp = new string[7];
        rowDataTemp[0] = "Name";
        rowDataTemp[1] = "ID";
        rowDataTemp[2] = "Lvl";
        rowDataTemp[3] = "Score";
        rowDataTemp[4] = "X Movement";
        rowDataTemp[5] = "Y Movement";
        rowDataTemp[6] = "Z Movement";
        //rowDataTemp[3] = "Total Movement";
        rowData.Add(rowDataTemp);

        // You can add up the values in as many cells as you want.
        for (int i = 0; i < 1; i++)
        {
            rowDataTemp = new string[7];
            rowDataTemp[0] = "Andreas"; // name
            rowDataTemp[1] = "1"; // ID
            rowDataTemp[2] = "" + currentLevel; // Score
            rowDataTemp[3] = "" + score; // Score
            rowDataTemp[4] = "" + leftX; // X Movement
            rowDataTemp[5] = "" + leftY; // Y Movement
            rowDataTemp[6] = "" + leftZ; // Z Movement

            rowData.Add(rowDataTemp);

        }

        string[][] output = new string[rowData.Count][];

        for (int i = 0; i < output.Length; i++)
        {
            output[i] = rowData[i];
        }

        int length = output.GetLength(0);
        string delimiter = ",";

        StringBuilder sb = new StringBuilder();

        for (int index = 0; index < length; index++)
            sb.AppendLine(string.Join(delimiter, output[index]));

        string filePath = getPath();

        //switch to System.IO.File.AppendText(filePath); the second time you use the script
        StreamWriter outStream = System.IO.File.CreateText(filePath);
        outStream.WriteLine(sb);
        outStream.Close();

    }

    // Following method is used to retrive the relative path as device platform
    private string getPath()
    {
        #if UNITY_EDITOR
        return Application.dataPath + "/CSV/" + "Saved_data.csv";
        #elif UNITY_ANDROID
        return Application.persistentDataPath+"Saved_data.csv";
        #elif UNITY_IPHONE
        return Application.persistentDataPath+"/"+"Saved_data.csv";
        #else
        return Application.dataPath +"/"+"Saved_data.csv";
        #endif
    }


    // Increase score
    public void IncreaseScore(int amount)
    {
        // Increase the score by the given amount
        score += amount;

        // Show the new score in the console
        print("New Score: " + score.ToString());

        if (score > highScore)
        {
            highScore = score;
            print("New high score: " + highScore);
        }

        if (score > 24)
        {
            // Increase level
            Save(score, currentLevel, leftController.finalMovementX, leftController.finalMovementY, leftController.finalMovementZ);
            GameManager.instance.IncreaseLevel();
        }
    }

    // Restart game. Refresh previous score and send back to level 1
    public void Reset()
    {
        // Reset the score
        score = 0;

        // Set the current level to 1
        currentLevel = 1;

        // Load corresponding scene (level 1 or "splash screen" scene)
        SceneManager.LoadScene("Level" + currentLevel);
    }

    // Go to the next level
    public void IncreaseLevel()
    {
        if (currentLevel < highestLevel)
        {
            currentLevel++;
        }
        else
        {
            currentLevel = 3;
        }
        SceneManager.LoadScene("Level" + currentLevel);
    }
}

附加到我的ControllerLeft游戏对象的我的LeftControllerTracking:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LeftControllerTracking : MonoBehaviour {

    public Transform track;
    public Transform cachedTransform;
    public Vector3 cachedPosition;
    public float finalMovementX = 0;
    public float finalMovementY = 0;
    public float finalMovementZ = 0;

    void Start()
    {
        if (track)
        {
            cachedPosition = track.position;
        }
    }

    public void Update()
    {
        if (track && cachedPosition != track.position)
        {
            finalMovementX = (finalMovementX + (track.position.x - cachedPosition.x));
            finalMovementY = (finalMovementY + (track.position.y - cachedPosition.y));
            finalMovementZ = (finalMovementZ + (track.position.z - cachedPosition.z));

            print("New Total Left Katana X cordinate: " + finalMovementX);
            print("New Total Left Katana Y cordinate: " + finalMovementY);
            print("New Total Left Katana Z cordinate: " + finalMovementZ);

            cachedPosition = track.position;
            transform.position = cachedPosition;
        }
    }  
}

2 个答案:

答案 0 :(得分:0)

最简单的解决方案是公开展示

public LeftControllerTracking leftController;

然后您可以在编辑器中分配文件,对于您的用例来说,这应该足够了,因为对象的实例已经存在,所以您没有对其的引用

答案 1 :(得分:0)

以下是将字段公开给Unity中其他类的一些方法:

  1. 公开字段并将其绑定到编辑器中。
  2. Make fields [SerializeField] and bind them in the Editor.这样,您只违反了编辑器中的封装。
  3. Find game objects runtime.注意Find()需要很长时间。
  4. 设置LeftControllerTracking类singleton

另外,将帖子标记为重复可能很有意义,但是新的stackoverflowers需要积分。