본문 바로가기

프로그램/유니티 스크립트 소스

[유니티 스크립트 소스] 가중치 랜덤 추출기

728x90
반응형

가중치를 주어서 랜덤값을 추출하는 소스입니다.

 

1. 클래스

클래스 : 가중치 랜덤 추출
public static class WeightedRandomizer
{
    public static WeightedRandomizer<R> From<R>(Dictionary<R, int> spawnRate)
    {
        return new WeightedRandomizer<R>(spawnRate);
    }
}

public class WeightedRandomizer<T> 
{
    private static System.Random _random = new System.Random();
    private Dictionary<T, int> _weights;

    public WeightedRandomizer(Dictionary<T, int> weights)
    {
        _weights = weights;
    }

    public T TakeOne()
    {
        var sortedSpawnRate = Sort(_weights);
        int sum = 0;
        foreach (var spawn in _weights)
        {
            sum += spawn.Value;
        }

        int roll = _random.Next(0, sum);

        T selected = sortedSpawnRate[sortedSpawnRate.Count - 1].Key;
        foreach (var spawn in sortedSpawnRate)
        {
            if (roll < spawn.Value)
            {
                selected = spawn.Key;
                break;
            }
            roll -= spawn.Value;
        }

        return selected;
    }

    private List<KeyValuePair<T, int>> Sort(Dictionary<T, int> weights)
    {
        var list = new List<KeyValuePair<T, int>>(weights);

        list.Sort(
            delegate (KeyValuePair<T, int> firstPair,
                        KeyValuePair<T, int> nextPair)
            {
                return firstPair.Value.CompareTo(nextPair.Value);
            }
            );

        return list;
    }
}

 

2. 데모

using System.Collections.Generic; 
using UnityEngine; 

public class DemoWeightedRandomizer : MonoBehaviour 
{ 
    enum Card { Bronze, Silver, Gold, Diamond } 
    private Dictionary<Card, int> m_Cards = new Dictionary<Card, int>(); 
    [SerializeField] private Card m_Card = Card.Bronze; 
         
    void Start() 
    { 
        m_Cards.Add(Card.Bronze, 90); 
        m_Cards.Add(Card.Silver, 6); 
        m_Cards.Add(Card.Gold, 3); 
        m_Cards.Add(Card.Diamond, 1); 
    } 
         
    void Update() 
    { 
        if (Input.GetKeyDown(KeyCode.S)) 
        { 
            m_Card = WeightedRandomizer.From(m_Cards).TakeOne(); 
            Debug.Log(m_Card.ToString()); 
        } 

    } 

    public static class WeightedRandomizer 
    { 
        public static WeightedRandomizer<R> From<R>(Dictionary<R, int> spawnRate) 
        { 
            return new WeightedRandomizer<R>(spawnRate); 
        } 
    } 

    public class WeightedRandomizer<T>
    { 
        private static System.Random _random = new System.Random(); 
        private Dictionary<T, int> _weights; 

        public WeightedRandomizer(Dictionary<T, int> weights) 
        { 
            _weights = weights; 
        } 

        public T TakeOne() 
        { 
            var sortedSpawnRate = Sort(_weights); 
            int sum = 0; 
            foreach (var spawn in _weights) 
            { 
                sum += spawn.Value; 
            } 

            int roll = _random.Next(0, sum); 

            T selected = sortedSpawnRate[sortedSpawnRate.Count - 1].Key; 
            foreach (var spawn in sortedSpawnRate) 
            { 
                if (roll < spawn.Value) 
                { 
                    selected = spawn.Key; 
                    break; 
                } 
                roll -= spawn.Value; 
            } 

            return selected; 
        } 

        private List<KeyValuePair<T, int>> Sort(Dictionary<T, int> weights) 
        { 
            var list = new List<KeyValuePair<T, int>>(weights); 

            list.Sort( 
                delegate (KeyValuePair<T, int> firstPair, 
                            KeyValuePair<T, int> nextPair) 
                { 
                    return firstPair.Value.CompareTo(nextPair.Value); 
                } 
                ); 

            return list; 
        } 
    } 
}

 

3. 결과

 

코더제로 유니티 스크립트 소스 가중치 랜덤 추출기
그림. 가중치 랜덤 추출기

 

728x90
반응형