从列表中逐步删除项目,但列表会在每个场景更改时继续重建

时间:2018-01-06 18:12:21

标签: c# list unity3d

我正在尝试创建一个管理器,它通过索引#从可能的索引列表中加载随机场景。一旦场景被加载,我想从列表中删除该项目,以消除相同的场景再次加载。一旦管理员完成了所有场景,我再次调用DoInitSceneIndexList()来创建一个填充了场景的新列表,并且该过程将重新开始。除了一件事,一切都在这里工作。每当我切换场景时,列表将再次重建,并且它从完整列表开始,而不是每次减少一个。每次加载场景时,我在哪里制作重建列表的错误?谢谢!

ForestGameManager.cs

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

public class ForestGameManager : MonoBehaviour
{
    public static ForestGameManager fgm = null; // create singleton

    ForestSceneTimer forestSceneTimer;

    [Header("Network Prefab")]
    public GameObject serverNetworkManagerPrefab;

    [Header("Forest Game Manager")]
    private int fgmIndex;
    private int firstForestSceneIndexNumber;
    private int lastForestSceneIndexNumber;

    [Header("Forest Scenes")]
    [TextArea(1,1)]
    public string forestSceneNotes = "Please place all Forest Scenes after Forest Loader scene";
    public int numberOfForestScenes;
    public float sceneCountdownLength;
    private List<int> forestSceneIndexes;
    private int randomSceneIndex;
    private bool initSceneList = true;
    private int currentSceneIndex;

    [Header("Forest Animal Management")]
    public int maxAnimalCount = 4;
    public List<ForestAnimal> forestAnimals;

    private void Awake()
    {
        StartCoroutine(DoInitForestGameManager());
        StartCoroutine(DoInitServerNetworking());

        fgmIndex = SceneManager.GetActiveScene().buildIndex;
        firstForestSceneIndexNumber = fgmIndex + 1;

        Debug.Log("firstForestSceneIndexNumber Index is : " + firstForestSceneIndexNumber);

        forestSceneTimer = GetComponent<ForestSceneTimer>();
    }

    private void Start()
    {
        forestAnimals = new List<ForestAnimal>();
        forestSceneIndexes = new List<int>();
        lastForestSceneIndexNumber = ((firstForestSceneIndexNumber + numberOfForestScenes) - 1);

        if (initSceneList)
        {
            StartCoroutine(DoInitSceneIndexList());
            StartCoroutine(DoGetRandomScene());
        }

        Debug.Log("There are " + numberOfForestScenes + " forest scenes in MasterLoader.");
    }

    private void Update()
    {
        // Destroy oldest animal gameobject based on maxAnimalCount
        if (forestAnimals.Count >= maxAnimalCount)
        {
            GameObject toDestroy = forestAnimals[0].forestAnimalGO;
            forestAnimals.RemoveAt(0);
            Destroy(toDestroy);
        }

        if (currentSceneIndex >= firstForestSceneIndexNumber && currentSceneIndex <= lastForestSceneIndexNumber)
        {
            // If all forest scenes have been used, re-initialize scene name list and pick the next random scene
            if (forestSceneIndexes.Count == 0)
            {
                StartCoroutine(DoInitSceneIndexList());
                StartCoroutine(DoGetRandomScene());

                Debug.Log("Out of scenes, re-initializing scene list.");
            }
        }
    }

    private void OnEnable()
    {
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    private void OnDisable()
    {
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        currentSceneIndex = SceneManager.GetActiveScene().buildIndex;

        Debug.Log("Current scene index is : " + currentSceneIndex);

        if (currentSceneIndex >= firstForestSceneIndexNumber && currentSceneIndex <= lastForestSceneIndexNumber)
        {
            // Start scene change countdown timer
            forestSceneTimer.StartSceneCountTimer(sceneCountdownLength);
        }
    }

    private IEnumerator DoInitSceneIndexList()
    {
        // Initialize scene name list
        for (int i = 0; i < numberOfForestScenes; i++)
        {
            forestSceneIndexes.Add(firstForestSceneIndexNumber + i);
            //Debug.Log("Scene index " + forestSceneIndexes[i].ToString() + " added to int list.");
        }
        yield return new WaitForEndOfFrame();

        initSceneList = false;
    }

    private IEnumerator DoInitForestGameManager()
    {
        if (fgm == null)
            fgm = this;
        else if (fgm != null)
            Destroy(gameObject);

        DontDestroyOnLoad(gameObject);
        yield return new WaitForEndOfFrame();
    }

    private IEnumerator DoInitServerNetworking()
    {
        Instantiate(serverNetworkManagerPrefab);
        yield return new WaitForEndOfFrame();
    }

    public void GetRandomScene()
    {
        StartCoroutine(DoGetRandomScene());
    }

    private IEnumerator DoGetRandomScene()
    {
        //Debug.Log("First forest scene index : " + firstForestSceneIndexNumber);
        //Debug.Log("Last forest scene index : " + lastForestSceneIndexNumber);

        // Get scene name from random pick
        randomSceneIndex = Random.Range(firstForestSceneIndexNumber, lastForestSceneIndexNumber);

        yield return new WaitForEndOfFrame();

        StartCoroutine(DoRemoveRandomSceneFromList());

        // Load selected scene
        StartCoroutine(DoLoadScene(randomSceneIndex, 0.0f));

        Debug.Log("randomSceneIndex is " + randomSceneIndex);

        for (int i = 0; i < forestSceneIndexes.Count; i++)
        {
            Debug.Log("Scene " + forestSceneIndexes[i].ToString() + " is still left in the list");
        }
    }

    private IEnumerator DoRemoveRandomSceneFromList()
    {
        // Remove selected scene from list
        forestSceneIndexes.Remove(randomSceneIndex);
        yield return new WaitForEndOfFrame();
    }

    private IEnumerator DoLoadScene(int sceneIndex, float loadDelay)
    {
        yield return new WaitForSeconds(loadDelay);
        SceneManager.LoadScene(sceneIndex, LoadSceneMode.Single);
    }
}

ForestSceneTimer.cs

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

public class ForestSceneTimer : MonoBehaviour
{
    public static ForestSceneTimer fst = null; // create singleton

    private IEnumerator _counter;

    private void Awake()
    {
        InitRestartTimer();
    }

    void InitRestartTimer()
    {
        if (fst == null)
            fst = this;
        else if (fst != null)
            Destroy(gameObject);
    }

    public void StartSceneCountTimer(float length)
    {
        //ForestGameManager.fgm.DestroyRestartTimer = false;
        Debug.Log("Scene Timer Started");
        _counter = RunTimer(length); // create new reference to counter, resets countdown to countdownLength
        StartCoroutine(_counter);
    }

    IEnumerator RunTimer(float seconds)
    {
        float s = seconds;
        while (s > 0)
        {
            yield return new WaitForSeconds(1);
            //if (RestartDialogBoxInstance != null)
                //_restartDialogCountdownTextTarget.text = s.ToString();
            s -= 1;

            if (s <= 0)
                ForestGameManager.fgm.GetRandomScene();

            Debug.Log(s);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

为了防止每次重建List,您必须做两件事。

DontDestroyOnLoad

将以下调用添加到 ForestGameManager 的Awake()方法中。

DontDestroyOnLoad(this.gameObject);

这样你的对象就不会在SceneChange上被销毁了。并保持直到你摧毁它或结束游戏。

不要初始化2次

  1. 将私有bool _isInitialized添加到您的GameManager
  2. 使用bool检查您的GameManager是否已全部初始化

    private void Start() {
      if (!this._isInitialized) {
        forestAnimals = new List<ForestAnimal>();
        forestSceneIndexes = new List<int>();
        lastForestSceneIndexNumber = ((firstForestSceneIndexNumber + numberOfForestScenes) - 1);
    
        if (initSceneList) {
          StartCoroutine(DoInitSceneIndexList());
          StartCoroutine(DoGetRandomScene());
        }
    
        Debug.Log("There are " + numberOfForestScenes + " forest scenes in MasterLoader.");
        this._isInitialized = true;
      } else {
        this.forestAnimals.Clear(); //I assume you can clear the list on scene change
      }
    }