[TIL][Unity] 확률 가중치 부여하기
확률 가중치
대부분의 게임에서 확률형 아이템을 사용할 때, 가치가 높은 아이템의 경우 일반 아이템에 비해 등장 확률이 작다. 이를 흔히 확률에 가중치를 부여했다고 한다. 오늘은 개인 프로젝트를 진행하며 해당 부분의 구현을 진행하였다.
private float GetWeightByRank(string rank)
{
switch(rank)
{
case "일반":
return 70.0f;
case "희귀":
return 25.0f;
case "전설":
return 5.0f;
default:
return 1.0f;
}
}
우선은 다음과 같은 메서드를 작성하였다. 유닛의 등급에 기반한 확률 가중치를 반환하는 메서드이다. 하지만 이 메서드만으로는 확률 가중치를 구현할 수 없다. 이렇게 반환된 값을 입맛에 맞게 가공하여 사용해야 한다.
public Unit DrawSingleUnit()
{
List<float> weights = new List<float>();
foreach(Unit unit in units)
{
float weight = GetWeightByRank(unit.unitData.UnitRank);
weights.Add(weight);
}
float totalWeight = 0;
foreach(float weight in weights)
{
totalWeight += weight;
}
float randomValue = Random.Range(0, totalWeight);
float cumulativeWeight = 0;
for(int i = 0; i < units.Count; i++)
{
cumulativeWeight += weights[i];
if(randomValue <= cumulativeWeight)
{
return units[i];
}
}
return null;
}
위 메서드는 유닛 하나를 랜덤으로 뽑는 메서드이다. 뽑기에서 등장할 유닛의 리스트에서 유닛의 등급을 받아와 기본 가중치를 받아오는 메서드를 실행하고 반환값을 가중치 리스트에 추가한다.
이후 totalWeight에 리스트에 포함된 모든 가중치를 더한 후 이를 이용해 랜덤값 randomValue를 뽑는다.
이 이후의 메서드 동작이 중요한데, cumulativeWeight의 경우 아래 반복문을 수행하며 unit 리스트에 접근, 각 유닛의 가중치를 더한 값이다. 즉, 계속해서 cumulativeWeight에 해당하는 가중치를 더해가며 randomValue값과 같아지거나 커지는 즉시 해당 unit을 반환한다.
위 사진은 200회 뽑기를 진행한 후의 결과이며 확률 가중치가 잘 적용됨을 알 수 있다.
뽑기 아이템의 경우 게임에서 양날의 검이라고 생각한다. 적당한 가챠 요소는 게임 플레이어로 하여금 흥미를 유발하며 게임사에 직접적인 금전적 이득을 불러오지만 이 점이 과도하거나, 유저가 일방적인 피해를 보는 구조로 악의적으로 구현한다면 그로 인한 역풍이 불어올 수 있음을 명심해야 한다.