天天看點

遊戲程式設計精粹學習 - 可預測随機數

遊戲程式設計精粹學習 - 可預測随機數

這是一種避免一次性生成所有内容的可預測随機數實作

原文使用了簡易的随機數生成算法來生成,可以支援的最大數字是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;
    }
}