随机场景加载器无法正常工作
Random scene loader not working correctly
我正在尝试开发我的游戏中的功能,该功能加载一个随机场景,该场景共有 8 个填充在列表中,然后在场景加载后从列表中删除 forestSceneIndexes = new List<int>();
。这样,当加载下一个随机场景时,它会从列表中的现有场景中进行选择,依此类推。
我做的第一件事是用以下函数的场景填充我的列表:
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;
}
之后我在函数DoGetRandomScene中得到了随机场景
private IEnumerator DoGetRandomScene()
{
// Get scene name from random pick
randomSceneIndex = Random.Range(firstForestSceneIndexNumber, (firstForestSceneIndexNumber + forestSceneIndexes.Count) - 1);
yield return new WaitForEndOfFrame();
StartCoroutine(DoRemoveRandomSceneFromList());
// Load selected scene
StartCoroutine(DoLoadScene(randomSceneIndex));
}
一旦我得到随机场景,我就会立即从我的列表中删除该索引:
private IEnumerator DoRemoveRandomSceneFromList()
{
// Remove selected scene from list
forestSceneIndexes.Remove(randomSceneIndex);
yield return new WaitForEndOfFrame();
}
然后我将 randomSceneIndex 传递给 DoLoadScene() 函数
private IEnumerator DoLoadScene(int sceneIndex)
{
yield return new WaitForEndOfFrame();
SceneManager.LoadScene(sceneIndex, LoadSceneMode.Single);
}
我的问题是它无法正常工作,前几个场景似乎一开始还不错,但是一旦剩下大约 3 个场景,它就会不断重新加载相同的场景。我不确定我有什么问题,任何帮助将不胜感激!下面还添加了完整的脚本。谢谢!
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;
public class ForestGameManager : NetworkBehaviour
{
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;
private bool _isInitialized;
[Header("Forest Scenes")]
[TextArea(1, 1)]
public string forestSceneNotes = "Please place all Forest Scenes after Forest Loader scene";
public int numberOfForestScenes;
private float sceneCountdownLength = 15.0f;
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()
{
//DontDestroyOnLoad(this.gameObject);
StartCoroutine(DoInitForestGameManager());
StartCoroutine(DoInitServerNetworking());
fgmIndex = SceneManager.GetActiveScene().buildIndex;
firstForestSceneIndexNumber = fgmIndex + 1;
//Debug.Log("firstForestSceneIndexNumber Index is : " + firstForestSceneIndexNumber);
forestSceneTimer = GetComponent<ForestSceneTimer>();
}
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
}
InvokeRepeating("CheckAnimalCount", 0, 1f);
InvokeRepeating("CheckRemainingScenes", 0, 10f);
}
private void CheckAnimalCount()
{
if (forestAnimals.Count >= maxAnimalCount)
{
GameObject toDestroy = forestAnimals[0].forestAnimalGO;
forestAnimals.RemoveAt(0);
StartCoroutine(ExplodedMesh(toDestroy));
//yield return new WaitForSeconds(1f);
}
Debug.Log("Checking animal count");
}
private void CheckRemainingScenes()
{
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.");
}
//yield return new WaitForSeconds(1f);
Debug.Log("Checking remaining scenes");
}
}
private IEnumerator ExplodedMesh(GameObject toDestroy)
{
MeshExploder meshExploder = toDestroy.transform.GetChild(0).gameObject.AddComponent<MeshExploder>();
yield return new WaitForEndOfFrame();
toDestroy.transform.GetChild(0).gameObject.GetComponent<MeshExploder>().Explode();
yield return new WaitForEndOfFrame();
Destroy(toDestroy);
yield return new WaitForEndOfFrame();
}
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()
{
Debug.Log("Get Random Scene");
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, (firstForestSceneIndexNumber + forestSceneIndexes.Count) - 1);
Debug.Log("First scene in list is " + firstForestSceneIndexNumber + " , the last one is " + ((firstForestSceneIndexNumber + forestSceneIndexes.Count) - 1));
yield return new WaitForEndOfFrame();
StartCoroutine(DoRemoveRandomSceneFromList());
// Load selected scene
StartCoroutine(DoLoadScene(randomSceneIndex));
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");
Debug.Log(forestSceneIndexes.Count.ToString() + " scenes are still left in the list");
}
}
private IEnumerator DoRemoveRandomSceneFromList()
{
// Remove selected scene from list
forestSceneIndexes.Remove(randomSceneIndex);
Debug.Log("Scene " + randomSceneIndex + " has been removed from the list.");
yield return new WaitForEndOfFrame();
}
private IEnumerator DoLoadScene(int sceneIndex)
{
yield return new WaitForEndOfFrame();
SceneManager.LoadScene(sceneIndex, LoadSceneMode.Single);
foreach (ForestAnimal animal in forestAnimals) // Spawn Animal Stored in the forestAnimals List
{
// print("Animal " + animal.forestAnimalName + "is still in the list");
//GameObject animalGO = (GameObject)Instantiate(animal.forestAnimalGO);
//NetworkServer.Spawn(animalGO);
Debug.Log(animal.forestAnimalName + " re-instantiated in new scene");
}
}
}
除了评论中提到的问题(您一定要仔细阅读)之外,问题在于您如何选择随机数。您没有从实际的索引列表中提取。它应该是这样的:
private IEnumerator DoGetRandomScene()
{
// Get scene name from random pick
int choice= Random.Range(0, forestSceneIndexes.Count - 1);
//here's where you convert your random choice into an actual scene index
int sceneIndex = forestSceneIndexes[choice];
yield return new WaitForEndOfFrame();
//If you want to remove the scene, just do it now
forestSceneIndexes.RemoveAt(choice);
// Load selected scene
StartCoroutine(DoLoadScene(sceneIndex));
}
注意,我没有修改你对协程的大部分使用,但正如评论中所指出的,你肯定有很多需要清理的地方。
我正在尝试开发我的游戏中的功能,该功能加载一个随机场景,该场景共有 8 个填充在列表中,然后在场景加载后从列表中删除 forestSceneIndexes = new List<int>();
。这样,当加载下一个随机场景时,它会从列表中的现有场景中进行选择,依此类推。
我做的第一件事是用以下函数的场景填充我的列表:
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;
}
之后我在函数DoGetRandomScene中得到了随机场景
private IEnumerator DoGetRandomScene()
{
// Get scene name from random pick
randomSceneIndex = Random.Range(firstForestSceneIndexNumber, (firstForestSceneIndexNumber + forestSceneIndexes.Count) - 1);
yield return new WaitForEndOfFrame();
StartCoroutine(DoRemoveRandomSceneFromList());
// Load selected scene
StartCoroutine(DoLoadScene(randomSceneIndex));
}
一旦我得到随机场景,我就会立即从我的列表中删除该索引:
private IEnumerator DoRemoveRandomSceneFromList()
{
// Remove selected scene from list
forestSceneIndexes.Remove(randomSceneIndex);
yield return new WaitForEndOfFrame();
}
然后我将 randomSceneIndex 传递给 DoLoadScene() 函数
private IEnumerator DoLoadScene(int sceneIndex)
{
yield return new WaitForEndOfFrame();
SceneManager.LoadScene(sceneIndex, LoadSceneMode.Single);
}
我的问题是它无法正常工作,前几个场景似乎一开始还不错,但是一旦剩下大约 3 个场景,它就会不断重新加载相同的场景。我不确定我有什么问题,任何帮助将不胜感激!下面还添加了完整的脚本。谢谢!
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;
public class ForestGameManager : NetworkBehaviour
{
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;
private bool _isInitialized;
[Header("Forest Scenes")]
[TextArea(1, 1)]
public string forestSceneNotes = "Please place all Forest Scenes after Forest Loader scene";
public int numberOfForestScenes;
private float sceneCountdownLength = 15.0f;
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()
{
//DontDestroyOnLoad(this.gameObject);
StartCoroutine(DoInitForestGameManager());
StartCoroutine(DoInitServerNetworking());
fgmIndex = SceneManager.GetActiveScene().buildIndex;
firstForestSceneIndexNumber = fgmIndex + 1;
//Debug.Log("firstForestSceneIndexNumber Index is : " + firstForestSceneIndexNumber);
forestSceneTimer = GetComponent<ForestSceneTimer>();
}
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
}
InvokeRepeating("CheckAnimalCount", 0, 1f);
InvokeRepeating("CheckRemainingScenes", 0, 10f);
}
private void CheckAnimalCount()
{
if (forestAnimals.Count >= maxAnimalCount)
{
GameObject toDestroy = forestAnimals[0].forestAnimalGO;
forestAnimals.RemoveAt(0);
StartCoroutine(ExplodedMesh(toDestroy));
//yield return new WaitForSeconds(1f);
}
Debug.Log("Checking animal count");
}
private void CheckRemainingScenes()
{
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.");
}
//yield return new WaitForSeconds(1f);
Debug.Log("Checking remaining scenes");
}
}
private IEnumerator ExplodedMesh(GameObject toDestroy)
{
MeshExploder meshExploder = toDestroy.transform.GetChild(0).gameObject.AddComponent<MeshExploder>();
yield return new WaitForEndOfFrame();
toDestroy.transform.GetChild(0).gameObject.GetComponent<MeshExploder>().Explode();
yield return new WaitForEndOfFrame();
Destroy(toDestroy);
yield return new WaitForEndOfFrame();
}
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()
{
Debug.Log("Get Random Scene");
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, (firstForestSceneIndexNumber + forestSceneIndexes.Count) - 1);
Debug.Log("First scene in list is " + firstForestSceneIndexNumber + " , the last one is " + ((firstForestSceneIndexNumber + forestSceneIndexes.Count) - 1));
yield return new WaitForEndOfFrame();
StartCoroutine(DoRemoveRandomSceneFromList());
// Load selected scene
StartCoroutine(DoLoadScene(randomSceneIndex));
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");
Debug.Log(forestSceneIndexes.Count.ToString() + " scenes are still left in the list");
}
}
private IEnumerator DoRemoveRandomSceneFromList()
{
// Remove selected scene from list
forestSceneIndexes.Remove(randomSceneIndex);
Debug.Log("Scene " + randomSceneIndex + " has been removed from the list.");
yield return new WaitForEndOfFrame();
}
private IEnumerator DoLoadScene(int sceneIndex)
{
yield return new WaitForEndOfFrame();
SceneManager.LoadScene(sceneIndex, LoadSceneMode.Single);
foreach (ForestAnimal animal in forestAnimals) // Spawn Animal Stored in the forestAnimals List
{
// print("Animal " + animal.forestAnimalName + "is still in the list");
//GameObject animalGO = (GameObject)Instantiate(animal.forestAnimalGO);
//NetworkServer.Spawn(animalGO);
Debug.Log(animal.forestAnimalName + " re-instantiated in new scene");
}
}
}
除了评论中提到的问题(您一定要仔细阅读)之外,问题在于您如何选择随机数。您没有从实际的索引列表中提取。它应该是这样的:
private IEnumerator DoGetRandomScene()
{
// Get scene name from random pick
int choice= Random.Range(0, forestSceneIndexes.Count - 1);
//here's where you convert your random choice into an actual scene index
int sceneIndex = forestSceneIndexes[choice];
yield return new WaitForEndOfFrame();
//If you want to remove the scene, just do it now
forestSceneIndexes.RemoveAt(choice);
// Load selected scene
StartCoroutine(DoLoadScene(sceneIndex));
}
注意,我没有修改你对协程的大部分使用,但正如评论中所指出的,你肯定有很多需要清理的地方。