天天看点

游戏编程精粹学习 - 可预测随机数

游戏编程精粹学习 - 可预测随机数

这是一种避免一次性生成所有内容的可预测随机数实现

原文使用了简易的随机数生成算法来生成,可以支持的最大数字是uint型的最大值4294967295。

文中提到的宏无限分解和微无限分解指的是用种子生成的随机结果再作为种子继续生成,细化到具体星球,植被等等。

这样当玩家在任意坐标区域内,只需要生成附近一小块的随机内容。这种做法也可以衍生到宝藏藏匿之类的实现上去。

这里测试代码使用unity自己的随机数来实现,也就是上面gif图的效果:

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

public class InfinityPlanet : MonoBehaviour
{
    public int x;
    public int y;
    public int probability = 70;
    List<GameObject> mCreatedCubeList = new List<GameObject>();


    void Update()
    {
        GetArea(x - 10, y - 10, x + 10, y + 10);
    }

    void GetArea(int beginX, int beginY, int endX, int endY)
    {
        for (int i = 0; i < mCreatedCubeList.Count; i++)
            Destroy(mCreatedCubeList[i]);

        var cacheState = Random.state;

        mCreatedCubeList.Clear();

        for (int x = beginX; x < endX; x++)
        {
            for (int y = beginY; y < endY; y++)
            {
                Random.InitState(x + y * (endX - beginX));

                var r = (int)(Random.value * 100);
                if (r % 100 < probability)
                {
                    var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    cube.transform.position = new Vector3(x, 0, y);

                    GalaxyBuild(r, cube);

                    mCreatedCubeList.Add(cube);
                }
            }
        }

        Random.state = cacheState;

    }

    void GalaxyBuild(int seed, GameObject go)
    {
        var cacheState = Random.state;
        Random.InitState(seed);
        var meshRenderer = go.GetComponent<MeshRenderer>();
        switch ((int)(Random.value * 100 % 3))
        {
            case 0://行星类型1
                meshRenderer.material.color = Color.red;
                break;

            case 1://行星类型2
                meshRenderer.material.color = Color.blue;
                break;

            case 2://行星类型3
                meshRenderer.material.color = Color.green;
                break;
        }

        Random.state = cacheState;
    }
}