【问题标题】:Issues loading different levels randomly in Unity-3D在 Unity-3D 中随机加载不同级别的问题
【发布时间】:2019-03-16 14:38:43
【问题描述】:

我需要创建一个类(或多个类,如果需要),每次用户单击“下一步按钮”时随机加载关卡,一旦所有关卡都加载完毕,我们就会停止加载并关闭应用程序。我设置了代码,但仍然没有得到我正在寻找的结果:

  1. 用户点击按钮。

  2. 加载随机关卡

  3. 这些级别被存储在一个数组列表中

  4. 一旦用户完成该级别,他/她就会按下“加载下一个级别”按钮

  5. 加载下一个随机关卡

  6. 但首先,我们检查随机级别是否与之前不同。

  7. 如果不是,那么我们重复步骤 2-5,否则我们转到步骤 8

  8. 如果所有关卡都被访问过,那么我们退出应用程序

我遇到的问题是每次我点击播放时我的游戏都会加载相同的级别,并且在我完成当前场景后它不会进入下一个场景。这是我目前所拥有的:

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class SceneManager : MonoBehaviour
{
    public static bool userClickedNextButton;   //This flag is raised by the other classes that have the GUI button logic

    protected const int MAX = 2;

    private ArrayList scenesWereAlreadyLoaded = new ArrayList();

    void Update()
    {
        if (userClickedNextButton)
        {
                //by default the game starts at 0 so I want to be able to 
                //randomly call the next two scenes in my game. There will
                //be more levels but for now I am just testing two
                int sceneToLoad = Random.Range(1, 2);
                if (!scenesWereAlreadyLoaded.Contains(sceneToLoad))
                {
                    scenesWereAlreadyLoaded.Add(sceneToLoad);
                    Application.LoadLevel(sceneToLoad);
                }
                userClickedNextButton = false;

        }
        if (scenesWereAlreadyLoaded.Count > MAX) { Application.Quit(); }
    }
}

【问题讨论】:

    标签: c# unity3d random


    【解决方案1】:

    您使用您的关卡编号创建一个列表,然后删除当前加载的关卡。您重复此操作,直到列表为空。

    也不要使用ArrayList,它是非常古老且已弃用的类型,从 .NET/Mono 获得通用支持之前的时代开始。最好使用通用List<T>,它比ArrayList 类型安全且速度更快。

    using UnityEngine;
    using System.Collections;
    using System.Linq;
    using System.Collections;
    using System.Collections.Generic;
    
    [ExecuteInEditMode]
    public class SceneManager : MonoBehaviour
    {
        // not best idea to have it static 
        public static bool userClickedNextButton;
    
        protected const int MAX = 50;
    
        private List<int> scenes = new List<int>();
        void Start() {
            // Initialize the list with levels
            scenes = new List<int>(Enumerable.Range(1,MAX)); // This creates a list with values from 1 to 50
        }
        void Update()
        {
            if (userClickedNextButton)
            {
                if(scenes.Count == 0) {
                    // No scenes left, quit
                    Application.Quit();
                }
    
                // Get a random index from the list of remaining level 
                int randomIndex = Random.Range(0, scenes.Count);
                int level = scenes[randomIndex];
                scenes.RemoveAt(randomIndex); // Removes the level from the list
                Application.LoadLevel(level);
    
                userClickedNextButton = false;
            }
        }
    }
    

    【讨论】:

    • 当我尝试使用 IEnumerable 时出现错误。我是否缺少范围声明?
    • using System.Linq,尽管通过查看 MSDN 文档msdn.microsoft.com/en-us/library/… 很容易找到这一点
    • 您还应该添加using using System.Collectionsusing System.Collections.Generic,因为IEnumerable&lt;int&gt; (我更新了上面的代码,因为它不是一个int。但你真的应该首先学习基础知识继续写游戏之前的C#。知道如何导入或使用MSDN查找需要哪些命名空间是.NET编程最基本的
    • 抱歉,现在修好了。 Enumerable.Range 是。我没有 VS/Unity3D 在工作,所以我是从头顶写的
    • 从上面看我的评论。确保您的对象在场景加载时未销毁,并且场景不会创建此类新对象(寻找用于 Unity/MonoBehaviours 的单例模式)
    【解决方案2】:

    根据 Unity3D 文档 (http://docs.unity3d.com/Documentation/ScriptReference/Random.Range.html),range 返回一个介于 min(包括)和 max(排除)之间的整数,因此,在您的情况下,Random.Range(1,2) 将始终返回 1。

    试试这个

    int = sceneToLoad = Random.Range(1,3)
    

    【讨论】:

    • 在 Randon.Range(1,3) 还是在哪里?
    • 当然,当数组/列表的长度为 2 时,a 2 会抛出异常
    【解决方案3】:

    有一种更简单的方法可以做到这一点。您可以准备一个具有随机唯一编号的数组。当你想加载一个新级别时,只需增加数组的索引。 这是一个可以提供帮助的代码:(将此脚本附加到第一个场景中的空游戏对象)

      using UnityEngine;
      using System.Collections;
    
    
      public class MoveToRandomScene : MonoBehaviour {
      public Texture nextButtonTexture; // set this in the inspector 
      public static int[] arrScenes;
      public static int index;
      void Start () {
        index = 0;
        arrScenes = GenerateUniqueRandom (10, 0, 10); //assuming you have 10 levels starting from 0.
    
    }
    
    void OnGUI {
    // Load the first element of the array
        if (GUI.Button(new Rect (0,0,Screen.width/4,Screen.height/4),nextButtonTexture))
        {
        int level = arrScenes [0] ;
        Application.LoadLevel (level);
        }
    }
    //Generate unique numbers (levels) in an array
    public int[] GenerateUniqueRandom(int amount, int min, int max)
    {
        int[] arr = new int[amount];
        for (int i = 0; i < amount; i++)
        {
            bool done = false;
            while (!done)
            {
                int num = Random.Range(min, max);
                int j = 0;
                for (j = 0; j < i; j++)
                {
                    if (num == arr[j])
                    {
                        break;    
                    }
                }
                if (j == i)
                {
                    arr[i] = num;
                    done = true;
                }
            }
        }
        return arr;
    }
    

    }

    对于其他场景,您只需要创建此脚本并将其附加到一个空的游戏对象,只要您想加载一个新的随机场景:

    void OnGUI {
        if (GUI.Button(new Rect (0,0,Screen.width/4,Screen.height/4),nextButtonTexture))
        {
           if (MoveToRandomScene.index == 9) {
           // Load again your first level
           Application.LoadLevel(0);
        }
        // else you continue loading random levels
        else {
        MoveToRandomScene.index++;
        int level = MoveToRandomScene.arrScenes[MoveToRandomScene.index];
        Application.LoadLevel(level);
        }
     }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-29
      • 1970-01-01
      • 1970-01-01
      • 2014-11-12
      • 2013-03-31
      • 2021-11-06
      • 2021-01-01
      • 1970-01-01
      相关资源
      最近更新 更多