为什么方法 return 的值应该是 return 随机值两次?

Why the method returns same value twice when it should return random value?

我正在制作 "build a tower" 游戏。在我的游戏中,我随机对立方体的侧面进行纹理处理,因此每个新立方体的每一面都有随机纹理。新立方体由附加到 "gamemanager" 个空游戏对象的脚本创建。这个 gamemanager 将 "TextureController" 脚本附加到每个新的立方体。该脚本负责创建纹理图集并为立方体的每一面拾取 UV。纹理加载并存储在 "TextureContainer" 脚本(也附加到 "gamemanager")中,该脚本具有 returns 随机纹理数组的方法。这很好用,并且按计划进行,除了一件事。第一个(基本)立方体不是由脚本创建的,而是由我设置的。它有一个不同的脚本(我们称之为 "baseCubeTextures"),它必须从 "gamemanager" 获取数组,创建自己的纹理图集并将 UV 设置到立方体的侧面。但问题是基础立方体的纹理始终与脚本创建的第一个立方体的纹理相同。为了更清楚一点:

GameManager 有一个脚本 GameManagerScript,其方法 CreateNextCube() 其中有一行:

playerCube.AddComponent<TextureController>().atlasTextures = GetComponent<TextureContainer>().getTextures(TextureSize.Ten);

它还附加了一个 TextureContainer 脚本。

TextureContainer 有一个方法 returns 随机纹理数组:

public Texture2D[] getTextures(TextureSize textureSize)
{

    switch (textureSize)
    {
        case TextureSize.Ten:
            textures[0] = textures10x6[Random.Range(0, textures10x6.Length)];
            textures[2] = textures10x6[Random.Range(0, textures10x6.Length)];
            textures[4] = textures10x6[Random.Range(0, textures10x6.Length)];
            textures[5] = textures10x6[Random.Range(0, textures10x6.Length)];

            break;
        case TextureSize.Eight:
            break;
        case TextureSize.Six:
            break;
        case TextureSize.Four:
            break;
        case TextureSize.Two:
            break;
        case TextureSize.One:
            break;
        default:
            break;
    }

    textures[1] = topBottomtextures[Random.Range(0, topBottomtextures.Length)];
    textures[3] = topBottomtextures[Random.Range(0, topBottomtextures.Length)];

    return textures;
}

基础立方体有一个大致如下所示的脚本:

public GameObject gameController;
private Texture2D[] atlasTextures = new Texture2D[7];
private Texture2D atlas;

Mesh mesh;
Vector2[] originalUVs;
private Rect[] atlasUVs;
// Use this for initialization
void Start()
{
    atlasTextures = gameController.GetComponent<TextureContainer>().getTextures(TextureSize.Ten);
// code for setting UVs
}

那么,为什么我从 getTextures() 方法获得了相同的纹理?是不是因为我几乎同时调用了这个方法(方法是在两个脚本的Start()中调用的)?我读到随机数生成器可能会发生这种情况。可以在这里以某种方式避免吗?

我需要完整的代码才能确定,但​​我认为这里的问题是附加在您的 GameManagerScript 上的 TextureContainer 脚本总是 return 相同的数组指针 "textures".

函数开头缺少 "Texture2D[] textures = new Texture2D[]"。

我知道这个问题已经得到解答,但我决定提供我的答案,因为我已经在处理这个问题,而当前的解决方案无法使随机数不重复。所以你可能会有 2 面具有相同的纹理。

下面的函数是用定时器做的,如果在2秒内没有产生随机数就停止。你可以随时改变它。 Unity 的随机 class 也有一个错误,有时 returns 相同的数字在函数中带有 while 循环。即使您也使用 System.Random class,此错误也存在于 Unity 中。

这两个函数应该可以让贴图的随机数不重复。

/// FOR textures10x6
    public List<int> newRandtextures10x6List = new List<int>();
    private void newRandtextures10x6Func(int arrayAmount)
    {
        System.Random a = new System.Random();
        int MyNumber = 0;

        //Reset
        newRandtextures10x6List.Clear();

        //2 seconds Timer. If it blocks exit 2 seconds exit
        System.DateTime startTime = System.DateTime.UtcNow;
        System.TimeSpan exitTime = System.TimeSpan.FromSeconds(2);

        bool quitRand = false;

        for (int i = 0; i < arrayAmount; i++)
        {
            do
            {
                if (System.DateTime.UtcNow - startTime > exitTime)
                {
                    quitRand = true;
                    Debug.Log("Time out Reached! ...Assigning 0 to it");
                    newRandtextures10x6List.Add(0);
                    break;
                }
                MyNumber = a.Next(0, arrayAmount);
            } while (newRandtextures10x6List.Contains(MyNumber));
            newRandtextures10x6List.Add(MyNumber);

            /* OPTIONAL. WILL QUIT THE WHOLE FUNCTION INSTEAD OF JUST THE WHILE LOOP
            if (quitRand)
            {
                break;
            }*/
        }
    }

    /// FOR topBottomtextures
    public List<int> newRandTopBottomtexturesList = new List<int>();
    private void newRandTopBottomtexturesFunc(int arrayAmount)
    {
        System.Random a = new System.Random();
        int MyNumber = 0;

        //Reset
        newRandTopBottomtexturesList.Clear();

        //2 seconds Timer. If it blocks exit 2 seconds exit
        System.DateTime startTime = System.DateTime.UtcNow;
        System.TimeSpan exitTime = System.TimeSpan.FromSeconds(2);

        bool quitRand = false;

        for (int i = 0; i < arrayAmount; i++)
        {
            do
            {
                if (System.DateTime.UtcNow - startTime > exitTime)
                {
                    quitRand = true;
                    Debug.Log("Time out Reached! ...Assigning 0 to it");
                    newRandTopBottomtexturesList.Add(0);
                    break;
                }
                MyNumber = a.Next(0, arrayAmount);
            } while (newRandTopBottomtexturesList.Contains(MyNumber));
            newRandTopBottomtexturesList.Add(MyNumber);

            /* OPTIONAL. WILL QUIT THE WHOLE FUNCTION INSTEAD OF JUST THE WHILE LOOP
            if (quitRand)
            {
                break;
            }*/
        }
    }

要测试 newRandtextures10x6Func() 函数,您可以使用:

 newRandtextures10x6Func(6);

for (int i = 0; i < newRandtextures10x6List.Count; i++)
{
    Debug.Log(newRandtextures10x6List[i]);
}

它将生成 6 个不同的数字,并且它们永远不会相同。

下面是您问题的其余代码。

public Texture2D[] getTextures(TextureSize textureSize)
    {

        switch (textureSize)
        {
            case TextureSize.Ten:

                //Generate the random numbers here with no repeated values
                newRandtextures10x6Func(textures10x6.Length);
                textures[0] = textures10x6[newRandtextures10x6List[0]];
                textures[2] = textures10x6[newRandtextures10x6List[2]];
                textures[4] = textures10x6[newRandtextures10x6List[4]];
                textures[5] = textures10x6[newRandtextures10x6List[5]];

                break;
            case TextureSize.Eight:
                break;
            case TextureSize.Six:
                break;
            case TextureSize.Four:
                break;
            case TextureSize.Two:
                break;
            case TextureSize.One:
                break;
            default:
                break;
        }

        //Generate the random numbers here with no repeated values
        newRandTopBottomtexturesFunc(topBottomtextures.Length);
        textures[1] = topBottomtextures[newRandTopBottomtexturesList[0]];
        textures[3] = topBottomtextures[newRandTopBottomtexturesList[1]];

        return textures;
    }