自定义随机权重,获取随机数

public class NewBehaviourScript : MonoBehaviour
{
    [System.Serializable]
    public class RandomConfig
    {
        public RandomConfig(int v,int w)
        {
            value = v;
            weight = w;
        }

        //返回值(不一定是int,float、枚举、类、结构体都可以)
        public int value;
        //随机权重
        public int weight;
    }

    [SerializeField] private List<RandomConfig> randomConfigList = new List<RandomConfig>();

    //---------

    private RandomConfig GetRandomValue()
    {
        //累加结算总权重
        int totalWeight = randomConfigList.Aggregate(0,(all,next) => all += next.weight);

        //在0~total范围内随机
        int cursor = 0;
        int random = Random.Range(0,totalWeight);
        foreach(var item in randomConfigList)
        {
            //累加当前权重
            cursor += item.weight;
            //判断随机数
            if(cursor > random)
            {
                return item;
            }
        }
        return null;
    }
}

 测试代码,随机10000次,记录每个随机配置被随机到的次数

    private void Start()
    {
        //定义随机参数权重
        randomConfigList = new List<RandomConfig>() {
            new RandomConfig(1,10),
            new RandomConfig(2,20),
            new RandomConfig(3,30),
            new RandomConfig(4,40),
            new RandomConfig(5,50),
        };

        //测试10000次,记录每次随机结果
        Dictionary<RandomConfig,int> testResultDic = new Dictionary<RandomConfig,int>();
        for(int i = 0; i < 10000; i++)
        {
            RandomConfig random = GetRandomValue();
            if(testResultDic.ContainsKey(random))
                testResultDic[random]++;
            else
                testResultDic[random] = 1;
        }
        //打印随机结果
        foreach(var item in testResultDic)
        {
            Debug.Log(string.Format("随机返回值 : {0}; 权重 : {1}; 随机到次数 : {2}",item.Key.value,item.Key.weight,item.Value));
        }
    }

测试结果,大致与权重一致


 扩展

每个随机配置有权重和可随机次数两个参数,权重影响随机概率,可随机次数表示能被随机到的次数上限。每次被随机到时,可随机次数减1,可随机次数为0时,从列表中剔除该随机数,以后不再参与随机。

public class NewBehaviourScript : MonoBehaviour
{
    [System.Serializable]
    public class RandomConfig
    {
        public RandomConfig(int v,int w,int c)
        {
            value = v;
            weight = w;
            count = c;
        }

        //返回值
        public int value;
        //随机权重
        public int weight;
        //可随机次数
        public int count;
    }

    [SerializeField] private List<RandomConfig> randomConfigList = new List<RandomConfig>();

    //---------

    private RandomConfig GetRandomValue()
    {
        if(randomConfigList.Count <= 0)
            return null;

        List<RandomConfig> resultList = new List<RandomConfig>();
        int totalWeight = randomConfigList.Aggregate(0,(all,next) => all += next.weight);

        int cursor = 0;
        int random = Random.Range(0,totalWeight);
        foreach(var config in randomConfigList)
        {
            cursor += config.weight;
            if(cursor > random)
            {
                config.count--;
                if(config.count == 0)
                    randomConfigList.Remove(config);

                return config;
            }
        }
        return null;
    }
}

 测试代码,分别随机1000、5000、10000次,记录每个随机配置被随机到的次数 

    private void Start()
    {
        //定义随机参数权重
        randomConfigList = new List<RandomConfig>() {
            new RandomConfig(1,10,1000),
            new RandomConfig(2,20,1000),
            new RandomConfig(3,30,2000),
            new RandomConfig(4,40,2000),
            new RandomConfig(5,50,1000),
        };

        //测试10000次,记录每次随机结果
        Dictionary<RandomConfig,int> testResultDic = new Dictionary<RandomConfig,int>();
        for(int i = 0; i < 5000; i++)
        {
            RandomConfig random = GetRandomValue();
            if(random == null)
                continue;
            if(testResultDic.ContainsKey(random))
                testResultDic[random]++;
            else
                testResultDic[random] = 1;
        }
        //打印随机结果
        foreach(var item in testResultDic)
        {
            Debug.Log(string.Format("随机返回值 : {0}; 权重 : {1}; 随机到次数 : {2}",item.Key.value,item.Key.weight,item.Value));
        }
    }

随机1000次

  

随机5000次

 

随机10000次